SGA Dental Partners
Site Builder — Fleet BlueprintEngineering & strategy brief · v3
9 sites · 26 modules
2026-08-20
00 — Start here

One builder for 260 practice brands — and the console to run them all.

This is the working brief for the SGA practice-website builder. We tore down nine best-in-class sites, separated every takeaway by discipline, turned them into a build-ready module list, and specced the control plane that turns a pile of static sites into a governed fleet. It is written to be handed to an engineer.

What this document is — and how to read it

Who it's for

The engineer(s) building the site builder and its management layer, plus the marketing lead who owns the outcome. Sections 02–03 are the evidence; 04–07 are the build.

The one decision it drives

Which patterns become default, automatic modules across all 260 sites — and in what order to build them, given that forms, analytics, and a site registry don't exist yet.

How it's organized

Sources → Findings by discipline → Modules → Control plane → Roadmap. Every finding links to the site it came from and to the module it becomes. Use the left outline to jump.

The headline

Eight of the nine sites leave their structured data incomplete. Only Aspen ships the full schema stack. Emitting it automatically on every site is our cheapest, biggest edge.

Disciplines
DES Design — look & feel
SEO Classic search ranking
AEO AI answer-engine citation
 
CRO Convert visits → patients
TRU Trust & credibility
PLT Platform & governance
Build status
In builder ships today, may need promotion
Upgrade exists but incomplete
Net-new does not exist yet
47
builder modules + 14 page recipes already shipping
0
working lead forms — every CTA is a #schedule anchor
0
sites with analytics — no funnel data to manage yet
8/9
sites leave the schema graph incomplete — Aspen is the exception
01 — Current state

What exists today, and the three things that don't

Grounded in the current codebase: the builder is a module + recipe assembler that emits static HTML (47 modules in site-builder/modules/, 14 page recipes). It is a solid foundation — but three capabilities the management layer depends on are literally absent.

No lead forms gap

Every CTA is an in-page #schedule anchor. There is no <form>, no backend, no submission store, and no leads table in packages/shared-types.

No analytics gap

No GA/GTM/CF beacon on any generated site. There is no traffic, conversion, or funnel data to roll up — so nothing to manage yet.

No site registry gap

project-registry.json tracks tooling, not practice sites. No per-site record of domain, host, code path, owner, forms, or analytics exists anywhere.

Schema is placeholder partial

One live JSON-LD block hardcodes telephone:'[PHONE]', ratingValue:'5.0', reviewCount:'100'. Two renderers (site-builder/ + design/sga-worker/) also duplicate assembly logic.

Consequence

Phase 0 has to come first

None of the patterns in this brief are measurable or governable until forms, analytics, and the registry exist. That is why the roadmap starts at Phase 0 and the control plane leads with the registry, not the dashboards.

02 — Sources

The nine sites we benchmarked

Four local-service exemplars plus five chosen to fill their blind spots — dental at DSO scale, booking UX, DTC intake funnels, answer-engine authority, and procedure AEO. Each card links to the live site and the exact pages audited. Discipline chips show where each site is strongest.

TendConsumer dental · 33 studios
hellotend.com ↗
DESCROTRU
Steal: emotional, barrier-dismissing hero ("6 months or 6 years… no judgment, ever"), inline insurance check, honest per-studio Google ratings.
Gap to beat: no FAQPage/AggregateRating schema; no OG cards.
CraftworkHome services · Next.js
craftwork.com ↗
AEOSEODES
Steal: a published /llms.txt, real FAQPage JSON-LD, programmatic neighborhood pages, no-PII cost calculator, named 3-year guarantee.
Gap to beat: zero financing/membership messaging.
Manchester RoofingLocal lead-gen · ~50 URLs
manchester-roofing.com ↗
SEOCROTRU
Steal: {service}×{city} page grid, phone-first sticky top+bottom bars, 5-field form + named lead magnet + callback SLA, founder E-E-A-T on every page.
Gap to beat: no FAQPage/Review/Service schema, no before/after gallery, no blog.
GroundworksMulti-brand at scale · 24 brands
groundworks.com ↗
PLTSEODES
Steal: one shared flagship theme + per-brand --brand-* tokens, a ZIP→location resolver front door, entity-linked @graph JSON-LD, pooled national rating, site-wide GTM + Optimizely.
Gap to beat: thin local NAP schema, no FAQPage.
Aspen DentalDental DSO · 1,000+ offices
aspendental.com ↗
AEOSEOCRO
Steal — the schema benchmark: full per-office JSON-LD (MedicalBusiness+geo+hours+AggregateRating+50 Reviews+OfferCatalog+FAQPage+Breadcrumb+ReserveAction), localized office pages, structured offer with expiry.
Gap to beat: no service×city pages, thin city hubs, client-only booking. We win on authenticity — a real local dentist per brand.
ZocdocHealthcare booking · aggregator
zocdoc.com ↗
CROAEOTRU
Steal: live time-slot chips on the result card, insurance filter before results, slot-first/PII-last flow, verified-review closed loop, multi-axis ratings, {procedure} cost in {city} guides with a Key-Takeaways box.
Gap to beat: availability hidden behind heavy JS; impersonal marketplace.
Audited: /dentists/blog cost guide · bot-blocked, documented-standard
Hers / HimsDTC healthcare · quiz funnel
forhers.com ↗
CROTRU
Steal: the question-first, contact-last intake funnel — one question per screen, progress bar, name personalization, de-stigmatizing copy, an earned "your plan" reveal, PII captured last. Reframes "book now" into "start your visit plan."
Gap to beat: opaque layered pricing, faceless care.
Audited: /weight-loss/faq · bot-blocked, documented-standard
HealthlineContent authority · AEO
healthline.com ↗
AEOSEOTRU
Steal: answer-first content (question-H2 → 1-sentence answer → bullets), a "Key Takeaways" box as the 2nd element, MedicalWebPage+MedicalCondition schema, and the "Reviewed by Dr. X, DDS · Updated {date}" E-E-A-T byline. Hub-and-spoke clusters.
Gap to beat: earns the AI citation but can't book — we win the citation and capture the patient.
InvisalignProcedure brand · locator
invisalign.com ↗
AEOPLTCRO
Steal: the ZIP→provider resolver encoded as a real SearchAction/EntryPoint (free AEO surface), worked $/mo payment examples instead of ranges, a no-PII "am I a candidate?" quiz, provider-tier badges.
Gap to beat: ships only FAQPage+Organization; blank locator results.
03 — Findings by discipline

What each discipline tells us to build

The same nine teardowns, reorganized by lens so the read is clean: from a Design perspective this, from an SEO perspective that, from an AEO perspective this. Each finding names the site it came from (linked) and the module it becomes (jump to the catalog).

DES

Design

Visual system, layout, typography, brand tokens, imagery, and motion — how a site looks and feels, and how one component library can produce 260 distinct brands.

Emotional, barrier-dismissing heroUpgrade

Lead with the patient's barrier (anxiety, shame about lapsed care), not the practice's credentials. Single repeated CTA, no competing buttons.

Seen on: Tend · Builds: Emotional Hero
One component set, per-brand tokensUpgrade

A single library re-skinned per practice via --brand-* CSS variables off practice_brand — Aspen & Groundworks both run hundreds of pages this way. Same skeleton, 260 skins.

Real-photo, light/white editorial systemStandard

Real project/space/team photography over stock, generous whitespace, one display + one text face. Matches SGA's light/white rule.

Seen on: Craftwork, Tend · Builds: design standard
Before/after smile galleryIn builder

Slider comparing outcomes — the dental analog to Craftwork's before/after rooms. Three variants already exist; promote to a default.

Seen on: Craftwork · Builds: Before/After Gallery
SEO

SEO

Crawlable structure — URLs and IA, metadata, sitemaps, internal linking, and programmatic pages — that wins classic search at scale.

Programmatic service × city pagesNet-new

A generator that spins /services/{procedure}/{city} pages from the practice's service list + geo radius — the growth engine Craftwork, Manchester, and Groundworks all run. Aspen notably lacks it (white space).

Clean tiered URLs + templated titles + breadcrumbsNet-new

Flat, keyword-only URLs, a {City} {Neighborhood} Dentist Near Me | {Brand} title formula, self-canonical, and BreadcrumbList on every page.

Seen on: Aspen, Manchester · Builds: part of Location Page Generator
Hub-and-spoke topical clustersNet-new

Per service line, auto-scaffold a pillar page + spoke pages on a fixed spine with a dense internal-link mesh — how Healthline concentrates topical authority.

Indexable per-provider profile pagesUpgrade

Give each dentist a real URL (bio, credentials, own slots, own reviews) instead of a buried grid tile — strong for E-E-A-T and "Dr. {Name} {City}" queries.

Seen on: Zocdoc, Aspen · Builds: Provider Profile Pages
AEO

AEO — answer-engine optimization

Structured data and answer-first content — how AI answer engines (Google AI Overviews, ChatGPT, Perplexity, Gemini) extract and cite a page. This is where the biggest, cheapest edge lives.

Full JSON-LD entity stackUpgrade

Auto-emit the complete graph from the practice record: Dentist/MedicalBusiness + geo + hours + AggregateRating + Review[] + OfferCatalog + FAQPage + Breadcrumb + ReserveAction. Aspen is the reference implementation to match.

Benchmark: Aspen · Builds: Schema Graph Generator
FAQPage schema on every FAQUpgrade

Single-source the visible accordion and the FAQPage JSON-LD so they never drift. Only Craftwork does this; Tend, Manchester, Groundworks & Invisalign all skip it.

Seen on: Craftwork · Builds: FAQ Block + schema
A published /llms.txtNet-new

A curated, LLM-readable positioning file + link index generated per practice. Only Craftwork ships one — first-mover advantage across 260 sites at near-zero cost.

Seen on: Craftwork · Builds: /llms.txt Generator
Answer-first content + Key-Takeaways boxNet-new

Question-H2 → 1-sentence answer → bullets, with a Key-Takeaways box as the 2nd element and worked $/mo cost examples — the exact shape AI Overviews lift.

Medically-reviewed E-E-A-T bylineNet-new

"Reviewed by Dr. X, DDS · Updated {date}" wired to real staff + MedicalWebPage/MedicalCondition schema and a sources/history block. A near-free YMYL trust win.

Seen on: Healthline · Builds: Medical Review Byline
ZIP box as a SearchAction entityUpgrade

Encode the "find a practice" ZIP field as a real SearchAction/EntryPoint JSON-LD — eligible for a Google sitelinks search box and a clean routing contract.

Seen on: Invisalign · Builds: SearchAction Resolver
CRO

CRO — conversion

Hero, CTAs, booking/intake, forms, offers, and insurance/financing — how a visit becomes a booked patient. Requires the Phase-0 forms backend to be real.

Question-first, contact-last intake funnelNet-new

One question per screen, progress bar, early name personalization, an earned "your visit plan" reveal, PII captured last as "so the office can confirm." PHI Phase-A, non-clinical question set.

Seen on: Hers/Hims · Builds: Intake Funnel
Live time-slot chips on the heroNet-new

Surface 4–6 real open times ("Next available: tomorrow 9:40") so a browse becomes a book at the list level; slot-first, PII-last. Needs the appointments feed; "request these times" fallback otherwise.

Seen on: Zocdoc · Builds: Live Slot Grid
Real 5-field lead form + submission storeNet-new

Low-friction intake with a named lead magnet + callback SLA, a honeypot, and a real backend that routes to a per-practice inbox. This is the Phase-0 foundation.

Seen on: Manchester · Builds: Lead Forms + Store
Sticky dual CTA + local click-to-callNet-new

A persistent mobile bar with Book + the practice's local tel: number — the single biggest mobile conversion lever, present on all four round-1 sites.

Seen on: all round-1 sites · Builds: Sticky Action Bar
Insurance check up-frontNet-new

A carrier-logo grid + "most PPO accepted" + plan lookup, answered before booking — removes the #1 dental objection at the decision point.

Seen on: Tend, Zocdoc, Aspen · Builds: Insurance Check
Financing / membership + worked $/mo costNet-new

CareCredit / in-house plan "from $X/mo" and worked payment examples (fees − insurance = balance → $/mo) instead of vague ranges. A top dental lever Craftwork omits.

Seen on: Invisalign, Aspen, Manchester · Builds: Financing Badge · Cost Estimator
Structured new-patient offer, with expiryNet-new

"$XX exam + X-rays / $0 with insurance" as a configurable component with a dollar value + expiration field so offers auto-expire and stay compliant.

Seen on: Aspen · Builds: New-Patient Offer Card
TRU

Trust & credibility

Reviews, ratings, provider authority, guarantees, and transparency — the credibility that closes a hesitant patient.

Live GBP reviews, verified + multi-axisUpgrade

Pull live Google reviews (never hand-typed), label "verified patient" from booked-and-attended appointments, show multi-axis stars (wait time, comfort) + earned ops badges, and emit Review/AggregateRating schema. Two-tier: network + local rating.

Named doctor / founder E-E-A-TUpgrade

A named provider with photo, credentials, and philosophy on service pages turns an anonymous practice into an accountable person — where the individual-brand model beats a national chain.

Named guarantee + first-visit reassuranceNet-new

A branded promise ("The {Practice} Promise") + a "what to expect at your first visit" block — anxiety reduction is dental-specific gold.

PLT

Platform & governance

The architecture that lets you run 260 brands at scale — routing, analytics/experimentation, one build path, and the control plane itself.

ZIP → practice resolver + parent directoryNet-new

A network "find-a-practice" front door routing by geography over the Master Crosswalk (reusing lookup_practice), with service-aware pre-filter and "Center of Excellence" tier badges. Each brand keeps its own identity.

Centralized analytics + standing A/B slotNet-new

One shared GTM container across the fleet + an experiment slot baked into every template (Groundworks' Optimizely model), so you test once and roll the winner to all 260.

Seen on: Groundworks · Builds: Phase 0 analytics + Improvement
One canonical build path + a site registryNet-new

Collapse the two renderers (site-builder/ + design/sga-worker/) into one, and stand up the system-of-record every management surface reads from. This is the backbone of the control plane.

Basis: current codebase · Builds: Control plane + 4 tables
04 — Build list

Module catalog

Every pattern above, as a discrete builder module — filter by discipline, read the source and status, and see relative build priority. Grounded in the current codebase (47 modules, 14 recipes, static-HTML assembler).

ModuleDisciplineSourcePriorityStatus
Schema Graph Generator
FAQPage · Dentist · Service · Review · AggregateRating · OfferCatalog · ReserveAction · Breadcrumb
AEOAll 9 · Aspen benchmarkUpgrade
/llms.txt Generator
per-practice LLM positioning + link index
AEOCraftworkNet-new
FAQ Block (visible + schema)
accordion single-sourced to FAQPage JSON-LD
AEOCraftwork · Tend · Manchester · AspenUpgrade
Service / Cost Answer Page
"{procedure} cost in {city}", Key-Takeaways box, $/mo examples
AEOZocdoc · Invisalign · HealthlineNet-new
Medical Review Byline + E-E-A-T
"Reviewed by Dr. X, DDS" + MedicalWebPage/Condition
AEOHealthlineNet-new
SearchAction Resolver + COE Tiers
ZIP box as SearchAction JSON-LD, service pre-filter
AEO PLTInvisalign · AspenUpgrade
Location Page Generator
service×city + neighborhood mesh + sitemaps + titles
SEOCraftwork · Manchester · Groundworks · AspenNet-new
Topical Cluster Generator
pillar + spokes per service line, internal-link mesh
SEOHealthlineNet-new
Provider Profile Pages
indexable page per dentist — bio, credentials, slots
SEO TRUZocdoc · Aspen · ManchesterUpgrade
Lead Forms + Submission Store
5-field intake, honeypot, routing, per-practice inbox
CROManchesterNet-new
Intake Funnel
one-Q-per-screen, progress, "your plan" reveal, PII last
CROHers/HimsNet-new
Live Slot Grid
real open times on hero; slot-first, PII-last
CROZocdocNet-new
Sticky Action Bar
mobile Book + local click-to-call, always visible
CROAll round-1Net-new
Emotional Hero
barrier-dismissing headline + reassurance + one CTA
CRO DESTendUpgrade
Insurance Check
carrier grid, "most PPO accepted", plan lookup
CROTend · Zocdoc · AspenNet-new
Financing Badge · Cost Estimator
CareCredit / membership "from $X/mo"; no-PII price ranges
CROManchester · GW · Aspen · InvisalignNet-new
New-Patient Offer Card
"$XX exam / $0 w/ insurance", value + auto-expiry
CROAspen · Hers/HimsNet-new
Verified Reviews + Rating Badges
booked-&-attended "verified", multi-axis, ops badges
TRUZocdoc · Aspen · GroundworksUpgrade
Doctor / Founder E-E-A-T
named provider, photo, philosophy, credentials
TRUManchester · Tend · AspenUpgrade
Named Guarantee + First-Visit
"The {Practice} Promise" + "what to expect"
TRUCraftwork · TendNet-new
Before / After Smile Gallery
slider, per-brand themed
TRU DESCraftworkIn builder
Brand Token System
one component set, per-practice --brand-* from practice_brand
DES PLTGroundworks · Aspen · InvisalignUpgrade
ZIP → Practice Resolver
parent find-a-practice directory over Master Crosswalk
PLT SEOGroundworks · InvisalignNet-new
Analytics + Experiment Slot
one shared GTM container, standing A/B slot per template
PLTGroundworksNet-new
Canonical Build Path
collapse site-builder/ + design/sga-worker/ into one renderer
PLTinternal (codebase)Upgrade
Site Registry + Control Plane
4 tables + 6-surface console (see §05)
PLTinternal (net-new)Net-new

Priority bars are relative build-sequence weight, not certainty. Status: In builder ships today · Upgrade exists but incomplete · Net-new does not exist. The schema block's placeholder values ([PHONE], 5.0, 100) must be replaced with real per-practice data before scaling.

05 — Management layer

Control plane & data model

A single console over all 260 sites. Its first job isn't dashboards — it's to create the system-of-record that doesn't exist: one queryable place for every site's code, hosting, forms, and analytics. Six surfaces, backed by four new Drizzle tables in packages/shared-types.

Illustrative wireframe — the summary strip every surface shares.

Surface 1

Site Registry

One row per practice site: brand, city, live URL, domain, CF account, code path, recipe + package, owner, last build, form endpoint, analytics ID.

writes → sites · deployments
Surface 2

Health & Uptime

Uptime, Core Web Vitals, SSL & domain expiry, broken-link sweep — a fleet heatmap that surfaces the few sites needing attention.

reads → site_health_checks
Surface 3

Lead Desk

Where every submission lands, who can see it, and the SLA clock on follow-up — the question that has no answer today.

reads → form_submissions
Surface 4

Analytics Rollup

Traffic → lead → booking funnel per site and portfolio-wide, off one shared GTM container.

reads → GTM · submissions
Surface 5

SEO / AEO Coverage

Schema-coverage %, /llms.txt presence, service×city counts, sitemap status, review freshness — with drift alerts.

reads → seo_coverage
Surface 6

Publish & Deploy

One canonical build path, CF-account routing + 100-project cap management, one-click rebuild, per-site template version.

writes → deployments

New data model — four tables

TablePurposeKey fields
sitessystem of record per practice sitepractice_id · domain · live_url · cf_account · code_path · recipe · package · template_version · owner · form_endpoint · analytics_id · gbp_url
deploymentsevery build + publish, per sitesite_id · commit · status · built_at · deployed_by · duration · cf_project
form_submissionslead capture + routing (PHI-aware)site_id · type · payload(non-PHI) · routed_to · sla_due · status · created_at
site_health_checksuptime, CWV, SSL, schema driftsite_id · checked_at · uptime · lcp · cls · schema_coverage · ssl_expiry · broken_links

Registry — a worked row

PracticeLive URLCode pathHostForms →AnalyticsStatus
Ressler Dentalresslerdental.comdocs/practices/resslerCF · sga→ inbox + CRMGA4-RSLLive
— example —{brand}.comdocs/practices/{slug}CF · {acct}→ {endpoint}GA4-{id}Stale
— example —{brand}.comdocs/practices/{slug}CF · {acct}unroutednoneNot deployed
PHI guardrail

Forms stay in Phase A

Booking step 1 and the lead store capture non-clinical selections only (new patient, cleaning, cosmetic consult, emergency) plus name/phone/email to confirm. Robots hide any portal/auth route. No patient records or clinical detail until a BAA is in place (Phase B).

06 — Ownership

RACI — who owns what

Fifteen elements across build, content, SEO/AEO, forms, hosting, monitoring, and improvement — centered on the SGA Marketing team, with the adjacent roles the fleet needs. Roles are placeholders; confirm the real owner per column.

R Responsible A Accountable C Consulted I Informed
ElementMarketingPlatform/BuildMarket MgrsPractice StaffAnalyticsCompliance
Template & module developmentCR/AIICC
Brand tokens & visual identityR/ACCI··
Copywriting (AI draft → review)R/ARCC·C
Photography & mediaAICR··
Technical SEO (schema, sitemaps, llms.txt)CR/A··C·
SEO/AEO content productionR/ACC·C·
Local listings / GBP / reviewsACRC··
Forms & lead-routing configCR/ACI·C
Lead follow-up & SLAI·ARC·
Hosting, domains & deploysIR/A····
Uptime & performance monitoringIR/A··C·
Analytics, tracking & reportingCCI·R/A·
CRO / A-B experimentsR/ACI·C·
Accessibility & HIPAA / PHIIC···R/A
Registry / system-of-record upkeepIR/AC·C·

Each row has exactly one A. Where Marketing and Platform both build, the split is intent vs. mechanism — Marketing owns what it should say, Platform owns that it works.

07 — Sequence

Roadmap — the order it has to happen in

A real dependency chain, not a menu. Nothing downstream is measurable or governable until the foundation exists — so it goes first.

0
Foundation · make the invisible visible

Forms, analytics, and the registry

The three things that are literally zero today. Without them there is no data to manage and no console to build.

  • Create sites · deployments · form_submissions · site_health_checks; backfill the registry from existing deploys.
  • Ship a real lead-form backend + submission store (PHI Phase A), wired into every generated site.
  • Drop one shared GTM container on all sites; collapse the two renderers into one build path.
1
The AEO wedge · cheapest differentiation

Schema graph, llms.txt, answer-first pages

Turn structured data from a spec into automatic output — the advantage no competitor is executing.

  • Full JSON-LD generator matching Aspen's stack, replacing the placeholder block.
  • Per-practice /llms.txt, auto sitemaps + robots, service×city generator with question banks.
  • Answer-first Service/Cost pages (Key-Takeaways, $/mo), the "Reviewed by Dr. X, DDS" byline, topical clusters.
2
Conversion kit · lift the whole fleet

Visits → booked patients

Ship the CRO + trust modules as inherited defaults, not per-site decisions.

  • Intake funnel + live-slot booking as the primary path; sticky dual CTA, insurance check, financing, offer card.
  • Emotional hero, named guarantee, first-visit, verified reviews + badges, before/after gallery, provider profiles.
3
Governance · the console + directory

The six-surface control plane

Now that the data exists, give it a front-end — and add the network front door.

  • Registry, Health, Lead Desk, Analytics, SEO/AEO Coverage, Publish & Deploy over the Phase-0 tables.
  • ZIP → practice resolver + parent "find-a-practice" directory (as a SearchAction) over the Master Crosswalk.
4
Compounding · never ship-and-forget

The improvement engine

Make the fleet get better on a cadence, owned per the RACI.

  • Content engine, CRO experimentation, reputation velocity, per-site scorecards.
  • Performance budget + nightly coverage audits + quarterly template upgrades propagating fleet-wide.
08 — Continuous improvement

Standing programs so the fleet compounds

A builder that ships and forgets decays. Each program has a cadence and an owner, and each is possible only once Phase 0's data exists.

AEO / SEO content engine Weekly

Expand per-service question banks, extend service×city coverage, refresh each /llms.txt; monthly guides + blog. Fed by the coverage surface's gaps.

Owner: SGA Marketing

CRO experimentation Monthly

A standing experiment slot per template; test hero, CTA, and funnel on high-traffic sites; roll winners fleet-wide in one push.

Owner: Marketing + Analytics

Reputation & review velocity Continuous

Live GBP pull keeps ratings honest; a monthly review-generation push raises count + recency, the signals engines weight.

Owner: Market Managers

Performance budget Per-change

CWV monitored continuously; a Lighthouse gate on every template change so a fleet-wide push can't regress speed.

Owner: Platform / Build

Schema & SEO coverage audit Nightly

Coverage % per site; drift alerts when a page loses FAQPage, NAP, or sitemap entries. "Did it ship everywhere?" becomes a dashboard.

Owner: Platform / Build

Per-site scorecard Monthly

Traffic → lead → booking + trust + coverage into one practice grade (reuse sga-scorecard), so Market Managers see their portfolio ranked.

Owner: Analytics / Data