Agent-Run AgencyBuild log · Alex Rowan · Guides

Guide · Alex Rowan · 11 Oct 2026

A static site generator for local lead-gen sites

Build log

My two rank-and-rent sites, medfordseptic.com and roanoketreeremoval.com, are plain static HTML generated by a small Python script from a JSON brief. No framework, no database, no build server. This guide is how that works and why I'd do it the same way again. Neither site has a renter yet and revenue is $0, so this is about the build, not results.

Why static

A local service site is a set of pages that rarely change: services, areas, guides, a cost guide, an FAQ. It doesn't need logins, a database or a CMS. Static HTML gives you:

  • Free hosting on Cloudflare Pages, with HTTPS and a global CDN
  • Fast pages without tuning, because there's nothing to run on the server
  • Nothing to patch or keep updated
  • A folder you can zip, diff and roll back

It also suits AI agents well. An agent can edit a JSON file and run a script. It doesn't need access to an admin panel, and the gated step, deploying, is a single action a person takes.

The brief is data

Everything about a site lives in one JSON brief:

  • The trade and the exact service names people search for
  • The main city and state, and the list of service areas
  • Guide topics, each tied to a question real customers ask
  • Cost-guide line items, each with a source and a date
  • FAQ questions and answers
  • The referral disclosure and the contact method

Keeping it as data means a fact fixed in one place is fixed on every page. It also means two versions of a site can be compared line by line, which is how I review what the agents changed.

The page plan

The generator turns one brief into 32 pages:

  • Home
  • A services index plus 5 or 6 service pages
  • An areas index plus 12 area pages
  • A guides index plus 6 or 7 guides
  • A cost guide, an FAQ, an About page and a Contact page

Measured on body text only, that's about 22,100 words on the septic site and about 20,300 on the tree site. Both launched at 18 pages and reached 32 the same day, once the brief had the full page list.

Templates, kept small

The script uses a handful of HTML templates: one base layout, and one each for a service page, an area page, a guide, and the index pages. Each template is plain HTML with slots for the brief's fields. Shared parts (header, navigation, footer, the referral disclosure) live in the base layout, so they're identical on every page and can't drift.

The output for each page is a folder with an index.html, so URLs come out clean without a file extension.

What the script writes besides pages

  • sitemap.xml with the final, clean URLs
  • robots.txt pointing to the sitemap
  • 404.html at the root, so unknown URLs return a real 404 on Cloudflare Pages instead of the homepage
  • _headers for caching
  • A favicon linked on every page

The checks before zipping

The agent runs the checks, and the zip only gets made if they pass:

  1. Every internal link resolves to a file in the output folder.
  2. Every page has a unique title and meta description, and one H1.
  3. No placeholder text is left anywhere in the output.
  4. No .md or .json files end up in the zip.
  5. The sitemap lists every page and nothing else.

After I deploy, one more check: the live sitemap should match the local copy. On both sites it matches byte for byte.

The sources file

Every factual claim in the brief, such as a price range, a permit rule or a local detail, also goes into a sources file with a link and the date checked. The generator doesn't read it, but I do when I review a brief. Facts that can't be verified are hedged in the copy or left out. One example: the county listed two different phone numbers for the same office, so my site lists neither.

The trap: thin area pages

A generator makes it easy to produce twelve area pages that only swap the town name. Those help nobody and can hurt the whole site. Each area entry in the brief needs something specific: which neighbourhoods it covers, local conditions that change the job, questions people there actually ask. If the agent can't find anything specific for a town, that town doesn't get a page.

Deploying

Deploying is gated: the agent builds, tests and zips, and I upload the folder to Cloudflare Pages myself. A redeploy is the same step. Because the whole site is one folder, rolling back means deploying the previous zip.

What I'd change

Plan the full page list in the first brief. Going from 18 to 32 pages on day one meant reworking navigation and the sitemap twice. And settle the brand name before generating anything, because it appears on every page.

A generator won't make a site rank. Sites take months to rank, and some never do. What it does is make the site consistent, cheap to host and quick to correct, so the time goes into content that's specific to the place.

Free

Get the AI Agent Team Playbook

The five agent briefs, the approval gates and the verifier routine from this build, in a free 9-page PDF. No promises of rankings or income.

Get the free playbook