How I Built This Blog with Next.js, Prisma, and Vercel
Why Build From Scratch?
Building a personal blog in 2026 might seem like a solved problem — there are plenty of platforms out there. But I wanted something I fully owned, could customize endlessly, and that would push me to work with modern tools. So I built this one from scratch.
What followed was a genuinely educational exercise: fighting Vercel's serverless constraints, migrating databases mid-project, and making deliberate decisions about the writing experience. This post is a record of all of it.
The Tech Stack
Every technology choice here was deliberate. Here's what powers the blog and why each piece earned its place:
Next.js 16: Handles routing, SSR, and API routes in one place. The App Router with server components means most pages ship with zero client-side JavaScript.
React 19 : The latest version, with server components baked in at the framework level.
Prisma 7 : A type-safe ORM that makes database queries feel like writing TypeScript, not SQL. The schema is the single source of truth for the data model.
Neon PostgreSQL: Serverless Postgres that scales to zero — perfect for a blog that doesn't need a database running continuously.
TipTap: A headless rich text editor built on ProseMirror. Powers the admin panel with formatting, code blocks, images, and links — no Markdown required.
Tailwind CSS 4: Utility-first styling that keeps the design consistent without writing a single custom CSS class from scratch.
Vercel: Push to GitHub, and the site is live. Deployment takes seconds.
The Architecture
The blog has two distinct sides: a public-facing front end and a private admin panel.
The public side is entirely server-rendered. When you visit a post, Next.js fetches the content from the database on the server and sends back fully rendered HTML. No loading spinners, no layout shifts — just content arriving immediately.
The admin panel lives behind authentication powered by NextAuth. It includes a dashboard with post statistics, a full post editor with live preview, and management for categories and tags. Only I can reach it.
The data model is intentionally simple: Users write Posts, which belong to Categories and carry multiple Tags. Prisma manages all the relationships and provides type safety across every query — a compiler error before a runtime bug every time.
The Interesting Challenges
Migrating from SQLite to PostgreSQL was the biggest hurdle. I started with SQLite for simplicity — no database server to manage, just a file on disk. But Vercel's serverless environment doesn't support persistent file storage. The migration meant swapping the Prisma adapter, regenerating migrations, and switching to Neon's serverless driver that connects over HTTPS instead of traditional TCP.
Lesson learned: Start with the production database from day one. Prisma abstracts away most SQL differences, so the migration wasn't technically difficult — but it added unnecessary steps to the deployment process that could have been avoided entirely.
Making the build work on Vercel required marking data-fetching pages as dynamic. Next.js tries to pre-render pages at build time by default, but that fails when the database isn't reachable during the build step. Setting dynamic = "force-dynamic" on pages that query the database solved this cleanly.
Choosing TipTap over Markdown was a deliberate authoring decision. TipTap gives a familiar writing experience — bold, italic, headings, code blocks, images — without requiring authors to know Markdown syntax. The content is stored as HTML, which means it renders exactly as written, no parsing step required.
What I'd Do Differently
Two things stand out in hindsight.
First, begin with PostgreSQL from day one instead of SQLite. The migration itself wasn't difficult thanks to Prisma, but it added avoidable friction to an already-complex deployment setup.
Second, set up image uploads to cloud storage early. Right now, cover images are URLs — which works, but a proper upload flow with drag-and-drop would make the authoring experience significantly smoother. It's the kind of thing that's much easier to wire in from the start than to bolt on later.
The Result
A fast, minimal blog that I fully control. No platform lock-in, no monthly fees beyond the domain, and a codebase I can extend whenever I want.
The entire project is open source. You can fork it, adapt it, break it, and make it your own.