BROKE → BUILT LOG #001 · EST. 2026 · BUILDING IN PUBLIC
Log #003 Jun 27, 2026 ~7 min Build With AI on $0

How I Built a Full Web App With AI Agents and $0 (Real Build Log)

Build a web app with AI agents for $0 — a real build log: every command, the dead end I killed, free Cloudflare hosting, no credit card.

No credit card. No paid hosting. No “free trial” waiting to auto-charge me at midnight. This is the full, honest log of how to build a web app with AI agents for $0 — and by the end of it there’s a real web app live on the internet, on a global CDN, with a marginal cost of $0.00. I’m going to show you every command, including the one expensive mistake I made halfway through.

I’ve been automating things since before GPT-2 was a headline. Scrapers, cron jobs, glue scripts, the works. The tooling kept getting better; my bank balance did not. So this is a build log written from exactly where I sit: broke, but not new at this. Today I direct the AI agents, they do the typing, and free infrastructure does the hosting.

The app is small on purpose: TinyBoard, a local-first kanban board that saves to your browser. No login. No backend. No database bill. Boring? Maybe. But it’s a real, shippable thing — and the workflow is the prize, not the app. The same loop builds bigger apps. This one just fits in a single post so you can watch the whole thing.

What “build a web app with AI agents” actually means

When I say build a web app with AI agents, I do not mean “ask a chatbot for a snippet and paste it.” I mean a directed loop with two people in it — except one of them isn’t a person:

  1. I decide what to ship and break it into ordered subgoals.
  2. The agent authors the actual files — components, styles, config — and runs the commands.
  3. I review and redirect — point warmer or colder, catch the dead ends, demand the real thing.
  4. We deploy to free hosting and verify it actually works in a browser.

The human is the director and the QA. The agent is the hands. That split is the whole game, and if you’ve never run it before, what an AI agent is in plain English will make the rest of this click.

The broke-builder stack — every single piece is free

Here’s the whole stack, top to bottom. Read it once so the commands later don’t surprise you:

  • The agent workhorse: a coding-plan-backed agent that can read/write files and run shell commands. I run mine on the GLM Coding Plan because it’s the cheapest way I’ve found to keep an agent grinding all day without a metered-token panic attack. (That’s my referral link — costs you nothing extra, and it helps fund the compute that builds this site.) The plan is genuinely load-bearing here: the entire app was authored by an agent running on it.
  • Framework: Vite + vanilla JS. No React tax for a board this size.
  • Source control: Git + GitHub, free tier.
  • Hosting: Cloudflare Pages — free, no card, global CDN. (GitHub Pages works too; I’ll show both.)
  • Cost so far: $0.00. I’ll keep repeating that number, because people don’t believe it the first time.

If you want the deeper rationale on which free AI tools are actually worth running in 2026, I broke that down in best free AI coding tools 2026. For now, just trust the stack and let’s build.

Step 1 — Scaffold the project (the agent runs the commands)

I don’t hand-type boilerplate anymore. I state the goal and let the agent run the scaffold. The literal instruction I gave was close to this:

Scaffold a Vite vanilla-JS app called tinyboard. Three columns: Todo, Doing, Done. Cards are draggable between columns. Persist board state to localStorage. No backend. Keep it one page.

The agent ran:

npm create vite@latest tinyboard -- --template vanilla
cd tinyboard
npm install

Then it wrote the column/card logic and the localStorage layer. The persistence ended up dead simple — which is exactly what you want for a $0 app with no database:

const KEY = "tinyboard.v1";

function saveBoard(state) {
  localStorage.setItem(KEY, JSON.stringify(state));
}

function loadBoard() {
  const raw = localStorage.getItem(KEY);
  return raw ? JSON.parse(raw) : { todo: [], doing: [], done: [] };
}

No server. No bill. The user’s own browser is the database. That single design choice is what pins this app at $0 forever — and it’s also the choice that nearly every “build an app” tutorial skips, because they’re quietly assuming you’ll pay for a backend later. Not here.

So far, so smooth. Then the agent made the mistake I’d been waiting for.

Step 2 — The dead end (a drag-and-drop rabbit hole)

This is the honest part, because build logs that hide the failures are useless.

The agent’s first instinct for drag-and-drop was to reach for a library. It pulled in a full DnD package, wired it up, and the bundle ballooned — for what is, functionally, “move a div to another div.” Worse, the thing fought the touch handlers on mobile. So I killed it:

Rip out the drag library. Use the native HTML5 drag-and-drop API. If touch is flaky, fall back to a tap-to-move-card interaction. Smaller bundle wins.

That’s the director’s job. The agent will happily ship the over-engineered version, because it runs. But “it runs” is not the bar. The native rewrite came in around 40 lines and produced a smaller, faster app:

card.addEventListener("dragstart", (e) => {
  e.dataTransfer.setData("text/plain", card.dataset.id);
});

column.addEventListener("dragover", (e) => e.preventDefault());

column.addEventListener("drop", (e) => {
  e.preventDefault();
  const id = e.dataTransfer.getData("text/plain");
  moveCard(id, column.dataset.status);
});

Here’s the lesson that repeats on every single build: the agent optimizes for “no errors.” You optimize for “actually good.” Those are two different jobs — and only one of them is ever going to be yours.

Step 3 — Make it not look like default AI output

The first visual pass looked like every generated app on earth: flat dark card, one accent color, system font. That’s a tell. And a tell is a trust-killer — the second a visitor clocks “AI made this and nobody cared,” you’ve lost them.

So I spent a real round on art direction and nothing else: a proper type choice, depth on the cards, a hover state with motion, a small hero header. You don’t need a designer for this. You need the discipline to refuse the first plain version and ask for a second, more intentional one. Direct the agent like an art director, not a ticket queue.

Step 4 — Build and verify locally

npm run build       # outputs to dist/
npm run preview     # serve the production build locally

Then I actually opened it in a browser and dragged cards around — by hand. HTTP 200 is not proof a user sees the right thing; you have to load the real build and watch it behave. Cards moved. State persisted across a refresh. Good. Now — and only now — ship it.

Step 5 — Deploy for free (Cloudflare Pages)

Two free routes here. I prefer Cloudflare Pages: the CDN is fast and there’s genuinely no card required. The agent ran:

git init
git add -A
git commit -m "TinyBoard: local-first kanban, $0 stack"
gh repo create tinyboard --public --source=. --push

Then deploy with Wrangler, Cloudflare’s CLI:

npm install -g wrangler
wrangler pages deploy dist --project-name tinyboard

That prints a live *.pages.dev URL. Done. Live on the internet, on a global CDN, for $0.

GitHub Pages alternative, if you’d rather keep everything in one place — set Vite’s base to your repo name and push to a gh-pages branch:

// vite.config.js
export default { base: "/tinyboard/" };
npm run build
npx gh-pages -d dist

I went deep on the Cloudflare side — DNS, custom domains, why there’s no card prompt — in free website hosting with Cloudflare, no credit card. If you’re choosing a host, read that before you commit to either one.

Step 6 — Verify the deploy actually landed

A push is not a deploy. So I opened the live pages.dev URL in a fresh browser — no cache, no localStorage — created cards, dragged them, refreshed. State held. Then I loaded it on a phone-sized viewport, because the touch fallback was the riskiest part of the whole build. It worked. Now I get to say shipped.

The rule I never skip: verify at the real failure mode and scale, not the happy path. For this app that meant mobile touch plus a cold browser with empty storage — the two places it was most likely to break. Test where it breaks, not where it shines.

What this cost, honestly

ItemCost
AI agent (coding plan)flat monthly, already paid for everything I build
GitHub repo$0
Cloudflare Pages hosting$0
Domain$0 (used the free pages.dev subdomain)
Marginal cost of this app$0.00

The only real cost is the coding plan — and that’s a fixed monthly that covers all my builds, not a per-app charge. Spread across everything the agent ships, the marginal cost of one more app is genuinely zero. That’s the number I promised you at the top, and it held.

What’s next

TinyBoard is intentionally tiny, but the loop scales without changing shape: direct → agent authors → you redirect → deploy free → verify. Next in this series I take the exact same workflow and bolt on a real data layer that’s still $0 — free-tier KV and edge functions — so the app can sync across devices without ever growing a hosting bill.

If you’re starting from nothing, the takeaway is simple. You do not need money to build a web app with AI agents. You need a clear goal, the discipline to reject the first lazy version, and a stack where every piece is free. The agent does the typing. You do the deciding.

And if you want the origin story — why I’m building all of this out in the open, broke, with AI agents doing the typing — start at day one of building in the open.


Some links may be referral links, always marked. Full disclosure →