Blitz Brand Lab · Templates

A page is a contract, not a canvas

14 live templates and 2 dormant ones. Each one fixes its data source, the order of its sections, what every section requires, and the checks a page must pass before it ships. Two pages of the same directory read as one template, or the site reads as several.

14 LIVE · 2 DORMANT15 PRODUCTS · 5 USE CASES · 5 TEAMSORDER IS PART OF THE CONTRACTMIRROR OF src/pages/**
01Copy lives in the data

H1, subtitle, FAQ, endpoint: all in JSON or MDX. A template that carries a sentence carries a bug waiting to diverge.

02A page never opens on a grid

The first body section is a split, a lead or a scene. Features in first position render as FeatureLead.

03Fallbacks are measured, not read

A missing asset or href produces a degraded variant without an error. Compare a page with the directory reference before touching CSS.

04Same closing everywhere, with one exception

Signed band, FAQ, offer strip, CTA. The reader lands on the same decision at the end of every chapter. The three benchmark templates close on the CTA alone: FAQPage markup is banned under /benchmarks since Google dropped it from results on 2026-05-07, and an offer strip beside a measurement reads as an ad.

00
Shared skeleton

What BaseLayout posts once

Every template starts here. None of these is ever redrawn in a page or a component.

6 PARTS
  1. SEOtitle, description, canonical, OG, Twitter, JSON-LD
  2. Navnavbar + mega-menu from config/site.ts (NAV, PRODUCT_FAMILIES, CTA)
  3. .page-railsthe two vertical rules, aligned on .container
  4. <main id="main">the only landmark; skip link target
  5. Footerfrom config/site.ts (FOOTER, EXTERNAL); privacy and opt-out links
  6. Tracking loaderonly when PUBLIC_TRACKING_ENABLED, guarded by BaseLayout
01
T1 · live

Home

The one page with bespoke sections: every home component reads home.json itself, the hero banner reads pricing.ts, and the data-quality band reads its numbers from the latest benchmark edition.

1 page
  1. 01
    HeroTopBorder + HomeHero + HeroBottomBorderhome.json hero
    • h1
    • subtitle
    • primaryCta

    Framed hero with the pricing banner (.hero-offer): « NEW PRICING », the entry price, no date

  2. 02
    LogoBandconfig/logos
  3. 03
  4. 04
    QualityRanking (measure accuracy_pct)home.json qualityRanking (a top-level key, NOT in sections) + collection benchmarks via lib/benchmark-compare.ts
    • eyebrow
    • title
    • subtitle
    • cta.label
    • methodologyLabel
    • cardLabel
    • measured
    • disclosure
    • measures.<key>
    • close

    Since 2026-09-24 (Antoine): the accuracy ranking of the latest edition, BlitzAPI in the brand blue. It replaced DataQuality. The only comparison allowed outside /benchmarks: the recipe lists this page in COMPARISON_PAGES, and tolerates competitor names only inside the block, which carries its dated scope and the disclosure

  5. 05
    AllInOneSolutionkind: usecaseshome.json sections[0]
  6. 06
    VideoFeature + TourPosterkind: videohome.json sections[1] + PRODUCT_TOUR_VIDEO in config/video.ts

    The /sculpt design since 2026-10-14: section heading, framed 16:9 facade with the HTML poster, nothing loads before the click

  7. 07
    InfraPillarskind: splithome.json sections[2]

    100 % driven by JSON: pillars, chips, proof

  8. 08
    RawDataIntelligencekind: showcasehome.json sections[3]
  9. 09
    DataWorkflowskind: featureshome.json sections[4]

    Dark matrix, one cell per workflow

  10. 10
    Testimonialsconfig/testimonials.ts

    Hidden in production while QUOTES_ARE_PLACEHOLDERS is true

  11. 11
02
T2 · live

Product

One API, one page. Two openings exist: split + showcase (CodeSplit then ProductTabs) or a FeatureLead opening followed by the rail and the steps.

15 pages
  1. 01
    Breadcrumbsfamily label + seo.title

    BreadcrumbList JSON-LD

  2. 02
    • h1
    • subtitle
    • primaryCta
    • secondaryCta

    secondaryCta = the deep link to the API reference page

  3. 03
    TrustedBandconfig/logos

    Product variant: text cell + client marquee

  4. 04
  5. 05
    CodeSplitkind: splitoptional
    • title
    • items (text bullets)
    • asset

    Opening A. The button falls back to docsUrl

  6. 06
    ProductTabskind: showcaseoptional
    • title
    • items[] with title + text

    Opening A

  7. 07
    FeatureLeadkind: features
    • items[] with title, text, asset

    Opening B, only when features is the FIRST section. Later features render as GrayCards

  8. 08
    UseCaseRailkind: usecases
    • items[] with title, text, href
  9. 09
    WorkflowStepskind: stepsoptional
    • items[] with title, text

    Subtitle carries the endpoint: « One endpoint, POST /v2/…, … »

  10. 10
  11. 11
    GrayCards (links)relatedProducts[] or same family

    « Related APIs », 3 cards. relatedProducts: [] removes the band

  12. 12
    SignatureBandFAMILY_BANDS[family] + docsUrl
  13. 13

    Native <details>, FAQPage JSON-LD emitted automatically

  14. 14
    OfferBandconfig/pricing.ts

    variant="strip", links to /pricing

  15. 15
    CtaSectionconfig/site.ts
JSON · the T2 contract, opening A
{
  "family": "search",
  "endpoint": "POST /v2/search/companies",
  "seo": { "title": "… | …", "description": "140 to 160 characters" },
  "hero": {
    "tag": "…", "h1": "…", "subtitle": "…",
    "primaryCta": { "label": "Get 1,000 credits free", "href": "https://app.blitz-api.ai" },
    "secondaryCta": { "label": "API Docs", "href": "https://docs.blitz-api.ai/api-reference/…" }
  },
  "sections": [
    { "kind": "split", "title": "…", "subtitle": "…", "asset": "search-query", "items": [{ "text": "…" }, { "title": "API Docs", "href": "https://docs.blitz-api.ai/…" }] },
    { "kind": "showcase", "title": "…", "items": [{ "title": "…", "text": "…", "asset": "filter-set" }] },
    { "kind": "features", "title": "…", "items": [{ "title": "…", "text": "…", "asset": "dataset" }] },
    { "kind": "usecases", "title": "…", "items": [{ "title": "…", "text": "…", "href": "/use-cases/build-tam" }] }
  ],
  "faq": [{ "q": "…", "a": "…" }],
  "docsUrl": "https://docs.blitz-api.ai/api-reference/…",
  "relatedProducts": ["/products/people-search", "/products/tam-by-people"]
}
03
T3 · live

Use case

A playbook page: framed hero with its MotionScene, one proof frame per editorial block, a capability map, the endpoints that execute it.

5 pages
  1. 01
    BreadcrumbsUC_META crumb
  2. 02
    UseCaseHerohero + scene
    • h1
    • subtitle
    • primaryCta
    • a spec in motion/specs/use-cases/

    Without a scene the hero is a centered text block

  3. 03
    TrustedBandconfig/logos

    Use case variant: centered hook + marquee

  4. 04
  5. 05
    • asset
    • items[] text bullets

    Text on the left rail, proof frame on the right

  6. 06
    WorkflowStepskind: steps
    • items[] title + text
  7. 07
    PlaybookGridkind: features
    • href on EVERY item

    The current page cell becomes « You are here »; every other href is typed by lib/destination.ts, or the build throws

  8. 08
    • asset
    • exactly one item {title, href}

    Proof on the left, text + button on the right. Without the href item it silently falls back to « points »

  9. 09
    RelatedApiskind: apis
    • asset
    • items[] with href; bullets separated by \n

    The P1 frame shows UC_META.endpoint

  10. 10
    SignatureBandUSECASE_BANDS[slug] + docsUrl

    proof is cut when the page already shows that signature

  11. 11

    Native <details>, FAQPage JSON-LD emitted automatically

  12. 12
    OfferBandconfig/pricing.ts

    variant="strip", links to /pricing

  13. 13
    CtaSectionconfig/site.ts
04
T4 · live

Team (persona)

A persona page, one fixed sequence on all five: the pains, what the role builds, the calls it has at hand, how they chain, the human proof, then the shared closing. The template derives the splits structurally and THROWS, naming the file and the field, when a required part is missing or a section has no place in the sequence.

5 pages
  1. 01
    Breadcrumbshero accent
  2. 02
    • h1 (« … for <persona> » or **accent**)
    • primaryCta
  3. 03
  4. 04
  5. 05
    PainsSectionkind: split + features (untitled)
    • pains split: title, subtitle, items[] (lead + bullets)
    • pains split: ONE item {title, href} without text, the column button (label and link); no fallback
    • features WITHOUT title: exactly 3 cells with title and text (throws otherwise)
    • scene in motion/specs/teams/ + SCENE_LABELS

    closesOnBand: no bottom padding, the gray band's top rule closes its grid

  6. 06
    UseCaseMatrixkind: usecases
    • title (**accent**)
    • exactly 6 items with title and text (the outcome, not the call)
    • href optional: without it, a plain CAPABILITY cell

    Gray band; destination type from lib/destination.ts (shared with PlaybookGrid and NextStep), an href it cannot type throws; stretched title link, no aria-label

  7. 07
    EndpointToolkittoolkit (root field)
    • title, subtitle
    • items[]: {product: "/products/<slug>", job}, 4 to 8, no duplicate; job = what goes in, what comes back

    Name, endpoint, family, link and plans read from the product JSON (sections/product-ref.ts), the call drawn by EndpointCall; optional note at the foot (agencies: client work; developers: Blitz Embedded); stretched name link

  8. 08
    EndpointChainworkflow (root field)
    • title, subtitle
    • steps[]: {product, text, output}, 3 or 4; text = what the step does with the previous output
    • every step product listed in toolkit.items

    Dark panel on the gutter; the eyebrow counts the calls; the call drawn by EndpointCall (tone dark)

  9. 09
    WorkplaceSectionkind: split (founder) + split (Plug BlitzAPI)
    • founder split: ONE item with title « Name, Role » and text
    • stack split: title starting with « Plug BlitzAPI », one item with text

    Four cells; no pipeline diagram, the chain above carries it

  10. 10
    SignatureBandTEAM_BANDS[slug] + docsUrl
    • docsUrl
    • TEAM_BANDS entry
  11. 11

    Native <details>, FAQPage JSON-LD emitted automatically

  12. 12
    OfferBandconfig/pricing.ts

    variant="strip", links to /pricing

  13. 13
    CtaSectionconfig/site.ts
05
T-hub · live

Hub (Developers, Integrations)

Three single pages on the developer side (the toolkit, the integrations, the MCP server), so they share one contract: framed hero with a scene, editorial split, one showcase, one code or connector block, one « Where to go next » matrix. /mcp puts its setup (CodeTabs) and prompts (McpPrompts) before the split, and its 24-tool reference (McpTools) in place of the showcase, after the split.

2 pages
  1. 01
    Breadcrumbs
  2. 02
    UseCaseHerohero + scene
    • a spec in motion/specs/hubs/
  3. 03
  4. 04
  5. 05
    FeatureLeadkind: features
    • 3 items
  6. 06
    • href only on what is really documented
  7. 07
    CodeTabskind: codeoptional
    • endpoint
    • responseFields
    • items[] with lang, code and a verbatim `source` URL

    Developers only. A snippet without source is an invented snippet

  8. 08
    WorkflowStepskind: steps
  9. 09
    HubSplitkind: split
    • asset
    • proof.head
    • proof.foot
  10. 10
  11. 11
    PlaybookGridrelatedProducts[] + relatedCourses[]
    • 6 cells (full grid)

    ONE « Where to go next » matrix, never two consecutive card bands

  12. 12
    SignatureBandHUB_BANDS[slug] + docsUrl
  13. 13

    Native <details>, FAQPage JSON-LD emitted automatically

  14. 14
    OfferBandconfig/pricing.ts

    variant="strip", links to /pricing

  15. 15
    CtaSectionconfig/site.ts
06
T-pricing · live

Pricing

The page that decides the conversion rate. No component carries a figure: everything reads pricing.ts, including the JSON-LD offers.

1 page
  1. 01
    Breadcrumbs
  2. 02
    PageHeroCOPY.hero

    align="center" compact

  3. 03
    PlanCardsPLANS
    • three plans (Start, Scale, Build Your Infra), same decision at the same height
    • specs: speed, fair use policy as a LEVEL (the number lives in the tooltip and the table), support
  4. 04
    QualityStrip

    Quality reassurance without an accuracy figure

  5. 05
    PlanComparePLAN_COMPARE

    Four groups (what changes, included everywhere, custom terms, service), a decision row in <tfoot>

  6. 06
    EmbeddedBandEMBEDDED

    Primary CTA = cal.com booking, the contact form as a secondary link

  7. 07
    FaqSectionPRICING_FAQ
  8. 08
07
T-about · live

About

The company page: manifesto, counters, principles, the dark workflow grid. Copy and the four portraits are frozen.

1 page
  1. 01
    Breadcrumbs
  2. 02
    Inline hero (Tag + h1 + Button)about.json hero
  3. 03
  4. 04
    Manifestoabout.json
    • html
    • name
    • role
  5. 05
    CountersBandabout.json counters

    variant="about", authorized KPIs only

  6. 06
    ValuesGridabout.json tabs

    Principles, all unfolded

  7. 07
  8. 08
  9. 09
  10. 10
08
T-contact · live

Contact

A form page: PageHero, the form (Field + Checkbox, three states), the logo band, the steps, the FAQ.

1 page
  1. 01
    Breadcrumbs
  2. 02

    align="left": the left variant carries the section envelope geometry

  3. 03
    Form (Field, Checkbox, Button)CONTACT_FORM endpoint (n8n webhook)
    • three states: sending, sent, error
  4. 04
  5. 05
    WorkflowStepskind: steps
  6. 06
  7. 07
10
T-utility · live

Utility pages

Self-contained pages on the shared skeleton: the 404 (Nav, copy, Button, Footer) and the CCPA opt-out form (verbatim brief, request_id generated on the site).

2 pages
  1. 01
    Nav + FooterBaseLayout
  2. 02
    Page bodyJSON copy

    Opt-out: [hidden]{display:none!important} scoped rule, because state frames set display:flex

11
T-event · live

Event landing

A campaign page for people who just heard about BlitzAPI somewhere else (an event stage, a partner survey): the promo code in one tap, then trust in their language (measured quality, people they know, what they can do, the product video), the offer itself (the discounted plan), and the three steps to redeem.

  1. 01
    HeroTopBorder + PromoHero + HeroBottomBorder<page>.json hero + the Promo object

    HomeHero geometry; the right column is the page visual in HeroVisualFrame (slot "visual": GuestPass on /sculpt, PerkDeck on /stateofgtme, decorative), the left column carries PromoCode (functional)

  2. 02
  3. 03
    SectionDivider
  4. 04
    QualityRanking (measure accuracy_pct)stateofgtme.json quality + the latest benchmark edition

    /stateofgtme only (Antoine, 2026-10-27): the home ranking, without links to the head to heads; the page is listed in COMPARISON_PAGES, names tolerated inside the block only

  5. 05
    UseCaseRailstateofgtme.json usecases

    /stateofgtme only: five use cases in plain words, each row a link

  6. 06
    PeopleProofsculpt.json speakers · stateofgtme.json people
    • quote = verbatim with a dated source, or bio = prose, never a bio in quotes

    Eric Nowoslawski (verbatim) and Jordan Crawford (bio) on both pages

  7. 07
    LinkMatrixstateofgtme.json products

    /stateofgtme only: five flagship products + the stack cell

  8. 08
    VideoFeature + TourPosterPRODUCT_TOUR_VIDEO in config/video.ts

    Inline facade, nothing loads before the click; YouTube, Loom, Vimeo or a file

  9. 09
    PromoOffer<page>.json offer + PLANS, SELF_SERVE and COMPARE_GROUPS in config/pricing.ts

    The discounted plan (prop `plan`, Scale on both pages) large, the same code on the other self-serve plan in one line; discounted prices are computed

  10. 10
    LinkMatrixsculpt.json teams

    /sculpt only: 3 × 2 matrix, five teams + the stack cell

  11. 11
    SectionDivider
  12. 12
    WorkflowSteps<page>.json redeem
  13. 13
  14. 14

    buttonAttrs carries data-promo-cta so the button flips when a dated code expires

12
T-blog · dormant

Blog article

A 740px reading column (about 67 characters): category, date and reading time, KeyTakeaways under the title, prose with the 12 shared content blocks, FAQ, then « Keep reading » cards.

3 articles, routes dormant
  1. 01
    Article headerfrontmatter
    • title
    • description
    • category
    • publishedAt
    • takeaways (3 to 5)
  2. 02
    KeyTakeawaystakeaways[]

    Also emitted as structured data

  3. 03
    Prose + content blocksMDX body

    components/content/* (Definition, Callout, Steps, Compare, Stats…)

  4. 04
    Figurescene spec

    Visual mounted on the Visual Generator, caption required

  5. 05
  6. 06
    BlogCard × 3latest posts

    « Keep reading »

13
T-learn · dormant

Course and lesson

An LMS without login: course catalog (CourseCard with a generative cover), course landing (CurriculumList, VideoIntro, LeadMagnet), lesson page (LessonChrome, LessonSidebar, prose, the 7 lesson blocks, progress in localStorage).

2 courses · 12 lessons, routes dormant
  1. 01
    CourseCardcourses collection

    Generative 16:9 cover, platform tag, level badge, lessons and minutes

  2. 02
    CurriculumList + VideoIntro + LeadMagnetcourse JSON

    Course landing

  3. 03
    LessonChrome + LessonSidebarlesson headings + progress

    Reading bar, remaining time, keyboard arrows, resume

  4. 04
    Lesson arclesson MDX
    • Objective first
    • Recap last

    Objective → prose + shared blocks → Payload → TryIt → Troubleshoot → Quiz · Checkpoint → Recap

14
T-bench-hub · live

Benchmark directory

The page of the SERIES, not of an edition. The report keeps the ranking; the directory keeps the question « which one, for me ». It opens on a figure that ranks the providers measure by measure, because the order changes with what you optimise, and it is also the navigation: every competitor name opens its head to head. Then the head to head rail, the protocol in three steps, the index of every edition, and, from two comparable editions, how positions have moved.

1 page
  1. 01
    Breadcrumbsstatic

    BreadcrumbList JSON-LD

  2. 02
    Short heropage copy
    • kicker
    • h1
    • one paragraph
  3. 03
    Latest report cardlatest run
    • eyebrow with the Measured on line
    • h2 linked
    • one solid action

    A BORDERED card (session 47, Antoine: make it read as a block of the page that gives access to the actions): 1px --color-border, white on the page background, square corners like the report recap, padding --pad-8xl. It wraps the eyebrow, the h2 and the action row, nothing else; the actions sit on a rule inside it. The h2 carries its underline AT REST: painted like the h1, nothing marked it as a link before hover, and there is no hover on a finger. The solid pill sits directly under it, in the first screen

  4. 04
    ChartFrame + DimensionRanksproviders[].kpi + interval
    • claim={false}: no claim, by decision

    Right under the card, outside it. Its claim (« No provider here is ahead on every measure ») was removed in session 47 at Antoine's request: ChartFrame is called with claim={false} and renders nothing in its place; the readAs note stays. Columns are measures, rows are ranks. The order is DERIVED in the component, not written in the page: measures whose separation was tested first, then the one where the publisher places lowest, whichever rank that is, then the tightest race. On the September run that opens the figure on coverage. Rank 1 is marked by weight alone. The four-sentence rule paragraph under the figure was removed in session 46: what it said is IN the figure, in the column headers (separation not tested) and on the rows (too close to separate). Work history is deliberately absent: its 80 point gaps are endpoint scope, not quality

  5. 05
    Disclosurepage copy

    BELOW the figure: before it, it reads as a barrier to a result

  6. 06
    HeadToHeadRailduels + pairBestoptional
    • the base n on every row
    • the coverage concession
    • the contacts where the competitor is right and we are not

    Sorted by SMALLEST gap first: sorting the other way would open on the most flattering pair. The two counterweights are rendered unconditionally; the counter sentence is counterLine() of viz.ts, the same one as the duel page, and the pair is oriented by pairSides(). The lede names the Coverage column of the figure above by its name, never « the reach figure », and describes the duel page from DUEL_SECTIONS (duel/sections.ts), in its order. The whole section is SKIPPED when the publisher is absent from the edition, rather than rendering an empty rail

  7. 07
    How a run workspage copy, three steps

    Three, not six: more repeats /benchmarks/methodology. Step 01 and the hero lede DATE the queries from run.queried_on of the latest edition (dayRange() of viz.ts): « same day » is written only when every provider was queried on one day

  8. 08
    EditionIndexevery published run

    ALWAYS rendered, even with one edition: a shape never seen on screen has never been measured. Year grouping keys off the SPREAD of years, not a count; label falls back to the long date for the whole list as soon as two editions share a month; data-benchmark on EVERY row. The fold over twelve editions is specimened on /brand-lab/sections with visible=0

  9. 09
    ChartFrame + RankTrendeditions on the same protocolVersionoptional

    Renders NOTHING below two comparable editions, so it is absent from every published page today. It plots the RANK, not the value: each edition is a different list of contacts. Only providers present in every edition shown carry a line. Its layout specimen lives on /brand-lab/sections, fed the same edition twice, so the geometry is measured before the second edition lands

  10. 10
    CtaSectionconfig

    cta id benchmarks.cta_section.primary

15
T-bench-run · live

Benchmark run

One run, in full: every measure, every segment, and the rules that produced them. Ten sections under a sticky horizontal section rail, numbered from the order of the SECTIONS array rather than by hand, and one claim per figure. Two gestures change what is shown, and both make information APPEAR rather than dim it: switch the measure, switch the segment dimension.

1 run published
  1. 01
    Breadcrumbsstatic
  2. 02
    Editorial header + ranking recapheadline, standfirst, testDate, kpi
    • kicker
    • h1
    • standfirst
    • disclosure
    • measured on line
    • one action

    The standfirst is report register, 25 to 40 words (session 47): a figure-free human framing of what the series measures, then a GENERATED sentence naming the edition and its providers in ALPHABETICAL order, never rank order. It carries no measure and does not repeat the Measured on line right under it. The disclosure names what the reference is FOR (« the reference every answer is scored against »): the shortened standfirst no longer introduces it, and the PDF reader meets it on page 1. The measured on line keeps the REFERENCE date (testDate); when the queries do not all fall on it, a « Queried on » item follows, read from run.queried_on (dayRange() of viz.ts), and the recap note, the Dataset JSON-LD and the footer date the queries the same way. The measured on line (BenchMeta, kicker off) and the action row (BenchActions: the download pill carries its « PDF, no email » note and no arrow) are shared with /benchmarks and the duel pages since 2026-09-23; the local copy had drifted. On paper the header goes back to two columns, so the cover carries the whole recap. The takeaways block was removed in session 46, and the field with it: a field a person writes every month and nobody reads is how it drifted into publishing a false count in the first place

  3. 03
    Section railSECTIONS

    Sticky under the nav, scrollspy, hidden in print. A 16px gap, so the ten entries fit whenever the list has its full width (viewports from about 1140px); below that it stays a scroller and fades its right edge while entries remain to the right (.rp-rail-list--more, set by the rail script), instead of cutting « 10 The report » to « 10 T » with no sign that the list goes on

  4. 04
    01 ChartFrame + RankingChartproviders[].kpi + interval

    Composed track over 100 contacts. Its exact numbers are OPEN, not folded. The middle part is « Returned, not verified accurate » (legend, aria-label, claim, readAs), never « wrong »: it is coverage minus accurate, so it holds the unverifiable answers too, and the home DataQuality block names the same part the same way

  5. 05
    01 Formula stripkpi ranges

    coverage x accuracy = accurate per 100

  6. 06
    02 ChartFrame + TradeoffChartproviders[].kpi

    Coverage against accuracy, with equal-yield curves. No red. The lede names BOTH ways a record is lost: never returned, or returned and not verified accurate (different title, stale employer, unverifiable). It said « an employer the person has left » alone, which is false for Apollo, whose largest loss is the title; the page throws if the verdict keys ever differ from those four

  7. 07
    03 Lede + ChartFrame + VerdictStackproviders[].verdicts

    Titled « What a wrong answer is made of », like its twin on the duel pages. The punch line (a run-wide « one in N ») and the cost note under it were removed in session 47 at Antoine's request, and « costs you » left the title with them: the section opens on a plain, figure-free report lede naming the four verdicts, and the measure is in the figure claim. Status palette, never provider colors

  8. 08
    04 ChartFrame + MetricSwitch + JobAgeChartfreshness[]

    A grid read by color. Four switchable measures, all rendered at build. No lede since session 47 (both the screen and the print one were removed at Antoine's request): the title opens on the claim, which COMPUTES how many providers bottom out early AND names the measure it was computed on, since a claim placed above a switch is only true on one position. The print copy shows one measure only, so the figure carries a print variant of its reading note (readAsPrint) that says so

  9. 09
    05 SegmentExplorersegments[]

    Segments led per dimension, then a bar in every cell

  10. 10
    06 ChartFrame + DuelMatrix + pair linksduels

    6x6 grid, then ONE line of links to the duel pages. Never link from the cells: the grid holds fifteen pairs and only five have a page. The line describes a duel page from DUEL_SECTIONS (duel/sections.ts), in its order: written by hand it skipped a section and would outlive a reorder, in the PDF too

  11. 11
    07 ChartFrame + CascadeChartcascade + union
  12. 12
    08 DataTable (scorecard)providers[]

    Measures in rows, sticky first column. Four rows were removed in session 46 (share of stale that is a real previous role, start month agreement, share matched by identifier, billed units per accurate record): they describe how the test WORKS, not what a buyer gets. Check the prose around any row you remove: the cost note (itself removed since) pointed at « the billed units above » and outlived them by one build

  13. 13
    09 Method, population, ProviderLegendprotocol + population

    Warnings are published, never smoothed

  14. 14
    10 DataDownloadfiles[] (PDF only)
    • one solid action

    The four CSV, the aggregate JSON and the evidence pack form were removed in session 45: the free PDF is the only file that leaves the site. A print variant replaces the offer, because the reader of the PDF already holds it, and it gives the EDITION URL (built from the slug, like the PDF footer), never the directory. Neither variant says « nothing is written twice »: the page holds screen and print twins, and the PDF is printed by hand

  15. 15
    Other reportscollection

    Bounded to THREE, then a link to the directory: unbounded, a monthly report adds a card to the foot of every earlier report, in the HTML and in the PDF

  16. 16
    Disclosure footerpage copy

    Trademarks, corrections address, test id. KEPT in the PDF

  17. 17
    CtaSectionconfig

    cta id benchmarks.cta_section.primary

16
T-bench-duel · live

Head to head

One page per competitor, aimed at the paired-brand query rather than the category query. It is published by one of the two providers it measures, so its whole construction is about containing that: a face-off symmetrical by design on the main measures, coverage as its second row on every pair page with the publisher’s coverage rank written right under it, the contacts where the competitor is right and we are not, rendered unconditionally, and an exhaustive walk of every published segment whose result is published as one generated sentence, including when it comes back empty. The body is ONE ordered array, DUEL_SECTIONS in components/benchmark/duel/sections.ts: reordering the page is moving one line there, and the directory, the report (and its PDF) and llms.txt describe the page from the same array, in its order.

5 pairs, one page each
  1. 01
    Breadcrumbsstatic
  2. 02
    Headerproviders + duels
    • measured on line
    • disclosure before the first number
    • link to the methodology

    The query date of the lede is read from each provider’s run.queried_on, and the lede points at the shared-contacts section by its SECTIONS id, never by a number. The measured on line (BenchMeta) and the action row (BenchActions) are shared with /benchmarks. The measured on line keeps the reference date; when the pair was not queried exactly on it, a « Queried on » item follows, from the same run.queried_on as the lede (model.queriedMeta). A dated banner appears when the edition shown is not the latest, because the competitor left the run. Everything below the header is driven by DUEL_SECTIONS (duel/sections.ts): each entry is an id and a short summary, the page maps each id to its section component from components/benchmark/duel/ and throws on an id without one, the number is derived from the position and the anchor is the id. Every section reads the same model (duel/model.ts), so moving one needs no prop rewiring

  3. 03
    01 FaceOffSection: ChartFrame + DuelFaceOff, then the coverage rank and the ledger linekpi + interval + verdicts, kpi.coverage_pct of every provider, segments
    • both sides always rendered
    • the ledger sentence, generated

    Five measures: accurate records per 100 (featured, the measure the report ranks on, NOT a composite), then its two factors, coverage and accuracy, then the wrong title rate and the stale employer rate. The row list lives in FACE_OFF (duel/model.ts). A side is marked ahead only where the gap clears both intervals; rows without an interval print the gap and « separation not tested ». The former section « Reach, where we come Nth » is folded in under the figure: the publisher’s coverage rank on the whole run, and the segment ledger sentence, which is the transparency device of the page and must not be removed without a replacement

  4. 04
    02 ErrorsSection: ChartFrame + VerdictStackverdicts

    Two bars instead of six. n is the two returned counts added, like the report figure: the shares are of returned contacts, not of the list. The claim is computed in duel/model.ts (errors.claim) from the stale share the figure draws, and throws when it is missing: it used to fall back to 0% in the section

  5. 05
    03 SharedSection: ChartFrame + DuelSplit + counter lineduels
    • the base n written on the figure
    • the counter line, rendered unconditionally

    The four buckets partition the shared contacts, and the component THROWS if they do not. Never mix this accuracy with the face-off accuracy: two different bases. The counter line says « right where we are not », never « wrong » (the bucket holds our unverifiable answers), and comes from counterLine() of viz.ts, the same sentence as HeadToHeadRail. Its separation threshold is the two PUBLISHED accuracy intervals added together, which are computed on everything each provider returned, and the sentence names that base: no interval is published on the shared contacts

  6. 06
    04 FreshnessSection: MetricSwitch + ChartFrame + JobAgeChartfreshness

    Two series, four switchable measures. The claim is computed on the default measure and NAMES it: a claim written above a switch is false on the other three positions, and the grid rounds to integers, which creates ties the source does not have. The lede is a reading instruction only, no universal claim

  7. 07
    05 CaveatsSectionhistory + the face-off measures

    The Separation line is DERIVED from the face-off measures that carry an interval, and names them « the main measures on this page », never by their position. The work history line is conditioned on provider_exp_per_profile, never on a list of names, and points at no figure: work history is not on this page. The cost line says only that neither provider publishes a unit price that can be sourced and dated (the model throws if either run says price_is_public_list); its « units are not the same object » clause was false on the MoltSets page, where both bill records per returned profile

  8. 08
    06 ConditionsSection: ProviderLegendendpoint + run

    Two entries. Colors computed on the WHOLE edition then filtered, never on the pair

  9. 09
    OtherPairsSectionthe edition roster

    Unnumbered: it is an exit, not a measure

  10. 10
    CtaSectionconfig