Rebuilding My Personal Site Live with Claude and Harper: A Developer's Take on Vibe Coding
One hour and thirty-four minutes, a personal website that hadn't been touched in two or more years, and a fresh attempt at building a CMS the way I actually want to write.
My personal site, austinakers.com, has been collecting dust since 2024. It's still in Nuxt 3. I've been meaning to update it for a while, partly because I want to write more again, and partly because the workflow for getting a post from my head to the internet currently involves Obsidian, copy-paste, a Git push, and enough friction that I just… don't.
So last Tuesday, my coworker Aleks and I jumped on a live stream and tried to fix that by rebuilding my site from scratch with a custom Markdown CMS sitting underneath it. Two people, one browser window, and Claude doing most of the heavy lifting. I'll say up front: I write code for a living. This isn't a "non-developer ships an app" story. It's the developer-side counterpart — what it looks like when someone who's perfectly capable of writing this code by hand chooses to pair with an AI instead, and what changes when you do.
Here's what happened, what worked, what didn't, and what I took away.
Start in the chat, not the editor
The first thing I did was open a Claude chat and ask it to help me build a project plan.
This is the part of my workflow that tends to surprise people. I don't go straight to Claude Code or jump into an editor. I spend the first chunk of any new project in a chat window, writing a plan together with Claude — the schema, the routes, the structure of the CMS, what npm package handles the Markdown parsing — before a single file gets created. By the time I open the terminal, the agent and I already agree on what we're building.
Aleks pushed back on this. He's been using Claude Code's CLI for everything, and a chat-first flow looked like overhead. He wasn't wrong, exactly. The unified approach would've been faster on a one-hour stream. But the chat-first pattern is a habit I picked up from my open-source workflow — I run a self-hosted Open WebUI with Ollama for a lot of side work, and that environment doesn't have the same agent-in-the-terminal experience. The chat-first habit just stuck.
What I'll say in its defense: the plan that came out was solid. Categories, slugs, tags, real-time fields, an upsert path for seeding content. I copied it straight into Claude Code and got moving.
npm create harper@latest
The scaffolding command is the same one Aleks used the week before: npm create harper@latest. React, TypeScript. Done in maybe 30 seconds.
I'll tell anyone who'll listen: TypeScript by default, especially for business applications. Frameworks and libraries are sometimes a different conversation. Application code in 2026 should have types.
A few packages I noticed in the install: @harperfast/vite-plugin (which I worked on, so hey), @harperfast/schema-codegen, Prettier, ESLint. I'd swap ESLint for Oxlint later and probably trim a couple of dependencies in favor of a closer-to-void-zero stack, but for a stream — fine as-is.
The schema is half the app
The schema for the blog table looked like this (loosely):
type BlogPost @table @export {
id: ID @primaryKey
slug: String @indexed
title: String
content: String
tags: [String]
publishedAt: Date
}
Two attributes did almost all of the work. @table defines the table inside Harper. @export automatically exposes a REST interface — GET /BlogPost, GET /BlogPost/:slug, POST, PUT, all of it, generated from the schema. No controller files. No router setup. The schema is the API.
This is the thing about Harper that I keep coming back to as a frontend engineer who occasionally has to do backend work: I don't have to think about backend boilerplate. I describe the data, and the endpoints exist. I add @export and the CRUD operations are real. That's it.
For context on what I mean by "frontend engineer who does backend" — I don't call myself full-stack because I think full-stack means working both ends at equal expertise. I'm an expert on the frontend; on the backend I can build what I need to build. Harper makes the second part feel a lot more like the first.
Two windows, one project
While Claude Code worked on the backend, I had Claude Design open in another tab generating the front-end mockups. Same pattern Aleks used the week before, and the same one that ended up working here: let the visual agent do the visual thing, let the code agent do the code thing, then merge.
Claude Design is genuinely better at design than Claude Code is. Claude Code on its own produces frontends that look fine — clean, functional, blandly competent. Claude Design produces frontends that look like a designer thought about them. On this stream, it pulled from Harper's design system without me asking and gave the site a kind of Harper-esque vibe out of the box. I'd specified useHarperDesignSystem: true in the prompt and forgotten about it; turns out that mattered.
When the design was ready, I downloaded the zip and dropped it into Claude Code with one instruction: merge this design into the Harper app. Done. The placeholder UI got replaced with the real thing.
Seeding broke. Claude fixed it. I learned something about myself.
The seeding script — the one that reads my Markdown files and imports them into the blog table — didn't work on the first try. Claude had written await tables.BlogPost.upsert(...), and Harper's runtime returned upsert is not a function.
I went hunting. Pulled up the docs. Considered the database.tables import path. Started typing out an import statement. Then I caught myself: this is the part of the stream where I'm supposed to be vibe coding, and I'm three deep in API references trying to do it manually.
I deleted what I'd typed, asked Claude to look at the error and fix it, and went back to talking on stream. A minute later the script ran clean. The records seeded. I checked the database and there they were.
This is the honest thing about being a developer using AI: the hardest part isn't the AI. It's not taking over. The reflex to just-do-it-myself is strong, and it's not always wrong, but on the stream it was costing me time. The whole point of the workflow is to delegate the parts that are mechanical and keep my brain free for the parts that require judgment. I keep relearning that lesson.
Deployment took less than a minute
Once the site was running locally, the deployment to Harper Fabric was: create a cluster, set three env vars (username, password, cluster URL), and run npm run deploy. Four minutes, maybe five. The first try threw an error on a resource file that was development-only and didn't need to ship — I commented out the import, re-ran, and it deployed clean.
This is the part I want every frontend engineer who's ever fought with deployment to hear. Pushing to Harper Fabric is not a separate exercise from building the app. It's the same project, the same config, three more values in .env, and a command. The thing on my screen and the thing on the internet are the same thing.
What we didn't finish, and why that's fine
The CMS UI exists but uses tab state instead of real routing, so there's no deep linking yet. I haven't wired up authentication, which means the CMS is sitting wide open on a local port (it's not deployed publicly yet — I'll add auth before that ships). The seeding still won't auto-pull my old content from the live site; for now it reads from local Markdown files, and I'll migrate the existing posts manually.
Read-time calculation is in, though. Claude added that without me asking, based on character count and average reading speed. Small surprise; appreciated.
The site isn't fully launched. I'm going to polish, add the authentication template we already have at Harper, and probably refactor the front-end into a bulletproof-React structure (features-based, not pages-based — closer to how we organize our own studio code). Once that's done, the final version will be live at austinakers.com.
What I took away
A few things stuck with me from this build.
The fundamentals matter more, not less. I said this on the stream and I'll say it here: AI is another layer of abstraction. Like every other layer of abstraction, it's amazing when you understand what's underneath it and dangerous when you don't. The folks who learn to ship with AI without learning what the AI is doing are going to hit a ceiling. The ones who understand the system underneath are going to 10x.
Chat-first vs CLI-first is a real choice, not a phase. I worked in a chat window first, then handed off to the CLI. Aleks would've stayed in the CLI the whole way. Both work. Pick the one that matches how you think, and stop apologizing for it.
Let the agent do the boring fixes. I caught myself manually debugging an upsert issue when I could've just described the error and let Claude handle it. That reflex — to grab the wheel — is the thing developers will have to unlearn most.
Schema-first design is a cheat code on Harper. The moment the schema was written, the API existed. I never wrote a route handler. I never wired up a controller. The schema was the contract, and Harper made it real.
If you want to build something like this yourself, the entrypoint is the same one Aleks used last week:
npm create harper@latest
Then open a chat with Claude and tell it what you're building. If you're a developer, you already know what to do from there — you just have to decide how much of it you want to do yourself.
The final version of austinakers.com will be live soon. I'll post when it ships. If you want to chat about the workflow, find me in the Harper Discord.






.webp)



.jpg)