Building a Personal Blog with Next.js 14: Choosing the Stack
Why I chose Next.js 14 for this website and what I learned from using the App Router.
Building a Personal Blog with Next.js 14: Choosing the Stack
Why Next.js?
Before building the site, I compared several popular approaches:
| Option | Strengths | Trade-offs | |---|---|---| | Next.js | Strong SEO, good performance, broad ecosystem | A learning curve | | Gatsby | Fast static output and many plugins | Longer build times | | Astro | Lightweight and framework-agnostic | A younger ecosystem | | Hugo | Extremely fast builds | Go template syntax |
I ultimately chose Next.js 14 for the following reasons.
1. The App Router
// app/posts/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map((post) => ({
slug: post.slug,
}))
}
export default async function PostPage({ params }) {
const post = await getPost(params.slug)
return <Article post={post} />
}
- Server Components reduce client-side JavaScript
- Streaming supports progressive rendering
- Layouts make shared page structure easier to maintain
2. Built-in performance tools
import Image from 'next/image'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function Hero() {
return (
<div className={inter.className}>
<Image
src="/avatar.jpg"
width={120}
height={120}
alt="Avatar"
priority
/>
</div>
)
}
- Image optimization provides modern formats and responsive sizing
- Font optimization self-hosts fonts and reduces layout shifts
- Bundle optimization removes unused code through tree shaking
3. Flexible data fetching
// Static generation with revalidation
export const revalidate = 3600
async function getData() {
const response = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 }
})
return response.json()
}
The framework supports several rendering modes:
- SSG — generated during the build
- ISR — regenerated incrementally
- SSR — rendered for each request
- CSR — rendered in the browser
Project structure
app/
├── layout.tsx # Global layout
├── page.tsx # Homepage
├── posts/
│ ├── page.tsx # Article index
│ └── [slug]/
│ └── page.tsx # Article page
├── resources/
│ └── page.tsx # Resource library
└── api/
└── submit/
└── route.ts # API route
components/
├── ui/ # Reusable UI
├── layout/ # Shared layout
└── features/ # Feature components
lib/
├── posts.ts # Article data
├── resources.ts # Resource data
└── utils.ts # Utilities
Performance results
The initial Lighthouse test produced:
- Performance: 95
- Accessibility: 98
- Best Practices: 100
- SEO: 100
Deployment
I chose Vercel for hosting:
npm i -g vercel
vercel --prod
The main benefits are zero-config Next.js support, a global CDN, preview deployments for every pull request, and integrated performance analytics.
Conclusion
Next.js 14 is a strong option for a modern personal website when you need:
- Reliable SEO
- Strong performance
- Flexible data fetching
- A mature ecosystem
The right stack is not the newest stack. It is the one that makes publishing and maintaining the site easier over time.