The problem
For a small business, launching the website is the easy part. Afterwards pages go stale, the call to action stops fitting, and nobody has time to look at how visitors use the site. FWRD is my Dutch web company, and FWRD Studio is its product. It treats a website as something that keeps being worked on after launch.

How it works
A visitor describes their business in a chat box. An LLM pipeline turns that description into a structured site config, and the config renders into a client template that is then provisioned on Cloudflare. Building is free. You pay when the site goes live.
The system has three parts:
- The marketing site, fwrd.digital. Astro on Cloudflare Pages, with Sanity as a block-based page builder that includes two scroll-pinned storytelling blocks. It is also written for machine readers: a custom Astro integration generates
llms.txtandllms-full.txtfrom Sanity, and every page has a Markdown twin. The blog runs in six languages, translated by a model with parity checks against the Dutch source. - The hub, app.fwrd.digital. A SvelteKit app on Cloudflare Pages, plus a separate Cloudflare Worker for generation, chat, Stripe webhooks and crons, and a dedicated MCP worker. Data lives in Supabase Postgres with deny-by-default row-level security, and cross-tenant tests run in CI. Stripe handles subscriptions, credits, top-ups and dunning.
- Client sites. Each site is built from the “Maple & Stone” template, which uses Astro and Sanity and is driven by tokens. Brand theming is done with Tailwind v4
@themeCSS variables that are overridden per client at build time. Every document carries asiteId, and the template emits JSON-LD, including LocalBusiness. The builder warns when a colour choice fails WCAG contrast.

Provisioning is a durable Cloudflare Workflow: a GA4 property, a Pages project and a Turnstile widget per site, a GitHub Actions build of the template, then DNS and, for custom domains, a Cloudflare for SaaS hostname. Every step is get-or-create, so a failed run resumes where it failed. A cron watchdog flags sites that stay stuck in provisioning.
After launch
The site watches how visitors behave and turns that into suggestions, such as a sharper CTA, a new page for a search intent people keep arriving with, or archiving a page nobody reads. The owner approves each suggestion, or turns on autopilot and sets the limits on what it may change by itself.

Every FWRD site also gets its own MCP endpoint with four tools: generate_page, edit_page, publish_site and run_report. The owner connects it to Claude and asks for changes in plain Dutch. Each edit comes back as a card that shows its credit cost, and nothing goes live until it has been approved.

One of the first internal tools was mcp-page-gen, an MCP server of about 520 lines with three tools: Claude writes a schema-exact Sanity document, the server saves it as a draft, and it scaffolds the Astro page. After every Claude call the server estimates the cost from the reported token usage and throws the result away if it crosses a ceiling (50 cents by default), so page generation can’t run up the bill unnoticed.
Decisions worth explaining
- Receipts over model claims. A September audit showed that replies like “here is what I changed” were model-written free text, never checked against the actual diff. The fix renders the factual half of each reply from a server-side change receipt, adds no-op detection to the shared edit functions so an edit that changed nothing isn’t billed, and adds a claim guard that strips sentences the receipt can’t support. Its first version was overfit to the sentences it was tuned on; after a rework, a fresh test corpus showed it catching 43 of 50 rephrased false claims and keeping all 40 true sentences.
- Fail closed. If the Turnstile secret is missing, the form pipeline returns 403 on every submission. Other layers: a honeypot, size caps, an allow-list of fields declared on the Sanity form document, and a Sanity token that can only create submissions. Secrets never go into Sanity, because the dataset is publicly readable through GROQ.
- Deterministic gates for untrusted input. The prompt-injection check for the Coordinator agent, which reads inbound client messages, is deterministic: regex, keywords, length, and encoding checks after NFKC normalisation. A planned LLM classifier may only add advisory flags, because an injection that fools the agent can fool an LLM judge too.
Built with agents, reviewed by agents
FWRD started in May 2026 as a marketing site, an internal boilerplate and the page-generation server. For the first stretch I ran the company as a Paperclip organisation of 12 Claude agents. It had a CEO, a CTO, engineers, marketing roles and a Risk & Compliance council (cybersecurity, legal, accessibility) that could sign off, ask for fixes or block a release. I was “the board”, and a question only reached me when it was blocking, irreversible, needed human judgement and had no internal owner. The first commits in the hub repository are authored by the frontend engineer agent.
From June on, most of the build ran through Claude Code sessions that I directed. I made the product calls, approved merges, and handled the parts that need a human, like live payments and DNS. By September the hub was about 200k lines, with 122 migrations and 182 test files. A deep review that month sent about 60 finder agents across 30 subsystems and gave every finding two independent refuters, so only findings that survived both went onto the fix list.
My role
Founder and the only human engineer. I decide what the product does and how the system fits together, from the prompt box down to the Cloudflare and Supabase setup. I designed and ran the agent setup that builds and audits it, and I approve what ships.
Status
It is live. fwrd.digital serves the landing page, and app.fwrd.digital runs the Studio builder. Development is ongoing: in early October the hub was at v2.58, and a migration gate on deploys had just gone live. In June an audit of the go-live checklist against the code found the backend well ahead of the UI, so the launch plan became a concierge pilot in which I handled publishing by hand.
