All Posts

March 10, 2025 · 1 min read

Building a Portfolio with Next.js 15 and Payload CMS

Next.jsPayload CMSArchitecture

Why Payload CMS?

When I set out to rebuild my portfolio I had one constraint above all others: I wanted full ownership of the data model with zero vendor lock-in. Payload CMS gives me a Postgres-backed, TypeScript-first CMS that lives inside my own Next.js app — no external service, no per-seat pricing.

App Router all the way down

Next.js 15's App Router lets me co-locate the Payload admin panel at /admin and my public site under a (site) route group in the same repo. Server Components handle all data fetching — no API layer, no useEffect waterfalls. The result is a site that feels instant because it mostly is.

Cloudflare R2 for media

Payload's S3-compatible storage plugin made wiring up R2 straightforward. Uploads go straight from the browser to the edge — no origin round-trip, zero egress fees.

Skipping Tailwind

I chose a hand-rolled CSS design system over Tailwind. One globals.css file with CSS custom properties for tokens, BEM-ish class names, and zero runtime overhead. It forces intentionality — every class has a reason.