Ship a Real Website with Claude Code, GitHub, and Cloudflare (Cheap and Reliable)
A copy-pasteable kickstart your AI coding agent can run end to end: scaffold an Astro site, push to GitHub, auto-deploy on Cloudflare Pages, and gate it with a smoke test. For about the price of the domain.
The cheapest, most durable way to put a website on the internet has not changed much: publish static files to a CDN, version them in Git, and let a build run on every push. What has changed is who does the wiring. You can now describe the site to an AI coding agent and let it run the whole sequence, while you click the two things only a human can click. This is the stack I use to ship the sites behind this publication, written so you can hand it to your agent and get a live site on your own domain in an afternoon. The interesting part is not the tools, it is the division of labor: the agent runs the whole sequence, and you own only the two steps it genuinely cannot do.
Why this is cheap and reliable
The reliability comes from the shape of the system, not from spending more. A static site is a folder of HTML, CSS, and a little JavaScript. Served from a CDN, it has no server process to patch, no runtime to crash, and no database to corrupt. Your repository is the source of truth, GitHub holds it, and Cloudflare rebuilds and ships the site on every push. The most common way to break it is a typo in your own content, and the test gate below catches the usual cases of that before they go live.
| Layer | Choice | Why |
|---|---|---|
| Framework | Astro (static output) | Ships plain HTML and CSS with almost no JavaScript by default, so pages are fast and there is no server runtime. Content is Markdown or MDX in your repo. |
| Source control | GitHub (private repo) | Free, durable, and the thing Cloudflare watches. A bad change is one git revert away. |
| Hosting | Cloudflare Pages | Free tier includes a global CDN, automatic HTTPS, and Git-connected auto-deploy. Static hosting on a CDN is about as reliable as the web gets. |
| Package manager | pnpm | Fast, disk-efficient installs. npm or yarn work too. |
| Quality gate | Build check plus a Playwright smoke test | Catches broken builds, missing images, and dead links before they reach visitors. |
Alternatives that also work: Cloudflare Workers if you need server-side logic, Vite with React, Svelte, or Vue if you want a single-page app, and Netlify or GitHub Pages instead of Cloudflare Pages. The principles carry over. This guide picks one good default path so your AI does not have to deliberate.
Prerequisites (one-time, about 15 minutes)
Three free accounts: a GitHub account, a Cloudflare account, and a domain name if you want a custom address (Cloudflare Registrar sells them at cost, which is the cheapest honest option). You can skip the domain and use the free *.pages.dev subdomain.
Four tools on your machine: Node.js LTS (version 20 or newer), pnpm (npm install -g pnpm), Git, and the GitHub CLI (gh, then gh auth login once, so your agent can create the repo without you clicking through the web UI). Plus your AI coding agent of choice.
Verify them:
node --version # v20 or higher
pnpm --version
git --version
gh auth status # should say "Logged in"
Give this to your AI
Once the prerequisites are in, paste the block below to your agent. Replace the bracketed values first.
I want to create and deploy a website. Use this stack and follow it exactly:
- Framework: Astro (static output)
- Source: a NEW PRIVATE GitHub repo named [my-site]
- Hosting: Cloudflare Pages, auto-deploy on push to main
- Package manager: pnpm
- Custom domain (optional): [yourname.com]
Site description: [one or two sentences about what the site is and who it is for].
Do this:
1. Scaffold a minimal Astro site with pnpm. Run it locally and confirm it builds.
2. Initialize git, create the private GitHub repo with the gh CLI, and push.
3. Add a publish gate: a "pnpm build" check and a minimal Playwright smoke test
that loads the home page, checks the title, and verifies every <img> loads
without a 404. Wire it so I can run it before every push.
4. Give me the exact Cloudflare Pages settings to enter (build command, output
directory, framework preset) and the DNS steps for the custom domain. I will
click those in the Cloudflare dashboard; you cannot do that part for me.
5. Write a short README with the local dev command, the deploy flow, and the
gotchas list.
Keep it minimal and working. Do not add features I did not ask for. After each
step, tell me what you did and what I need to do next.
The one thing your agent cannot do is click inside the Cloudflare dashboard to connect the repo and the domain. Everything else it can run. The steps below are what it follows, and what you click.
The steps
1. Scaffold and confirm it builds
pnpm create astro@latest my-site
# Choose a minimal or blog starter, TypeScript "Strict", install dependencies
cd my-site
pnpm dev # open the local URL; confirm the page loads
pnpm build # produces the static site in ./dist
pnpm preview # serves ./dist exactly as it will deploy
If pnpm build fails, fix it before going further. A green build locally is the contract Cloudflare relies on.
2. Put it on GitHub (private)
git init
git add -A
git commit -m "Initial site scaffold"
gh repo create my-site --private --source=. --remote=origin --push
That last command creates the private repo and pushes in one shot.
3. Connect Cloudflare Pages (you click this part)
In the Cloudflare dashboard, open Workers and Pages, click Create, then Pages, then Connect to Git. Authorize GitHub, select your repo, and set the build configuration:
- Framework preset: Astro
- Build command:
pnpm build - Build output directory:
dist - Node version: add an environment variable
NODE_VERSIONset to20(or newer) so the build matches your machine.
Click Save and Deploy. In a minute or two you have a live site at my-site.pages.dev. From then on, every push to main triggers a new deploy automatically.
4. Add your custom domain (you click this part)
In the Pages project, open Custom domains, click Set up a domain, and enter your domain. If its DNS is already on Cloudflare, the records are added for you. If not, Cloudflare gives you the exact CNAME or A records to add at your registrar, or you can move the domain’s nameservers to Cloudflare (free) and let it manage DNS. HTTPS is automatic.
5. The reliability gate
A site that deploys is not the same as a site that works. Add a small gate so a broken build or a missing image never reaches visitors.
pnpm add -D @playwright/test
pnpm exec playwright install chromium
Create tests/smoke.spec.ts:
import { test, expect } from "@playwright/test";
const BASE = process.env.SMOKE_URL || "http://localhost:4321";
test("home page loads with a title", async ({ page }) => {
await page.goto(BASE);
await expect(page).toHaveTitle(/.+/);
});
test("no broken images", async ({ page }) => {
await page.goto(BASE);
const srcs = await page.locator("img").evaluateAll(
(imgs) => imgs.map((i) => (i as HTMLImageElement).src).filter((s) => s.startsWith("http")),
);
for (const src of srcs) {
const res = await page.request.get(src);
expect(res.status(), `broken image: ${src}`).toBeLessThan(400);
}
});
Run it against your local preview before every push. The habit is the point: build green, smoke green, then push. I learned the “no broken images” check the hard way, so it is not optional in my own setup. A broken <img> does not fail the build; the page just renders with a gap, and the smoke test is the only thing that catches it cheaply.
Cost, honestly
Hosting is $0 on Cloudflare Pages’ free tier, which serves unlimited static requests and bandwidth, with a cap on the number of builds per month. Source control is $0 on GitHub, where private repos are free. The domain is the only guaranteed cost, roughly $8 to $15 per year depending on the extension. Everything else is free at this scale. If the site later needs a server, Cloudflare Workers plus a small database is the next step, and it stays inexpensive.
Gotchas (the things that actually bite)
These are real failure modes from running this stack. Tell your agent to watch for them.
- Wrong build output directory. Astro outputs to
dist. If Cloudflare is set tobuildorpublic, you deploy an empty or wrong site. Confirmdist. - Node version mismatch. Pin
NODE_VERSIONin the Pages environment variables so CI matches your machine. - Images that 404 silently. A broken
<img>renders as a gap, not a build error. The smoke test’s image check is what catches it. - Trailing-slash redirects. Static hosts often redirect
/pageto/page/with a 308. This is normal. If you script checks against your own URLs, follow redirects (curl -L). - Secrets in the repo. Never commit API keys. Put them in
.env, add.envto.gitignore, and set the real values as encrypted environment variables in the Cloudflare dashboard. - Committing
node_modulesordist. Both belong in.gitignore. The scaffold sets this up; confirm it. - Pushing a red build. The whole reliability story depends on never pushing when
pnpm buildis failing locally. Build first, push second.
The mental model to keep
You are not running a server. You are publishing files. Your repo is the source of truth, GitHub holds it, Cloudflare turns it into a fast global site on every push, and a small test gate keeps obviously broken changes from going out. That is the entire system, and it is cheap and reliable precisely because it is so small. Hand the prompt above to your agent, answer its questions, click the two Cloudflare steps when it tells you to, and you have a real site on your own domain.
Read Next
Stay in the loop
Get new posts delivered to your inbox. No spam, unsubscribe anytime.
Related articles
How to Align Claude Code With Your Codebase: 6 Techniques (2026)
Align Claude Code with your codebase and intent: plan mode, full context, project memory, and gates that cannot be skipped. Six practical techniques.
Coding Agents and Developer Economics on the Microsoft Stack (2026)
Coding agents are normal tool evolution, not rupture. The Microsoft business-apps read: execution compresses, but judgment and accountability do not.
Agentic Development with Claude Code: The Setup That Actually Works
Build a multi-agent development environment with persistent memory, quality gates, and automated pipelines. The setup that turned one CLI tool into a content factory.