Shipping a Developer Portfolio
How I used Next.js App Router, Tailwind v4, and shadcn/ui to build a production-ready developer portfolio

How I used Next.js App Router, Tailwind v4, and shadcn/ui to build a production-ready developer portfolio

"Abstract isometric 3D illustration of stacked application interface layers with modern UI design elements and data visualization on dark background"
Illustration by Perplexity Labs
4 posts in this series
Feel free to send us a message with your thoughts, or learn more about us!
Implement event-driven architecture with Inngest for instant API responses, automatic retries, and production-grade background processing. Real code from a live portfolio.
A multi-part series on building production-ready developer platforms: implementing CSP, rate limiting, INP optimization, analytics, and comprehensive security features.
A short, honest changelog: what shipped in the @dcyfr/ai v3.x line, what changed for people building on it, and what comes next — catching the blog up with work the package already produced.
Part 1 of 4
Series Background: This is the first post in the Portfolio series. . What started as a minimal portfolio has evolved into a production-ready platform with comprehensive security, featuring CSP headers, rate limiting, Redis analytics, background job processing, and extensive monitoring. This series documents the complete journey from initial build to production deployment.
I built a modern stack that prioritizes , typed data, and tiny bundles.
The Next.js makes server components the default:
I use client components only for theme toggling, the contact form, and sprinkle interactions.
src/
├── app/ # App Router pages and API routes
├── components/ # Reusable UI components
├── content/ # MDX blog posts with frontmatter
├── data/ # Typed static data (projects, resume)
└── lib/ # Utilities and helpersNext.js 15 + React 19
TypeScript (strict)
Tailwind CSS v4
shadcn/ui
Everything lands on Vercel with zero manual knobs. Analytics and Speed Insights are on by default, headers are set via vercel.json, and the whole thing stays fast.
Blog posts live as individual MDX files in src/content/blog/, parsed at build time with for frontmatter. This approach offers:
MDX content is rendered with and enhanced with rehype plugins for auto-linking headings and GitHub-flavored markdown.
Search and tag filtering are live. View counts are on the roadmap.
After shipping, I hardened the site for production with security, performance, and developer experience improvements.