
Building a Portfolio with Next.js, Supabase, and Claude Code
A walkthrough of how I built this portfolio site — the stack choices, the decisions I'm proud of, and the ones I'd revisit. Plus what it's like building a full-stack app with Claude Code as a pair programmer.

Building a Portfolio with Next.js, Supabase, and Claude Code
A walkthrough of how I built this portfolio site — the stack choices, the decisions I'm proud of, and the ones I'd revisit. Plus what it's like building a full-stack app with Claude Code as a pair programmer.
I built the site you're reading right now over the course of a few focused sessions, using a stack I'll defend: Next.js 15, Supabase, Tailwind, Cloudinary, and Claude Code. This post breaks down why each piece earned its place, what I'd change if I started over, and what surprised me about working with an AI pair programmer on a real project.
The stack, decided
Most "what I used to build my portfolio" posts read like a shopping list. I want this one to be a series of decisions — because every framework choice is a tradeoff, and the tradeoff is the interesting part.
Next.js 15 (App Router)
The portfolio is content-heavy and SEO-sensitive. Server Components let me fetch from Supabase directly on the server with no client-side waterfalls, while the App Router's file-based routing made nesting public + admin layouts trivial. The async params and searchParams in 15 caught me once or twice (you have to await them now), but the migration is small.
Supabase as the database + auth
I considered Postgres on Railway with a custom auth layer. I picked Supabase because:
- Row Level Security gave me a clean public/admin split with zero middleware code
- The TypeScript types generate from the schema, so the whole app is type-safe end-to-end
- The free tier is generous enough to ship without a payment method on file
The decision I'm happiest with is keeping section eyebrows and headings hardcoded while everything else flows through the database. "ABOUT" and "A few words about me" never need to be editable. The bio paragraph, the stats, the company logos — those do. Drawing that line cleanly saved hours of admin UI I would have built and never used.
Cloudinary for media
Cloudinary auto-transcodes videos for web, generates poster images from frame N, and gives me a CDN by default. The alternative — Supabase Storage — would have meant managing image transformations myself.
The Claude Code workflow
I built this site with Claude Code as a pair programmer. A few things I learned:
Plan before you prompt
The biggest unlock wasn't prompting Claude better — it was thinking better before opening the prompt. For each page, I'd write down:
- What sections does this page need?
- What data drives each section?
- What's editable vs. hardcoded?
- What's the fallback when data is missing?That outline turned into a single prompt that built the page end-to-end — types, queries, components, animations, error states. Without that outline, I'd be patching things piecemeal forever.
Verify each phase
Long prompts work better when broken into phases (DB → types → queries → components → verification). After each phase, I'd eyeball the output before moving on. When something was off, I caught it within minutes instead of debugging at the end.
What I'd revisit
If I started over, two things would change:
- I'd build the admin panel sooner. I deferred it to last and spent more time updating content via raw SQL than I should have.
- I'd generate Supabase types via the CLI from day one. Hand-written types worked, but kept drifting from the schema as I added columns.
What's next
The site itself is the start, not the end. I'll be writing here about the projects I ship, what I learn working with cloud-native architectures, and the decisions that go into real software. If you found anything here useful, the best thing you can do is tell me what you're building.
Found this useful?
What's next
Keep reading
Or take a look at what I've been building lately.