{"id":869,"slug":"client-bjf-craft-signals-structural-v2","title":"B&J — five structural craft signals worth surfacing in case-study narrative (v2)","kind":"reference","scope":"client-case-studies","status":"current","audiences":["kevin","candid-team","client-prospect"],"topics":["editorial-discipline","client-boucher-jones","case-study-source","architectural-decisions","narrative-angles"],"reference_body":"Five structural details surfaced in the v2 sweep that would read well in a case study — each verifiable from the repo or live site.\n\n## 1. Two-tier component model (kit primitives + sections), enforced by convention\n\nThe repo deliberately splits `src/components/ui/kit/` (**19 single-concept primitives** — buttons, dark surfaces, gauges) from `src/components/sections/` (**33 labelled, `aria-labelled` page sections** composed from primitives).\n\n- Pages compose **sections**, never primitives directly.\n- The trigger to promote inline JSX into a real section is **the second occurrence of the pattern.**\n- Documented in `src/components/sections/SECTIONS.md`.\n- Result: App Router page files stay thin — typically **50–150 lines of \"configuration\"** against typed content modules.\n\n## 2. Schema infrastructure is helper-ised, not hand-rolled per page\n\nEvery JSON-LD block on the site goes through one of **9 functions in `src/lib/schema.ts`** (`organizationSchema`, `localBusinessSchema`, `breadcrumbSchema`, `buildBreadcrumbFromPath`, `faqPageSchema`, `articleSchema`, `serviceSchema`, etc.).\n\n- The Organization `@id` is a **single canonical entity** emitted once in the root layout.\n- Every per-page schema references it via `{ \"@id\": ORG_ID }`.\n- An audit can land on any page (homepage, vertical hub, resource article, location page) and find a **consistent graph** — no duplicated literal in any page file.\n\nSee [[client-bjf-schema-deployment-verified-v2]] for the live verification.\n\n## 3. Service-functions-own-the-DB convention, lint-enforced\n\n**ESLint bans `pg` imports outside `src/lib/`.** Combined with the \"thin route handler\" pattern, this means a future portal split (data layer → separate Express service) is a **mechanical extraction, not a rewrite**.\n\nThe migration rationale is documented in `CLAUDE.md` (\"the three migration rules\") — worth quoting in the case study as an example of **architectural foresight that costs almost nothing today but pays off when the contract for the portal is signed**.\n\n## 4. Strict-from-day-one TypeScript + husky-gated commits\n\n- `strict: true`\n- `noUnusedLocals`\n- `noUnusedParameters`\n- `noFallthroughCasesInSwitch`\n- `noImplicitOverride`\n- `allowJs: false`\n- ESLint runs with `--max-warnings 0` (warnings are errors)\n- Both gated via **husky pre-commit**\n\n**185 commits in, the lint baseline has held — zero `// @ts-ignore`, zero `any` without rationale.**\n\n## 5. Single design-token source, no Tailwind config file\n\nTokens live in `src/app/globals.css` inside a **`@theme inline` block** (Tailwind v4 pattern). Brand colours, surface tokens, type scale, motion easings, layout dimensions — all expressed once as CSS custom properties, surfaced through Tailwind utilities.\n\nThe whole site renders against **one `--color-surface-card-dark` (`#141413`)** for every dark surface — no near-blacks, no alternate shades.\n\n> **`CLAUDE.md` spells out the rule and the rationale:** *two near-blacks side-by-side on `/agriculture` \"read as cheap.\"*\n\nA small detail that materially distinguishes the site from a default shadcn build. See [[client-bjf-image-asset-inventory-v2]] for the broader \"type + color + CSS shape, not imagery\" approach this enables.","rationale_body":null,"metadata":null,"links":{"outgoing":[{"slug":"client-bjf-marketing-site-stack","title":"B&J marketing site stack (`bj-next`, dev URL `bjweb.candidcreative.ca`) — VERIFIED LIVE STACK","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-arch-decisions-ranked","title":"B&J architectural decisions worth surfacing in case-study narrative — eight, ranked","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-schema-deployment-verified-v2","title":"B&J — JSON-LD schema deployment VERIFIED (v2) — supersedes the \"biggest technical gap\" claim in v1","kind":"reference","scope":"client-case-studies","link_type":"relates-to"}],"incoming":[{"slug":"client-bjf-case-study-source-v2","title":"Boucher & Jones — case-study source material, v2 (technical facts, 2026-05-24)","kind":"reference","scope":"client-case-studies","link_type":"relates-to"},{"slug":"client-bjf-image-asset-inventory-v2","title":"B&J — image and asset inventory (v2, verified 2026-05-24)","kind":"reference","scope":"client-case-studies","link_type":"relates-to"}]},"created_at":"2026-05-24T01:16:37.181Z","updated_at":"2026-05-24T01:16:37.181Z"}