Brik Design System
Theming

Blueprints

The Blueprints Theming Dimension — named layout + interaction patterns that ground AI mockup generation with concrete structural constraints.

Named layout + interaction patterns that ground AI mockup generation with concrete structural constraints. BDS owns the canonical data; portal design_blueprints is a downstream seed.

See blueprints/ARCHITECTURE.md for the two-taxonomy model, bridge rules, and v1 / v2 coexistence.

Beyond match tags, a blueprint is parameterized along curated closed-enum prop axes — structure (layout, align, columns, ratio), media, and motion (reveal, contentMotion). Motion is an axis an agent selects, not the free-text animationSuggestion prose the section contract used to carry (retired). The Theming Dimensions on this page are the style axis; the rest are structure, media, and motion. See ADR-039.

Two taxonomies

Authors hand-write match tags (moods, industries). Client-axis projections (personality, visual_style, industry_slugs) are derived at load time via the bridges — never stored in source JSON, never authored by hand.

Mood to personality

Derived by MOOD_TO_PERSONALITY in content-system/blueprints/bridges.ts — never hand-authored on blueprints.

MoodPersonality projection
boldBold
minimalMinimal
warmWarm
corporateCorporate
playfulPlayful
luxuryLuxury · Refined
trustworthyTrustworthy
energeticEnergetic
professionalProfessional
modernModern
approachableApproachable

Mood to visual style

Derived by MOOD_TO_VISUAL_STYLE in content-system/blueprints/bridges.ts. Moods with no visual correlate (warm, trustworthy, professional, approachable) project to an empty set — explicit, not a gap.

MoodVisual Style projection
boldBold
minimalMinimal
warm—
corporateClassic
playfulPlayful
luxuryLuxurious
trustworthy—
energeticColorful
professional—
modernModern
approachable—

Industry tag to pack slug

TagPack slug
dentaldental
real_estatereal-estate-rv-mhc
wellnesssmall-business (until graduated)
legalsmall-business (until graduated)
universaluniversal sentinel — no pack lookup

Catalog

The full enumerated library — every blueprint with moods, industries, layout spec, CSS hints, version, last-reviewed dates — rendered live from @brikdesigns/bds/blueprints/library.json. Coverage matrix shows section type × mood density at a glance; cells with · are gaps to author.

Every entry below is renderable: is_active: true asserts the key dispatches on at least one rail, and validate:blueprints enforces it. Designed-but-unbuilt layouts are not here — they live in blueprints/blueprint-roadmap.json, which carries no is_active flag so nothing can read it as an available-key set. A · in the coverage matrix is therefore a shipped-coverage gap, which the roadmap may already have a spec for.

Library version3.0.0
Last reviewed2026-09-09
Review cadencequarterly
Blueprint count13
Section types7

Coverage matrix

Cell value = blueprint count for that section / mood combination. Empty cells (·) are gaps — opportunities to author.

Sectionapproachableboldcorporateenergeticluxuryminimalmodernprofessionaltrustworthywarm
content_block··1···111·
cta211···1332
features11·11·1111
hero111··13231
services1·1···2211
stats·11····11·
testimonials·1··1··11·

Library

Grouped by section type. Expand any blueprint for moods, industries, layout spec, and CSS hints.

content block (1)

Logo Walllogo_wall
Moods: trustworthyprofessionalcorporatemodern
Industries: universalreal_estatesaascorporatelegal
Layout spec:

Logo / partner / trust strip. Optional centered uppercase eyebrow heading (label/lg, muted) above a row of client/partner logos. Each item is one logo image (consumer supplies a pre-monochromed SVG/PNG), optionally linked. Two motion modes via the content-motion axis (ADR-039): default `none` renders a centered wrapped flex row; `contentMotion: marquee` scrolls the strip through the Marquee primitive (seamless loop, reduced-motion-gated by construction — the track stops and wraps under prefers-reduced-motion). Logo height ~24px, generous gap (~40px). Section-driven; no required client facts.

CSS hints
.bp-logo-wall__strip { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--bds-size-1000); } .bp-logo-wall__strip[data-motion='marquee'] { display: block; } /* marquee scroll owned by the bds-marquee primitive */
Tier: internal · Source: ADR-039 §Decision 2 — content-motion axis, first marquee adopter (brik-bds#2529) · v1.0.0 · reviewed 2026-09-13

cta (3)

Centered CTActa_centered
Moods: boldprofessionalmoderntrustworthycorporate
Industries: universal
Layout spec:

Dark background (near-black or brand dark). Radial gradient glow behind content (accent color, low opacity). All content centered. Eyebrow label (uppercase, accent). Heading: 2 lines max, 52–64px, 800 weight. Single subheading sentence (muted, max 50 chars). Two CTAs centered: primary filled + ghost outlined. No body paragraph.

CSS hints
.cta-section { position: relative; } .cta-section::before { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse 70% 50% at 50% 50%, rgba(var(--accent-rgb), 0.15) 0%, transparent 70%); }
Tier: internal · Source: Vale demo · v2.0.0 · reviewed 2026-09-09
Callout Panel — Illustration + Card Splitcallout_split
Moods: approachablewarmprofessionaltrustworthy
Industries: universalsaasecommercecorporate
Layout spec:

Light section. Centered section header (heading + subhead) above. Below: two-column split, content-region (illustration block) left, plan card right. Illustration block: persona/scene composition with floating UI elements (chat bubble, message tile, optional photo) — composed via the BDS MarketingIllustration primitive (PR #484), NOT a baked image. Plan card: surface-secondary background, rounded-lg corners, padded generously. Card content: plan name (heading/sm), 2-sentence description (body/sm, on light), 'Learn more' primary CTA (size md). Two-column collapses to stacked at <992px (illustration goes above card on mobile). Section also supports an 'illustration-omitted' variant where the card centers max-width 720px.

CSS hints
.support-plan-callout { padding-block: clamp(var(--bds-padding-xl), 9vw, var(--bds-padding-huge)); background: var(--bds-page-primary); } .support-plan-callout__split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--bds-gap-xl); align-items: center; } .support-plan-callout__card { background: var(--bds-surface-secondary); border-radius: var(--bds-border-radius-lg); padding: var(--bds-padding-xl); display: flex; flex-direction: column; gap: var(--bds-gap-md); align-items: flex-start; } @media (max-width: 991.98px) { .support-plan-callout__split { grid-template-columns: 1fr; } }
Tier: internal · Source: brikdesigns.com /services/{slug} 'Monthly support services' cross-sell section (PR #477 spec) · v2.0.0 · reviewed 2026-09-09
Split CTA with Contactcta_split_contact
Moods: approachablewarmprofessionaltrustworthy
Industries: universalhealthcarelegalreal_estatebeauty
Required facts: phoneemail
Layout spec:

Light background. Two-column layout. Left: heading (2 lines, 40px), 1-sentence subheading, primary CTA button. Right: contact details (phone number large, email, optional address), each with a small icon. Separated by a thin vertical rule. Conveys "we are real, reachable people" rather than just a form prompt.

CSS hints
.cta-split { display: grid; grid-template-columns: 1fr 1px 1fr; gap: 64px; align-items: center; } .cta-divider { background: var(--rule-light); align-self: stretch; }
Tier: internal · Source: Original research · v1.0.0 · reviewed 2026-09-08

features (2)

3-Column Feature Card Gridfeature_grid
Moods: boldmodernluxuryenergetic
Industries: universalsaasecommercecorporate
Layout spec:

Dark section background (page-inverse). 3-column grid of cards, each filled with its own brand color via [data-audience='X'] scope binding (re-binds --bds-background-brand-primary per card). Card layout: oversized illustration top (1:1 aspect, ~60-70% of card height, padded inside the brand color), then card body with high-contrast title (heading/sm, font-weight bold for AA on saturated bg), 1-sentence description (body/sm at 16px regular for large-text 3:1 threshold), and 'Learn more' affordance with arrow. Cards rounded-lg, full-bleed image at top, body padding generous. Section header centered above grid in light text on dark surface. Optional eyebrow above heading. Cards collapse to 2-col at <992px, 1-col at <768px. Each card establishes its own data-audience subtree binding so its --brand-primary cascades correctly per the BDS scope-binding pattern (consumer site defines [data-audience='X'] cascade rules).

CSS hints
.features-branded-dark { background: var(--bds-page-inverse); padding-block: clamp(var(--bds-padding-xl), 9vw, var(--bds-padding-huge)); color: var(--bds-text-on-color-dark); } .features-branded-dark__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--bds-gap-lg); } .features-branded-dark__card { background: var(--bds-background-brand-primary); border-radius: var(--bds-border-radius-lg); overflow: hidden; } .features-branded-dark__media { aspect-ratio: 1; padding: var(--bds-padding-xl); display: flex; align-items: center; justify-content: center; } .features-branded-dark__body { padding: var(--bds-padding-lg); display: flex; flex-direction: column; gap: var(--bds-gap-md); }
Tier: internal · Source: brikdesigns.com /services/{slug} 'Other Service Lines' cross-sell module (PR #477 spec) · v2.0.0 · reviewed 2026-09-09
Story Splitstory_split
Moods: warmtrustworthyapproachableprofessional
Industries: universalhealthcarelegaldentalveterinaryreal_estatefinance
Layout spec:

Two-column layout for About / Story sections: left 55% is body content — eyebrow label, H2 headline (36–44px, 700 weight), 2–3 short paragraphs, optional values list as small icon + label rows. Right 45% is a single portrait or team photo in a tall card with rounded corners (16px radius), optional overlapping stat chip (e.g. "12 years in business") positioned bottom-left of the photo. Vertical rhythm: section is 100–120px tall padding.

CSS hints
.about-split { display: grid; grid-template-columns: 55fr 45fr; gap: 64px; align-items: center; } .about-photo { border-radius: 16px; overflow: hidden; position: relative; } .stat-chip { position: absolute; bottom: -20px; left: 24px; background: white; border-radius: 10px; padding: 12px 20px; box-shadow: 0 4px 20px rgba(0,0,0,0.12); }
Tier: internal · Source: Original research · v2.0.0 · reviewed 2026-09-09

hero (3)

Split Herohero_split
Moods: professionalboldtrustworthymodern
Industries: universalhealthcarereal_estatelegalfinancesaas
Required facts: hero_image_url
Layout spec:

Two-column layout: left 60% contains eyebrow label (12px uppercase, accent color, line before text), display headline (72–96px, font-weight 800, letter-spacing -0.04em, line-height 1.02), single subheading (1 sentence, 17px, muted color), and two CTAs side by side (primary filled + ghost outlined). Right 40% is full-height photography with dark gradient overlay bleeding from left edge. Trust signal (small text, very muted) sits below CTAs separated by a horizontal rule. No body paragraph.

CSS hints
grid-template-columns: 1fr 1fr; .hero-photo { position: relative; overflow: hidden; } .hero-photo img { height: 100%; object-fit: cover; } .hero-photo::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to right, var(--ink) 0%, transparent 30%); }
Tier: internal · Source: Framer - Buildaxa / Vale demo · v2.0.0 · reviewed 2026-09-09
Split Hero with Image Card + Price Overlayhero_split_image_card_overlay
Moods: approachablemodernwarmtrustworthy
Industries: universal
Layout spec:

Two-column 58/42 split on a soft audience-tinted background. Left column (vertical flex stack, gap-md): optional breadcrumb trail (3-5 items, brand-primary text color, '/' separators, last item aria-current=page); optional eyebrow label (uppercase, label-sm, primary text); h1 headline (display, weight bold); optional 1-3 line body paragraph (body-md, secondary text, max-width 55ch); optional single dark CTA button (small padding, dark background, white label — NOT a paired CTA group). Right column: white surface-primary card (radius-lg, soft shadow, padding-md) containing a 4:3 image-frame and an optional price overlay block underneath (label 'Starting at' / display price / brand-primary CTA button). Background tinting comes from `[data-audience='X'] { --background-brand-primary-soft: ... }` cascade declared by the consumer site — BDS ships the slot, not the values. Drives interior service-detail and similar 'page lives under a category' templates.

CSS hints
grid-template-columns: 58fr 42fr; gap: var(--bds-gap-huge); .media-card { background: var(--bds-surface-primary); border-radius: var(--bds-border-radius-lg); padding: var(--bds-padding-md); box-shadow: var(--bds-shadow-md); } .image-frame { aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--bds-border-radius-md); } [data-audience] { /* consumer-defined cascade */ }
Tier: internal · Source: brikdesigns.com /service/{slug} pages — verified 2026-05-09 audit · v1.0.0 · reviewed 2026-09-08
Interior Page Hero — Minimal Bannerhero_interior_minimal
Moods: professionalminimaltrustworthymoderncorporate
Industries: universalhealthcarelegalfinancesaascorporatedental
Layout spec:

Compact banner hero for interior pages (About, Services, Contact). Full-width section, 200–280px tall. Left-aligned breadcrumb (very small, muted) above a large page headline (48–60px, 800 weight, ink color). Optional one-sentence subheading below (muted, 16px). No CTA. Background is either solid brand-light fill or subtle diagonal stripe texture. Transitions page context before the main content area begins.

CSS hints
.interior-hero { padding: 56px 0 40px; background: var(--surface-brand-subtle, var(--bds-surface-secondary)); } .interior-hero h1 { font-size: clamp(40px, 5vw, 60px); font-weight: 800; letter-spacing: -0.03em; } .breadcrumb { font-size: 12px; color: var(--bds-text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 12px; }
Tier: internal · Source: Original research · v1.0.0 · reviewed 2026-09-08

services (2)

Two-Column Detail Gridtwo_column_detail
Moods: professionaltrustworthymoderncorporate
Industries: universalhealthcaredentallegalfinancereal_estatesaascorporate
Layout spec:

Services or offerings detail layout. Section heading + subheading centered at top. Below: 2-column grid of service cards (3–6 cards typical). Each card: icon top-left (32px, accent color), service name (18px, 600 weight), 2-sentence description (14px, muted), optional price or tier badge bottom-right, optional "Learn more" text link at bottom. Cards have subtle border (1px rule color), 16px radius, 28px internal padding. Hover: elevate with box-shadow transition.

CSS hints
.services-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; } .service-card { border: 1px solid var(--bds-border-primary); border-radius: 16px; padding: 28px; transition: box-shadow 0.2s; } .service-card:hover { box-shadow: 0 8px 32px rgba(0,0,0,0.08); }
Tier: internal · Source: Original research · v2.0.0 · reviewed 2026-09-09
3-Column Card Gridcard_grid
Moods: approachableprofessionalmodernwarm
Industries: universalsaasecommercecorporate
Layout spec:

Light background section. Centered section header (eyebrow optional + heading + optional one-line subhead). 3-column grid of service cards below. Each card: top image area (3:2 aspect) showing service-specific 3D illustration or photo on a light backdrop; below, a small ServiceTag (icon variant, accent color) + service name (heading/sm, 700 weight) + 1-2 sentence description (body/sm, on light) + 'Learn more' ghost-variant link-button. Optional 'Has Options' positive-status badge anchored top-right of card when the service exposes multiple offerings. Cards have rounded corners (border-radius-md), no border at rest, optional subtle hover lift. Grid gap is generous (24-28px). Collapses to 2-col at <992px, 1-col at <768px.

CSS hints
.services-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--bds-gap-lg); } .service-card { background: var(--bds-surface-primary); border-radius: var(--bds-border-radius-md); overflow: hidden; position: relative; } .service-card__media { aspect-ratio: 3/2; background: var(--bds-surface-secondary); } .service-card__body { padding: var(--bds-padding-lg); display: flex; flex-direction: column; gap: var(--bds-gap-md); } .service-card__has-options { position: absolute; top: var(--bds-gap-md); right: var(--bds-gap-md); }
Tier: internal · Source: brikdesigns.com /services/{slug} index pages — service-line card grid pattern (PR #477 spec) · v2.0.0 · reviewed 2026-09-09

stats (1)

Stats Barstats_bar
Moods: boldprofessionaltrustworthycorporate
Industries: universalreal_estatelegalfinancehealthcare
Layout spec:

Full-width dark background strip (sits between hero and first content section). 4 metrics in equal columns separated by 1px vertical rules. Each metric: large number (40–48px, 800 weight, white) with colored accent suffix (+ % B yr), label below in small muted text (2 lines max, 13px). No heading — the numbers speak. Counter animation on scroll-into-view.

CSS hints
.stats-bar { display: grid; grid-template-columns: repeat(4, 1fr); } .stat-col { padding: 32px 24px; border-right: 1px solid rgba(255,255,255,0.07); } .stat-col:last-child { border-right: none; } .stat-num { font-size: clamp(28px, 3vw, 44px); font-weight: 800; }
Tier: internal · Source: Vale demo / Buildaxa · v2.0.0 · reviewed 2026-09-09

testimonials (1)

Featured Large Testimonialtestimonials_featured_large
Moods: luxuryboldprofessionaltrustworthy
Industries: universalluxuryreal_estatelegal
Layout spec:

Dark or accent-tinted background. Single large testimonial centered. Quote mark (large decorative, accent color, 80px). Quote text is large (20–24px, light weight, italic, white, max 2 lines). Author avatar (60px circle), name, and title below. Optional: 2–3 smaller secondary quotes in a row below the featured quote at smaller size.

CSS hints
.testimonial-featured { text-align: center; max-width: 720px; margin: 0 auto; } .quote-mark { font-size: 80px; line-height: 1; color: var(--accent); font-family: Georgia, serif; } .quote-text { font-size: clamp(18px, 2vw, 24px); font-style: italic; font-weight: 300; }
Tier: internal · Source: Original research · v1.0.0 · reviewed 2026-09-08

Two rails, one canonical

Blueprints ship on two renderers, and they are not peers. ADR-037 §1 makes Astro canonical: it carries every published client site, so where the rails disagree, Astro's implementation is the reference and React is brought to it.

Site classRailContent sourceEntry point
Standard client siteAstro (canonical)in-repo content@brikdesigns/bds/blueprints-astro → <BlueprintDispatcher>
Client site with a CMS or database; brikdesigns.comReact / Next.jsportal Supabase@brikdesigns/bds/blueprints-react → <BlueprintDispatcher>

React is a supported rail, not a lesser one — and it is the source of the composition API both rails now share. React named files by block with the layout as a prop first; ADR-037's 2026-09-08 amendment brought Astro onto that shape, so today a component is a block on either rail and layout is a prop. The HeroLayout / CtaLayout / CardGridLayout unions live in one framework-agnostic module (astro/types.ts) that both rails read, so a layout cannot be added to one rail only.

Names carry layout, never content domain. ADR-037 §4: a blueprint key describes layout shape only. card_grid is a key; a domain prefix naming the content it happens to hold is not, because the same grid renders team, blog and product collections. Industry and mood are metadata on the library entry; brand and atmosphere are tokens. Column counts and ratios are props. scripts/lint-blueprint-naming.mjs enforces this as blueprint-key-context-word, with no allowlist.

Implementation

The Astro render surface the Theming tenet has always pointed at. Each blueprint key with a shipped Astro component is exported from this package; consumer Astro sites import the components directly or dispatch by key via <BlueprintDispatcher>.

See BLUEPRINTS-ASTRO-PACKAGE.md for the architecture contract, versioning policy, and scale-at-100-clients deployment topology.

Package exports

---
// Consumer Astro page — the intended import shape.
import {
  SiteHeader,
  BlueprintDispatcher,
  // Individual blocks if you want direct imports:
  Hero,
  // Types:
  type BlueprintProps,
  type ClientFacts,
  type ResolvedTheme,
  type HeroLayout,
} from '@brikdesigns/bds/blueprints-astro';
---
<SiteHeader archetype={...} brandName={...} navItems={[...]} />
<main>
  <BlueprintDispatcher sections={page.sections}
                       clientFacts={clientFacts}
                       theme={theme} />
</main>

Types-only entry for contexts without the Astro runtime (e.g. the portal's scaffold task that plans compositions):

import type { BlueprintSection, KnownBlueprintKey }
  from '@brikdesigns/bds/blueprints-astro/types';

Dispatch surface

ComponentPurposeProps shape
<BlueprintDispatcher>Reads visualNotes.blueprintKey per section and renders the matching component. Unknown keys fall through to <BlueprintFallback>.{ sections, clientFacts, theme }
<BlueprintFallback>Loud visible stub for unknown blueprint keys. Emits data-blueprint-unknown-key — CI greps client-repo builds for this attribute.BlueprintProps
<SiteHeader>Site-shell nav. Dispatches on the navigation archetype prop. v0.1 fully implements editorial-transparent; other archetypes render with a data-unimplemented-archetype attribute.{ archetype, brandName, navItems, phone?, primaryCta?, currentPath? }

Shipped blocks

Eight components. A component is a block; the layout it renders in is a prop, never a filename — so twelve blueprint keys resolve onto eight files. Each follows the same BlueprintProps contract (section + clientFacts + theme), plus layout where the block has more than one.

<BlueprintDispatcher> owns the key → (block, layout) mapping, so a consumer that dispatches never picks a layout by hand.

ComponentlayoutLibrary keySection typeStorybook
<Hero>splithero_splitheroastro-hero — Default
<Hero>interior-minimalhero_interior_minimalheroastro-hero — Interior Minimal
<Hero>with-pricing-cardhero_split_image_card_overlayheroastro-hero — With Pricing Card
<CardGrid>card-gridcard_gridservicesastro-card-grid — Default
<CardGrid>two-column-listtwo_column_detailservicesastro-card-grid — Two Column List
<Cta>splitcta_split_contactctaastro-cta — Split
<Cta>defaultcta_centeredctaastro-cta — Default
<Narrative>—story_splitaboutastro-narrative — Default
<Features>—feature_gridfeaturesastro-features — Default
<CalloutPanel>—callout_splitsupport_planastro-callout-panel — Default
<StatsBar>—stats_barstatsastro-stats-bar — Default
<TestimonialsFeaturedLarge>—testimonials_featured_largetestimonialsastro-testimonials-featured-large — Default

The HeroLayout / CtaLayout / CardGridLayout unions are exported from the package and shared with the React rail, so a layout cannot be added to one rail only.

The Blueprints/astro-* entries render this rail's own output, pre-rendered by scripts/render-astro-blueprints.mjs rather than by the React twin (ADR-039). Their Blueprints/* neighbours without the astro- prefix are the React twins — same fixtures, different rail, which is what makes the two comparable side by side.

Unshipped keys render <BlueprintFallback> when the dispatcher encounters them — expected during the v0.1 → v1.0 incremental ramp. Each follow-up PR adds one or more components and removes its key from the fallback case.

Contract per blueprint

Every blueprint component accepts the same props shape:

interface BlueprintProps {
  section: BlueprintSection;      // content: heading, body, items, cta, visualNotes
  clientFacts: ClientFacts;       // per-client: brandName, phone, heroImageUrl, etc.
  theme: ResolvedTheme;           // archetypes + atmosphere + theme mode
}

This uniformity is deliberate — the dispatcher is trivial (one lookup, one pass-through), every blueprint's surface is identical for authoring / review, and per-client customization happens through ClientFacts + CSS custom properties (not per-component props).

Per-client CSS overrides

Each blueprint exposes documented CSS custom properties for per-client tuning — for example:

.bp-hero-split-60-40 {
  --bds-hero-split-eyebrow-color: ...;
  --bds-hero-split-accent-line: ...;
  --bds-hero-split-image-radius: ...;
  /* ... more, see each component's header comment */
}

Per-client overrides MUST live in the client repo's src/styles/client-overrides.css with a /* BDS-ISSUE: <url> */ comment on the preceding line. CI in each client repo enforces the comment requirement. See spec §6.3 for rationale.

Non-hallucinatable content

Blueprints with required_facts render a visible data-content-needed="<field>" stub when the fact is null at render time — CI grep blocks publish. This is defense-in-depth; the portal's dev_scaffold_site task preflights required_facts before generating the client repo, so a missing fact should never reach the build stage.

Verification

The package has a dedicated verification script at scripts/verify-blueprints-astro-exports.mjs that runs on every BDS pre-push:

  1. Packs a tarball matching a real publish.
  2. Creates a scratch Astro 5 project, installs the tarball.
  3. astro check — type + import resolver.
  4. astro build — SSR render to static HTML.
  5. Asserts rendered HTML markers per blueprint.
  6. @axe-core/playwright scan against every built page (WCAG 2.1 AA).
  7. Confirms all expected files shipped in the tarball.

Any failure blocks the PR.

Authoring

Blueprint edits flow through BDS. Portal admin edits (if kept) are drafts — landed changes flow back through a BDS PR. Full rules in Architecture.

Pick the file first — a layout with no component belongs in the roadmap, never the library:

You are addingFile
A blueprint you are shipping in this PR (component wired on a rail)blueprints/blueprint-library.json
A layout spec with nothing built yetblueprints/blueprint-roadmap.json
  1. Edit the file the table names, on a task branch. Graduating a roadmap candidate moves it into the library — the validator rejects a key present in both.
  2. Run npm run validate:blueprints (also runs as part of npm run validate). A library entry must dispatch on a rail; a roadmap candidate must not, and must not carry is_active.
  3. Bump version on the affected blueprint(s) and the library envelope if the set changes. Update last_reviewed on confirmed-accurate passes — review_cadence is enforced, so a lapsed window fails the build.
  4. Open a PR. Bridge edits, schema changes, and data additions stay separate.
  5. After merge: publish the new BDS version, then bring the portal's design_blueprints across in a new numbered migration. npx tsx scripts/generate-blueprint-seed.mts regenerates 00114 in place, and Supabase does not re-run an applied migration — so regenerating alone changes the repo and never the database. A rename or a removal needs its own migration (brik-client-portal/supabase/migrations/00390_rename_blueprint_keys_context_free.sql is the worked example, from #2303). Tracked at brik-client-portal#3952.

On this page

💬