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"
Photo by Perplexity Labs
3 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.
On January 13, 2026, Node.js released security patches for 8 vulnerabilities (3 HIGH, 4 MEDIUM, 1 LOW) affecting all active release lines. This post breaks down each CVE, explains who is affected, and provides actionable remediation guidance.
Series Background: This is the first post in the Portfolio series. Hardening a Developer Portfolio and Building Event-Driven Architecture with Inngest. 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 wanted to build a focused portfolio that is fast to load, easy to iterate on, and simple to host. After trying a few prototypes, I settled on a modern stack that prioritizes , typed data, and tiny bundles.
The Next.js represents a fundamental shift toward server-first rendering. Unlike the Pages Router, App Router makes server components the default, which means:
In this portfolio, I only use client components where it actually matters, theme toggling, the contact form, and a few 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 gray-matter for frontmatter. This approach offers:
MDX content is rendered with next-mdx-remote and enhanced with rehype plugins for auto-linking headings and GitHub-flavored markdown.
Search and tag filtering are now live without compromising the stack’s simplicity, and view counts remain on the roadmap.
This was just the beginning. After shipping, I spent time hardening the site for production with security improvements, performance optimizations, and developer experience enhancements.
Part 1 of 3