Rebuilding This Blog
A Next.js 16 blog built almost entirely with Claude Code
I recently rebuilt my personal blog from scratch. What started as a simple Next.js + MDX setup evolved into a feature-rich platform with dynamic OG images, RSS feeds, syntax highlighting, and more. The interesting part? Almost every feature was implemented through pair programming with Claude Code.
The Long Road Back to Blogging
This isn't my first blog. I used to write extensively on LiveJournal back in the day—long-form posts about life, ideas, and whatever I was working on. That era of personal blogging felt different: more intimate, more exploratory, less performative.
Over the years I tried to restart blogging several times. There were attempts in the early 2010s that never stuck. The most recent was in 2024, when I spun something up, wrote a post or two, and let it languish. Each time, the friction of maintaining a blog won out over the desire to write.
This time feels different, partly because of the tools and partly because of where I am professionally. Working on AI agents daily gives me plenty to write about, and the writing itself helps me think more clearly about the problems I'm solving.
Why Not Hugo or Jekyll?
The conventional wisdom for a developer blog is to reach for a "batteries included" static site generator like Hugo, Jekyll, or Astro. These are mature tools with extensive theme ecosystems, plugin architectures, and years of community wisdom baked in.
I went the other direction: Next.js with MDX, building features incrementally from scratch.
Why? A few reasons:
Learning by building. I wanted to understand every piece of the stack. When something breaks, I know where to look. When I want to change something, there's no framework magic to reverse-engineer.
Flexibility over convention. Static site generators optimize for common cases with themes and plugins. But I wanted specific behaviors—like the way code blocks render, or how the table of contents tracks scroll position—that would require fighting against a framework's opinions.
Modern React patterns. Next.js 16 with the App Router and React 19 represents the current state of React development. Building a blog with it is a way to stay fluent in patterns I use professionally.
Incremental complexity. I started with the absolute minimum: routes, MDX rendering, basic styling. Each feature—tags, RSS, OG images, syntax highlighting—was added when I wanted it, not because a template included it.
The tradeoff is real: I've written code that Jekyll provides out of the box. But the code is mine, it does exactly what I want, and I understand it completely.
The Tech Stack
The blog runs on a modern JavaScript stack:
- Next.js 16 with the App Router and React 19
- MDX via
next-mdx-remotefor content - Tailwind CSS with the typography plugin for styling
- Shiki (via
rehype-pretty-code) for syntax highlighting - PostHog for privacy-friendly analytics
- Vercel for deployment
Content lives in MDX files with YAML frontmatter. The build process statically generates all pages, making the site fast and cheap to host.
The Migration Journey
The blog started on Cloudflare Pages using @cloudflare/next-on-pages, then migrated to OpenNext for Cloudflare Workers. Eventually I moved to Vercel, which simplified deployment significantly and resolved some security vulnerabilities in the dependency chain.
Features Built with Claude Code
Looking at the commit history, you can see most features were co-authored with Claude:
SEO & Discovery
- Sitemap generation
- RSS, Atom, and JSON feed support
- JSON-LD structured data
- Dynamic Open Graph images
Content Features
- Tagging system with
/blog/tag/[tag]routes - Reading time estimates
- Table of contents with active section highlighting
- Syntax highlighting with light/dark theme support
- Related posts based on shared tags
Custom MDX Components
<Callout>boxes for tips, warnings, and notes<Collapsible>sections for optional details- Copy-to-clipboard buttons on code blocks
- KaTeX math rendering (inline and display mode)
You can see these components in action in my Hello World post, which serves as a demo of MDX features.
Each of these was typically a single conversation: describe what I wanted, iterate on the implementation, commit and push.
The Claude Code Workflow
My typical workflow looked like this:
- Describe a feature I wanted (e.g., "add reading time estimates to blog posts")
- Let Claude explore the codebase to understand the existing patterns
- Review the proposed changes
- Commit with co-authorship attribution
The co-authorship shows up in the git log:
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
What worked well:
- Codebase awareness: Claude reads existing files before making changes, so new code matches existing patterns
- Incremental features: Each session focused on one feature, keeping changes reviewable
- Commit hygiene: Descriptive commit messages explaining what changed and why
What required human judgment:
- Architectural decisions: Choosing Vercel over Cloudflare, picking libraries
- Design choices: Layout, colors, typography
- Content: Writing the actual blog posts (well, mostly)
Claude Code as a Knowledge Work Tool
One realization from this project: calling Claude Code a "coding assistant" undersells what it actually is. Yes, it writes code. But it also:
- Researches: "What fields does a BlogPosting JSON-LD schema need?" gets me a complete answer faster than reading the schema.org docs
- Drafts prose: This very post was shaped through conversation, with Claude helping organize thoughts and fill in sections
- Explains concepts: When I'm unsure about a pattern, I can ask for an explanation tailored to my context
- Edits and refines: "Make this section more concise" or "does this flow logically?" works on prose just like code review works on code
The tool is really a general-purpose assistant for knowledge work that happens to have deep capabilities around code. The command line interface and developer-centric design shouldn't obscure that—if your work involves writing, researching, or thinking through complex problems, Claude Code is useful even if you never write a line of code.
Lines of Code
For context, here's the rough breakdown of what got built:
src/
├── app/ # Next.js routes and layouts
├── components/ # React components (Counter, Callout, etc.)
└── lib/ # Utilities (posts.ts, posthog.tsx)
content/
└── posts/ # MDX blog posts
The entire site is maybe 2,000 lines of TypeScript/TSX, plus the MDX content. Small enough to fit in context, large enough to be useful.
Takeaways
Building with an AI pair programmer changes the economics of side projects. Features that I might have skipped because they weren't worth the time investment (JSON-LD structured data, multiple feed formats, dynamic OG images) became easy wins.
The key is treating the AI as a collaborator rather than a replacement. I still made all the architectural decisions and wrote the content. Claude handled the implementation details, boilerplate, and research.
If you're building something similar, my advice: keep conversations focused, commit frequently, and don't be afraid to iterate. The git history is your documentation.