I Vibe Coded This Blog in Under a Day — Here's How
You're reading the proof.
This blog — the one you're on right now — was built by me and Claude Code in a single session. Not a weekend. Not even a full day. One sitting.
Here's the full build log.
The Starting Point
Ship or Kill was already a live site — a single-page sales page for my ebook at shiporkill.com. Built with Next.js 16, React 19, Tailwind CSS 4, deployed on Vercel.
No blog. No content pages. Just a sales funnel.
I wanted to add a blog for two reasons:
- SEO — ranking for "vibe coding" related keywords
- Content flywheel — every post drives traffic back to the book
The Approach
Instead of spinning up a separate blog (Astro, Ghost, Substack), I integrated directly into the existing Next.js app. Same repo, same deploy pipeline, same domain.
The stack:
- MDX files in a
content/blog/directory - next-mdx-remote for rendering MDX in server components
- gray-matter for frontmatter parsing
- rehype-pretty-code + shiki for syntax highlighting
- @tailwindcss/typography for prose styling
The Process
Step 1: The Plan
I opened Claude Code and described what I wanted:
Integrate a blog into this site. MDX posts in content/blog/,
listing page at /blog, individual posts at /blog/[slug],
tag filtering, RSS feed, sitemap, SEO metadata.
Claude Code read the existing codebase — the CLAUDE.md file, the component structure, the theme system — and proposed a plan. I reviewed it, tweaked a few things, and said "go."
Step 2: The Content Layer
First thing built: src/lib/blog.ts. Four functions:
getAllPosts()— reads all MDX files, parses frontmatter, sorts by dategetPostBySlug()— returns a single post with its contentgetAllTags()— deduplicated tag list with countsgetPostsByTag()— filtered list
Nothing fancy. fs.readFileSync + gray-matter. Runs at build time in server components.
Step 3: The Components
Six components, all built in sequence:
- BlogNavbar — adapted from the sales navbar, links to blog and book
- BlogPostCard — title, date, description, tags for the listing page
- TagList — clickable tag pills
- BlogPostLayout — the article wrapper you're reading in right now
- BlogNewsletterCTA — newsletter signup at the bottom of every post
- mdx-components — custom overrides for headings, code blocks, links
Step 4: The Routes
Three routes:
/blog— listing page with all posts/blog/[slug]— individual post withgenerateStaticParams/blog/tag/[tag]— filtered by tag
Plus /feed.xml (RSS) and /sitemap.xml.
Step 5: Polish
- BlogPosting JSON-LD for SEO
- Typography styles for prose content
- RSS autodiscovery link in the
<head> - Syntax highlighting with Shiki
What Went Right
- The CLAUDE.md file did most of the work. Because the project was already well-documented, Claude Code understood the theme system, the component patterns, and the design language. It didn't build a blog that looked foreign — it built one that matched.
- MDX in the repo is dead simple. No CMS to configure, no API to call, no database to provision. Write a markdown file, push to main, it's live.
- Static generation means zero runtime cost. Every page is pre-rendered at build time.
What Went Wrong
- Typography plugin conflicts. The
@tailwindcss/typographyprose styles needed customization to match the existing color tokens. Took some back-and-forth to get right. - Shiki bundle size. The syntax highlighting library ships a lot of language grammars. Had to be selective about which languages to include.
The Takeaway
A full blog — listing, individual posts, tags, RSS, sitemap, SEO, syntax highlighting — added to an existing Next.js site in one session.
Not because I'm fast. Because the tools are fast. I described what I wanted, reviewed the output, and shipped it.
That's vibe coding.
If you want to learn how to build like this, grab the book. It's the playbook I wish I had when I started.
Get vibe coding tips in your inbox
Build logs, tool reviews, and the prompts that actually work. No spam.