Skip to main content
  1. Posts/

My Vibe Coding Workflow: How I Built This Site with Claude Code

Nick Liu
Author
Nick Liu
Building infrastructure for Facebook Feed Ranking at Meta. Previously at Walmart, Twitter, AWS, and eBay. MS in Computer Science at Georgia Tech.
Table of Contents
I rebuilt my portfolio site in a weekend using vibe coding with Claude Code . This is the real workflow — no hype, with honest tradeoffs.

Andrej Karpathy coined “vibe coding” in early 2025. The pitch: describe what you want in natural language, let the AI write the code, spend your time directing instead of typing. Collins Dictionary named it Word of the Year. Most takes on it are either breathless hype or dismissive eye-rolls. Here’s what it looks like when a senior engineer uses it for a real project.

Why I Rebuilt This Site
#

My old portfolio was stale. It was a basic Jekyll site I’d set up years ago and barely touched. I wanted something that:

  • Looked modern without me fighting CSS for a week
  • Had a blog for technical writing
  • Was fast and easy to deploy
  • Didn’t require a JavaScript framework for what’s essentially static content

I chose Hugo because I’d used it before and respected its speed. The Blowfish theme had the profile-style homepage I wanted, dark mode out of the box, and Tailwind built in. I didn’t evaluate 50 themes. I saw one that matched my mental picture and committed.

That kind of decision — knowing what you want and picking quickly — is something AI can’t do for you.

My Setup
#

The core of my vibe coding setup is straightforward:

  • Claude Code running in my terminal (Ghostty + tmux)
  • A CLAUDE.md file at the project root defining architecture, commands, and conventions
  • Plan Mode for anything non-trivial (more on this below)
  • Git on a feature branch so I can always roll back
The CLAUDE.md file is the most underrated part of this workflow. Think of it as the onboarding doc for your AI pair programmer. Mine specifies Hugo version, theme, config locations, deployment target, conventions. Without it, every conversation starts from zero.

What I Tried Before
#

Before settling on Claude Code, I’d spent time with Copilot for autocomplete and Cursor for structured edits. Both are good tools. But for this kind of project — scaffolding an entire site from scratch, wiring up a theme, writing CI — I needed something that could reason about the project as a whole rather than the file I had open. The full breakdown of why I landed on Claude Code is in my tool comparison.

The Real Workflow, Step by Step
#

A typical session looks like this:

  1. Describe the Goal

    Step 1

    I start by describing what I want in plain English — the outcome, not the implementation. Example: "Migrate the site from the default Blowfish config to a profile-style homepage with my work experience and projects."
  2. Plan Mode

    Step 2

    For anything touching multiple files, I use Plan Mode. Claude reads the codebase, proposes a plan, and I review it before any code gets written. This is where I catch bad architectural decisions early.
  3. Generate and Review

    Step 3

    Claude writes the code. I review every change. Not line-by-line — structurally. Does this match how Blowfish expects configs? Is this the right Hugo partial to override?
  4. Iterate and Fix

    Step 4

    The first pass almost never works perfectly. I run hugo server, see what's off, describe the issue. Sometimes I just fix it myself — design choices and CSS tweaks especially.
  5. Commit and Move On

    Step 5

    Feature works, I commit on the branch, move on. Small commits. Easy reverts.

Where AI Saved Me Hours
#

Some tasks are perfect for vibe coding:

  • CI/CD pipeline: I described my deployment target (Cloudflare Pages) and got a working GitHub Actions workflow in one shot. Setting up Hugo builds with the right version pinning would have eaten an hour of docs-reading.
  • Boilerplate content structure: The data files for experience, projects, and education — produced with the exact YAML schema Blowfish expects.
  • Theme configuration: Blowfish has dozens of params. Claude read the theme docs and generated a coherent params.toml matching the settings I described.
  • Shortcode usage: Instead of reading Blowfish’s shortcode docs for every component, I described what I wanted (“a timeline showing my workflow steps”) and got working markup back.

Where I Had to Take Over
#

Other tasks fall apart:

  • Design taste: “Make it look good” isn’t a useful prompt. I had to make specific choices about color schemes, spacing, what to highlight on the homepage.
  • Architectural decisions: Hugo’s data templates or content pages for work experience? That’s a structural choice with cascading consequences. I decided, then told the AI.
  • Debugging theme quirks: When Blowfish’s Hugo compatibility warning showed up, I had to read it and decide to ignore it. When the Jekyll .nojekyll file kept reappearing, I had to dig in myself.
  • Content and voice: The actual writing — blog posts, about page, project descriptions — that’s all me. AI can scaffold structure. It can’t know what I want to emphasize about my career.

My Prompt Patterns
#

A few patterns emerge after dozens of sessions.

Be specific about the outcome, vague about implementation:

“Add a blog section that shows the 5 most recent posts on the homepage with title, date, and a 2-line summary. Use whatever Blowfish shortcodes or partials are appropriate.”

Reference existing patterns:

“Create a new blog post following the same front matter format as my existing posts. The topic is terminal setup.”

Provide constraints:

“Update the CI pipeline but keep the build under 2 minutes. Don’t add any npm dependencies.”

Too vague:

“Make the site better.”

This generates random changes with no clear direction.

Too prescriptive:

“On line 47 of params.toml, change the value of showRecent to 5 and then on line 52…”

If you’re specifying exact line numbers, just edit the file yourself.

No context:

“Fix the bug.”

Which bug? What’s the expected behavior? What did you observe? AI needs the same context a human colleague would.

The Honest Tradeoffs
#

What I Gained
#

  • Speed on boilerplate: Tasks that are well-documented but tedious — config files, CI pipelines, data schemas — drop from hours to minutes.
  • Lower context-switching cost: I describe what I need and iterate, instead of bouncing between docs, Stack Overflow, and my editor.
  • Exploration: I tried Blowfish features I’d never have bothered with manually (charts, timelines, keyword lists), because the cost of experimenting was near zero.

What Felt Off
#

  • False confidence: Sometimes the generated code looks correct but has subtle issues — a Hugo partial that works in dev but breaks in production, or a config value that’s deprecated.
  • Dependency on review skills: If I didn’t already know Hugo, I wouldn’t catch the mistakes. Vibe coding amplifies existing knowledge. It doesn’t substitute for it.
  • Context limits: Long sessions lose context. I learned to keep them tight — one feature at a time.
Vibe coding doesn’t reduce the skill required. It moves where the skill is applied. Less typing, more reviewing — architectural calls, tradeoff judgment, catching subtle wrongness. Arguably harder than writing the code yourself.

Advice for Engineers Considering This Workflow
#

  1. Start with a CLAUDE.md file. Define your project’s architecture, conventions, and tools before you start prompting. Single highest-leverage thing you can do.

  2. Use Plan Mode for anything non-trivial. Don’t let the AI start writing code until you’ve agreed on the approach. This prevents the most expensive mistakes.

  3. Stay on a feature branch. Vibe coding generates a lot of changes fast. You need the safety net of easy reverts.

  4. Review structurally, not syntactically. Don’t read every line. Ask: does this change make sense architecturally? Does it follow the patterns already in my project?

  5. Know when to take over. Three rounds on the same issue and it’s faster to fix it yourself. The AI is a tool — not a pair programmer who will eventually “get it.”

  6. Keep sessions focused. One feature per session. Commit, then start fresh. Your AI assistant doesn’t get tired, but it does lose context.

For a deeper look at where vibe coding fits in professional engineering, see my post on why it amplifies senior engineers rather than replacing them.

This site is the proof of concept. Every page, every blog post, every CI pipeline came out of this workflow. It’s a genuinely useful tool when you know how to wield it.

Related

Claude Code vs Cursor vs Copilot vs Windsurf: An Honest 2026 Comparison

The AI coding tool landscape in 2026 has finally settled into four serious players: Claude Code , Cursor , GitHub Copilot , and Windsurf . I've used all four on real work. This is the honest comparison. Forget feature checklists. What matters is how each tool feels under real engineering work — the kind I do every day as a senior software engineer at Meta. I built this site primarily with Claude Code, but I’ve put serious hours into the others.

Vibe Coding Won't Replace Senior Engineers. It Amplifies Them.

The hype says anyone can code now. The reality: vibe coding changes *what* senior engineers do, not *whether* we're needed. And the gap between experienced and inexperienced developers is getting wider, not narrower. Collins Dictionary named “vibe coding” their Word of the Year for 2025. Search interest spiked over 6,000%. The narrative is seductive: describe what you want, AI writes the code, programming becomes as easy as having a conversation.

The Claude Code hooks docs are wrong. Here's what's actually on the wire.

I wrote a daemon to listen to Claude Code hooks. My first version read `$CLAUDE_HOOK_PAYLOAD` and logged empty bodies for two days straight. The payload was sitting on stdin the whole time. This post is the five gotchas I hit while wiring up ClaudeDeck — a Stream Deck plugin (a small program that runs inside Elgato’s Stream Deck app on the USB grid of programmable LCD keys) that talks to Claude Code over its hooks system. Claude Code is Anthropic’s terminal CLI for Claude — claude in your shell — and its hooks are user-defined scripts it spawns at certain points in a session (before a tool call, on session start, on prompt submit). My daemon is a long-running background process the plugin and the hooks both talk to over a local socket. None of the gotchas are exotic. All of them cost me hours. Each one is a place where the docs were either silent, ambiguous, or contradicted by tribal knowledge I picked up from other people’s projects.