WP-03 · Grounded generation

Pages without lies: grounding generated web pages in the owner's own words

Abstract. Generative page builders fail small businesses in a specific way: the output is fluent, plausible and wrong. It invents review counts, years in business, partner logos and "trusted by" figures, and it converges on the same anonymous layout for every trade. I describe a constrained generation pipeline that treats the owner's own words as the only admissible source of facts. A pre-generation completeness gate converts missing inputs into questions. A declarative rule layer forbids unsourced entities, numerals and known layout clichés. A post-render audit diffs every figure and proper noun on the rendered page against a verbatim record of what the owner said, and walks the DOM for structural violations. A multimodal critic scores full-page desktop and phone captures on ten lines, with the overall score defined as the minimum, inside a repair loop bounded at three rounds. I report the design, the measured cost per critique round, the test evidence and the failure modes that remain.

Written 2026-10-23 from the build routine, the finishing-check and critic source, release notes and test runs on a non-client server. Worked examples use test businesses with made-up details. Model vendors, prompts and infrastructure are described by role, not by name.

1. The failure mode

A language model asked for "a website for a pizzeria in Mineola" has no access to the facts that make a local business page useful: the real hours, the real phone number, the dish people actually drive for, the year the owner opened, if the owner wants to say it at all. It does have a strong prior over what such pages usually contain. Left alone, it fills every gap from that prior. The result is a page that reads well and asserts things nobody said: "4.9 stars from 187 reviews", "serving the community since 1998", three icon cards, a stats row, a testimonial from a customer who does not exist.

Two properties make this worse for small businesses than for software companies. First, the owner is the only source of truth and is usually reached by text, so every invented fact either goes unnoticed or costs a round trip to correct. Second, the cost of a false claim on a local business page is real: a wrong price, a phantom discount or an invented review is a consumer protection problem, not a styling problem.

A design report assembled on 2026-10-22 from 61 sources summarized the pages the system was producing at the time as "anonymous, not ugly". The layout was competent and indistinguishable from any other trade's page. The same week, an internal review of an early insurance agency page found an invented "coverage at a glance" card, pill badges, eyebrow labels, a stat row and "call to confirm" hours. The pipeline described here is the response.

2. Threat model for a generated page

I treat the builder model as a capable but untrusted author. Its outputs are checked against an explicit model of what may appear on the page and where each claim came from. The failure classes fall into four groups:

Each class is assigned to the earliest layer that can see it. Most are covered twice: once by an instruction the builder is told to obey, and once by a measurement taken after the page exists. Fig. 1 shows the coverage.

Fig. 1 · Defense in depth

Defense in depth: which layer catches which failureA matrix of twelve failure classes against four layers: the completeness gate, the rule layer in the build routine, the mechanical post-render audit, and the multimodal critic. Most classes are caught by at least two layers.FAILURE CLASSGATEbefore generationRULESin the build routineAUDITmechanical, post-renderCRITICmultimodal, scoredMissing inputInvented number, price, percentInvented partner, carrier, brandGeneric headlineCard grid or stats rowFake button, dead linkBanned phrase, long dashHours: “call to confirm”No real photoBroken script, sideways scrollPhone first screenNot the owner's voiceA FAILURE IS CAUGHT AT THE EARLIEST LAYER THAT CAN SEE IT. MOST CLASSES ARE COVERED TWICE: ONCE BY RULE, ONCE BY MEASUREMENT.
Twelve failure classes against four layers. Open rings are rules the builder is told to obey; filled marks are checks that measure the page: the gate before generation, the audit and the critic after it.

3. Layer 0: the completeness gate

Before any design work, the builder checks whether it has five inputs, each in the owner's own words:

  1. what the business does and for whom, in one or two sentences;
  2. the services or products the owner wants on the page, as a list;
  3. one reason a customer picks this business over the one down the street, as a sentence the owner said;
  4. phone, address and real hours;
  5. at least one photo, or an explicit "no photo yet".

The gate has two thresholds. With one input missing, the builder proceeds with what is real, omits the gap from the page and lists the missing item as a question in its summary. With two or more missing, it does not build at all: it returns the questions only, and the assistant asks the owner. Requests with a higher blast radius, such as a rebuild of an existing site, a custom domain or more than six services, trigger a fixed set of five numbered questions before anything is generated.

The design principle is stated in the routine itself: a page with real content and no design beats a designed page with made-up content. The gate makes that trade explicit and moves the cost of missing information to the cheapest point in the pipeline, a single text message, instead of a correction after the owner has already seen a wrong page.

4. Layer 1: the rule layer

The build routine (version 2.0.0, rewritten on 2026-10-22) opens with hard rules written as short imperatives, placed before any procedural step so they dominate the builder's context. They encode the threat model directly:

Before writing markup, the builder produces a design specification next to the page: a section list with one job and one layout per section, the two faces, the type scale, the spacing scale, the four color roles, and where each photo goes. Only sections on that list may be built. The specification is later handed to the critic, so the plan and the result can be compared.

Rules alone are not sufficient. A model that has been told not to invent numbers will still, occasionally, invent numbers. The remaining layers exist because the rule layer is a prior, not a guarantee.

5. Layer 2: the post-render audit

The finishing check runs after the page is written and served. It is deterministic and does not use a language model. It opens the page in a headless browser, scrolls to the bottom so that scroll-triggered reveals have completed, and takes full-page captures at desktop width and at 390 px. It then runs three families of checks.

Runtime checks. Script errors in the console, sideways scroll at phone width, entrance-animation budget (one hero entrance plus one staggered list), long-running animations, buttons and links with no real target, and the presence of the owner-editable region markers described in section 8.

Structural checks, by DOM walk. A single evaluation inside the page returns card grids, stats rows, centered headings outside the hero, the typefaces actually in use, the heading face, gradients, box and button corner radii, the image count and the page height. These map one to one onto the structural rules, so a violation is a measurement, not an opinion.

Provenance checks, by diff. The owner's own messages about the business are copied verbatim into a known-file, never augmented with details the builder filled in. The audit extracts every number, price, percent and "N+" figure from the rendered text and flags any that does not occur in the known-file. It applies the same test to company names, using a short list of insurers and suppliers plus a capitalized-phrase pattern ending in Insurance, Group, Inc, LLC, Mutual or Financial. It also flags "call to confirm" hours, middle dots between facts, arrows at the end of links, banned phrases, repeated lines, and any page with no image that was not explicitly marked as type-only.

unsourced(page) = { x in numerals(page) ∪ entities(page) : x not in known_file }
deliver(page)   ⇐  unsourced(page) = ∅  ∧  structural_violations(page) = ∅  ∧  critic(page) ≥ 7

Findings are graded. FIX lines block delivery. NOTE lines are reported but do not block: two-digit numbers, a styled word inside the headline and a page taller than 3,000 px are NOTEs, because each has legitimate uses. When the DOM walk itself fails, the audit says so in a NOTE and those rules are skipped rather than silently passed.

Fig. 2 · Grounding data flow

Grounding data flowThe owner's verbatim messages become a known-file. The planned sections become a design spec. The rendered page becomes desktop and phone captures. A numeral and entity diff checks the page against the known-file, and a multimodal critic sees captures, spec and owner's words together.Owner's messagesverbatim, by textSection planone job, one layoutper sectionRendered pagedesktop + 390 pxfull-page capturesKnown-fileowner's words only,never filled inDesign specsections, 2 faces,5-step type scaleScreenshotsafter a full scroll,so reveals are doneVERIFIERSEntity + numeral diffevery figure and propernoun must appear inthe known-fileMultimodal criticsees both captures,the spec and theowner's words; flagsanything unsourcedUnsourced claimblocks deliveryas a FIX lineEditable regionsmarked spans becomethe owner's edit form
Three artifacts are produced alongside the page: the known-file, the design spec and the captures. The deterministic diff and the critic both read them; only marked regions flow into the owner's edit form.

6. Layer 3: the multimodal critic

Some failures are not mechanically detectable. Whether a headline is generic, whether the first phone screen shows what the business is, whether the page sounds like the person who runs it: these need a reader. The critic is a separate, fast multimodal model that receives both full-page captures, the design specification and the known-file, and is instructed to judge the page as the owner would on a phone in five seconds: bluntly, specifically, without praise.

It scores ten lines from 0 to 10:

  1. Specific. Could a competitor paste the headline and first section onto their site unchanged?
  2. Real. Is there a real person, place or piece of work above the fold?
  3. Honest. Any invented numbers, prices, partners, reviews or stats, judged against the owner's words?
  4. Layout variety. Repeated consecutive layouts, or more than one card grid?
  5. Centered and badged. Everything centered, pill badges, eyebrow labels, icon squares, stat rows, a highlighted headline word?
  6. Type. Two faces at most, a clear scale, left-aligned, readable on the phone capture without zoom?
  7. Color. One accent, buttons and links only, no gradients or glow?
  8. Length. Does every section earn its place?
  9. Phone. Is the first 390 px screen the business name, what it does and a call or text button, with nothing cut off?
  10. Owner voice. A person who runs this business, or software marketing?

The overall score is the minimum of the ten, not the mean. This is deliberate: a page that is beautiful and contains one invented review is not a 9, it is a page that cannot ship. The critic returns the score, up to five concrete FIX lines naming what to change and where, and exactly one KEEP line naming the single best element, so that repair does not destroy what already works. Two context rules are appended: a page explicitly marked as type-only scores 7 on the photo line when the hero is clean type, and the yellow markers that flag sample content for the owner are not to be judged as design.

The critic runs on infrastructure configured for zero data retention, with hidden reasoning disabled. That last setting is operational, not stylistic: with images attached and reasoning enabled, the critic spent its entire 500-token budget on hidden reasoning and returned no text, a failure reproduced twice before the setting was changed.

7. The bounded repair loop

The builder runs the finishing check itself, in the same shell, after writing the page. If the check prints FIX or MISSING lines, the builder must fix every one and run it again, or explain in one line why the owner's own words require the flagged element. It may not argue with the critic. It must preserve whatever the KEEP line names.

Fig. 3 · Repair loop

The bounded repair loopBuild, mechanical audit and critic run in sequence. A score of 7 or better delivers the page. Lower scores send up to five fixes and one keep line back to the builder, for at most three rounds. If the critic cannot run, the audit alone decides.Buildbuilder modelwrites the pageAuditDOM walk, regex,browser checksCritic2 screenshots,10 scored linesscore≥ 7 ?Deliveredit link, owner form,one text to the owneryesno → up to 5 FIX lines and 1 KEEP line go back to the builder · round counter + 1BOUNDS3 rounds max, then ship with open issues listedcritic unavailable (exit 3)→ continue on the audit alone
Generation, measurement and critique in sequence, with a hard round cap and an explicit degraded mode when the critic is unavailable.

Three properties keep the loop well behaved:

Only when the page is clean, or the round cap is reached, does the check create the owner's edit link and form and produce the single line the assistant texts to the owner. A no-text marker exists for tests so that test runs never message anyone.

8. Owner-editable regions

Grounding is not a one-time property. Hours change, specials change, prices change. Rather than regenerate the page, the builder marks the regions the owner will update as typed, editable spans: a single value (for example hours), or a list whose direct children are items with named fields (name, description, price, time, day, note). At least three such regions are required, only for content the owner will really change, and never for contact details or legal text. Marked text stays plain, with no links or bold inside, so edits cannot break markup.

From those marks the finishing check generates a private edit form. Edits write back into the same spans, so the page's structure, typography and contact details are outside the owner's edit surface and outside the model's reach after delivery. Sample content that still needs the owner's confirmation stays highlighted in yellow until the owner replaces it.

Fig. 4 · Worked example, test business with made-up details

A type-only page for a test pizzeria, built from the owner's words

4a The rebuilt page after the rule rewrite: type-only hero in the owner's words, left-aligned, one accent, a plain list instead of cards, no invented figures.

The private edit form for the same page, with specials, descriptions and prices

4b The edit form generated from the marked regions. The owner changes specials and prices; layout and contact details are not editable here.

9. Evidence

All runs below were on a non-client test server, with the no-text marker present so no owner was messaged.

Before the rewrite. A third rebuild of an insurance agency page, built from a one-line request with no owner facts, failed try one of three. The audit fired on a 25-second animation, numbers absent from the owner's words (two phone numbers, a street number and a ZIP code, because the request contained none of them), "call to confirm" hours, an arrow at a link end, two banned phrases, eight entrance effects plus two stagger groups, no photo, five pill buttons and corner radii of 999, 22 and 14 px. The DOM walk found one six-card grid. The critic scored it 2 and named a fake summary card, no real photo, a generic headline, badges and a stat row, and the card grid; it kept the call button under the headline on mobile.

After the rewrite. A test pizzeria page built end to end through the assistant, with no owner photo, produced a type-only hero in the owner's words, left-aligned, no pill badges or eyebrows, no icon squares, no card grid, no stats row, no invented numbers or partners, one accent on the call button only, two faces, a plain list for the menu and an address block with a map link, at about 1,900 px tall. On re-run after the type-only and sample-marker fixes, the critic scored it 3 and named exactly the three remaining problems a human reviewer had also found: the tagline restated three times in different words, two editable rows whose placeholder text read as filler, and a contact block nested inside another box.

Cost. Each critique round sends two full-page captures of roughly 450 KB, the specification and the known-file, for 5,600 to 7,200 input tokens and 330 to 360 output tokens, and cost $0.0007 to $0.0009 at list price, measured from the response usage. Three rounds per page cost under 0.3 cents. Latency was 3 to 8 seconds per round.

The honest summary of the evidence: the pipeline produces a real improvement in structure and honesty, and it does not yet produce pages that pass its own critic. That is the intended direction of failure. A page that ships with its open issues listed is recoverable; a page that ships with an invented review is not.

10. Limitations and open problems

11. Claim table

ClaimEvidenceConfidence
The build routine opens with hard rules forbidding invented numbers, prices, partners, ratings, reviews and testimonials.Build routine v2.0.0, hard rules sectionhigh
A completeness gate requires five owner-supplied inputs and halts with questions when two or more are missing.Build routine, step 0high
Pages are capped at six sections, two typefaces and one accent color.Build routine, hard ruleshigh
The routine was rewritten on 2026-10-22 after a 61-source design report diagnosed the pages as "anonymous, not ugly".Release notes and Queva working paperhigh
The audit diffs numbers, prices, percents and N+ figures against the owner's verbatim messages.Finishing check release noteshigh
The critic scores ten lines and reports the lowest as the overall score; 7 or better passes.Critic source and release noteshigh
Repair is bounded at three critic rounds per page, after which the page ships with open issues listed.Critic source (round cap) and build routine step 4high
A critic round cost $0.0007 to $0.0009 at list price, with 5,600 to 7,200 input tokens.Release notes, measured on two test pageshigh
A pre-rewrite insurance page scored 2 with about a dozen mechanical FIX lines; the rebuilt test pizzeria page scored 3.Release notes, test evidencehigh
Scoring by the minimum of ten lines is harsh; a pass mark of 6 or an average was left as an open decision.Release notes, open pointsmedium
Reworded tagline repeats are caught only by the critic, not the audit.Release notes, open pointshigh

12. Sources