Building a Modern Blog with Next.js 14: A Complete Guide
After years of working primarily with backend technologies, I wanted to build a personal blog that showcased modern frontend skills. Here's what I learned building this site.
Why Next.js?
I chose Next.js for several reasons:
- Static Site Generation (SSG) - Perfect for blogs, generates HTML at build time
- Developer Experience - TypeScript support, hot reload, great tooling
- Performance - Automatic code splitting, image optimization
- SEO - Server-side rendering capabilities when needed
- Free Hosting - Deploy to Vercel or GitHub Pages for free
Architecture Overview
The blog follows a simple but powerful architecture:
├── app/ # Next.js 14 app directory
│ ├── blog/ # Blog routes
│ ├── layout.tsx # Root layout
│ └── page.tsx # Home page
├── components/ # React components
├── lib/ # Utility functions
├── posts/ # Markdown blog posts
└── public/ # Static assets
Working with Markdown
Blog posts are written in Markdown with frontmatter:
---
title: "My Post Title"
date: "2024-02-15"
excerpt: "A brief description"
tags: ["Next.js", "React"]
---
Your content here...
Processing is handled by gray-matter and remark:
import matter from 'gray-matter'
import { remark } from 'remark'
import html from 'remark-html'
export async function getPostData(slug: string) {
const fileContents = fs.readFileSync(`posts/${slug}.md`, 'utf8')
const { data, content } = matter(fileContents)
const processedContent = await remark()
.use(html)
.process(content)
return {
slug,
content: processedContent.toString(),
...data
}
}
Styling with Tailwind
Tailwind CSS makes it easy to create beautiful, responsive designs:
<article className="prose prose-lg dark:prose-invert max-w-none">
<h1 className="text-4xl font-bold mb-4">{title}</h1>
<div dangerouslySetInnerHTML={{ __html: content }} />
</article>
The @tailwindcss/typography plugin provides beautiful default styles for markdown content.
Dark Mode Implementation
Adding dark mode is straightforward with Tailwind:
const toggleDarkMode = () => {
const isDark = document.documentElement.classList.toggle('dark')
localStorage.setItem('darkMode', String(isDark))
}
Static Site Generation
Next.js generates static HTML for all blog posts at build time:
export async function generateStaticParams() {
const posts = getAllPostSlugs()
return posts.map((post) => ({
slug: post.slug,
}))
}
This means:
- Lightning fast - No database queries at runtime
- Great SEO - Search engines get full HTML
- Free hosting - Just static files
- Scalable - Handles any traffic
Deployment Options
Option 1: Vercel (Easiest)
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
Option 2: GitHub Pages
Add to next.config.js:
module.exports = {
output: 'export',
basePath: '/your-repo-name',
}
Then deploy with a GitHub Action:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm ci
- run: npm run build
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./out
Performance Results
The results speak for themselves:
- Lighthouse Score: 100/100
- First Contentful Paint: < 1s
- Time to Interactive: < 2s
- Total Bundle Size: ~80KB (gzipped)
Future Enhancements
The beauty of this setup is that it's easily expandable:
- Comments - Add Giscus (GitHub Discussions)
- Analytics - Integrate Vercel Analytics
- Search - Client-side search with FlexSearch
- Newsletter - API routes + email service
- CMS - Add Contentful or Sanity for non-technical editors
Lessons Learned
- Start Simple - Markdown files are perfect for a personal blog
- Optimize Images - Use Next.js Image component
- Measure Performance - Use Lighthouse regularly
- Mobile First - Design for mobile, scale up
- TypeScript - Catch errors early, better DX
The Code
The complete source code for this blog is available on GitHub. Feel free to use it as a starting point for your own blog!
Building this blog taught me that modern frontend development doesn't have to be complex. With the right tools, you can create something beautiful, fast, and maintainable in a weekend.