535commits on main1
18locale-driven site looks2
10nodes in the daily n8n pipeline3
6architecture decision records4
- git rev-list --count origin/main in the quicksite repo
- directories under templates/looks, excluding the two shared ones (_photos, _shared)
- n8n_workflows/daily_pipeline.json
- docs/adr in the quicksite repo
The problem
A small local business with a weak or missing website is a real lead, but only if someone shows them what a better site would look like. Doing that by hand, one business at a time, does not scale past a few a day.
QuickSite automates the whole path: find the business, check it is worth contacting, build a demo site from its real details, review that site, deploy it, and reach out.
What I built
A daily pipeline plus a dashboard to supervise it.
- Find and qualify: scrape Google Maps, enrich each result from Google Places, then score and filter the leads.
- Generate: Claude writes the site copy into a strict schema, which a Jinja2 look turns into a static site. There are 18 looks, driven by locale rather than hard-coded to one country.
- Review: rule-based checks cover content, data and pipeline state. Only when they flag something does an AI reviewer run.
- Deploy and reach out: the demo goes to Cloudflare Pages, and an SMS goes out with a suppression list so nobody is texted twice or after opting out.
Architecture
AI design
- Strict schema out: Claude returns site content as JSON validated against a Pydantic schema. A bad shape is retried, and a shared call budget caps the worst case at 7 model calls per site.
- Fallback: Claude is primary and Gemini is the fallback, behind one small protocol.
- Cheap reviewer, only when needed: the review model is the smallest Claude, and it runs only when the rule-based checks flag something.
- Honesty checks: fields that would invent facts are stripped, and long verbatim copying from the source listing is detected.
- Untrusted input: scraped listings and reviews are treated as untrusted personal data. They never go into the system prompt and are never logged.
- Spend cap: a monthly AI cap is checked before each call, and a skipped review is logged with which review it was.
How it was built
Specs first, then plans, then parallel implementers per task with a reviewer. A hook blocks destructive database and git operations, so those stay human-only. Technology and model choices are recorded as ADRs.
Tradeoffs
- No queue worker. Background work runs through FastAPI
BackgroundTasks. It is simple and enough at this volume, and it means a crash mid-run is not resumed automatically. - Deploy is narrower than the generator. The generator handles any business type in any country, but the deploy step still accepts dental leads only.
- Manual deploys. GitHub Actions is off for this repo, so merging to main does not deploy. Deploys are manual and need my explicit go-ahead.
Next case study
AI Engineering Lab