create-ailk 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +43 -4
  2. package/component-catalog.json +146 -21
  3. package/component-catalog.md +9 -6
  4. package/dist/add-module-core.d.ts +22 -0
  5. package/dist/add-module-core.js +50 -0
  6. package/dist/add-module.d.ts +89 -0
  7. package/dist/add-module.js +334 -0
  8. package/dist/category-profile.d.ts +126 -0
  9. package/dist/category-profile.js +262 -0
  10. package/dist/cli.js +73 -11
  11. package/dist/index.d.ts +4 -2
  12. package/dist/index.js +6 -1
  13. package/dist/lib/extract-module-bundle.d.ts +56 -1
  14. package/dist/lib/extract-module-bundle.js +165 -13
  15. package/dist/lib/license-key-files.d.ts +15 -0
  16. package/dist/lib/license-key-files.js +102 -0
  17. package/dist/lib/pro-callout.d.ts +16 -10
  18. package/dist/lib/pro-callout.js +26 -3
  19. package/dist/license-set.d.ts +34 -0
  20. package/dist/license-set.js +194 -0
  21. package/dist/module-architecture.d.ts +20 -0
  22. package/dist/module-architecture.js +77 -19
  23. package/dist/modules/commerce/0.6.1.tar.gz +0 -0
  24. package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
  25. package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
  26. package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
  27. package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
  28. package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
  29. package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
  30. package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
  31. package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
  32. package/dist/modules/workspace/0.6.1.tar.gz +0 -0
  33. package/dist/parse-args.d.ts +7 -0
  34. package/dist/parse-args.js +23 -1
  35. package/dist/programmatic.d.ts +46 -0
  36. package/dist/programmatic.js +130 -9
  37. package/dist/site-chrome.d.ts +18 -7
  38. package/dist/site-chrome.js +32 -14
  39. package/dist/site-roster.d.ts +127 -0
  40. package/dist/site-roster.js +494 -0
  41. package/dist/surfaces.d.ts +20 -7
  42. package/dist/surfaces.js +149 -28
  43. package/dist/sync-routes.d.ts +9 -0
  44. package/dist/sync-routes.js +2 -2
  45. package/dist/template-manifest.d.ts +58 -2
  46. package/dist/template-manifest.js +196 -69
  47. package/package.json +6 -4
  48. package/site-templates/_base/content/en/BookCall/book-call.mdx +53 -0
  49. package/site-templates/_base/content/en/GlossaryList/glossary.mdx +66 -0
  50. package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +68 -0
  51. package/site-templates/_base/content/en/Pricing/pricing.mdx +71 -62
  52. package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +2 -3
  53. package/site-templates/_base/content/en/TermsPage/terms.mdx +2 -3
  54. package/site-templates/_base/content/en/UseCase/first-use-case.mdx +23 -0
  55. package/site-templates/_base/content/en/UseCase/second-use-case.mdx +23 -0
  56. package/site-templates/_base/content/en/UseCase/third-use-case.mdx +23 -0
  57. package/site-templates/designs/minimalism/DESIGN.md +162 -0
  58. package/site-templates/designs/standard/DESIGN.md +162 -0
  59. package/site-templates/marketing-site/DESIGN.md +55 -41
  60. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +312 -57
  61. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +209 -90
  62. package/site-templates/marketing-site/ailk-template.json +1 -0
  63. package/site-templates/marketing-site-free/DESIGN.md +55 -41
  64. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +260 -66
  65. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +294 -114
  66. package/site-templates/marketing-site-free/ailk-template.json +3 -2
  67. package/site-templates/minimalism-site/DESIGN.md +54 -40
  68. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +246 -19
  69. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +185 -51
  70. package/site-templates/minimalism-site/ailk-template.json +3 -2
  71. package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +53 -0
  72. package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +3 -37
  73. package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +124 -0
  74. package/site-templates/saas-product/DESIGN.md +55 -41
  75. package/site-templates/simple-service/DESIGN.md +55 -41
  76. package/site-templates/simple-service/TEMPLATE-MANIFEST.json +135 -26
  77. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +114 -59
  78. package/site-templates/simple-service/ailk-template.json +4 -3
  79. package/site-templates/simple-service/content/en/BookCall/book-call.mdx +53 -0
  80. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +1 -36
  81. package/site-templates/simple-service/content/en/PurchasePolicyPage/purchase-policy.mdx +124 -0
  82. package/templates/.claude/settings.json +15 -0
  83. package/templates/.claude/skills/README.md +8 -8
  84. package/templates/.claude/skills/{scaffold-auth → add-auth}/SKILL.md +7 -7
  85. package/templates/.claude/skills/{scaffold-auth → add-auth}/references/env-vars.md +2 -2
  86. package/templates/.claude/skills/{scaffold-auth → add-auth}/references/oauth-app-setup.md +3 -3
  87. package/templates/.claude/skills/{scaffold-page → add-page}/SKILL.md +76 -62
  88. package/templates/.claude/skills/add-page/references/page-types.md +111 -0
  89. package/templates/.claude/skills/{scaffold-page → add-page}/templates/content.mdx.tmpl +4 -4
  90. package/templates/.claude/skills/{scaffold-page → add-page}/templates/route.tsx.tmpl +1 -1
  91. package/templates/.claude/skills/{audit-site → check-site}/SKILL.md +16 -17
  92. package/templates/.claude/skills/{audit-site → check-site}/references/common-errors.md +3 -3
  93. package/templates/.claude/skills/{audit-site → check-site}/references/findings-glossary.md +16 -14
  94. package/templates/.claude/skills/{audit-site → check-site}/references/severity-levels.md +1 -1
  95. package/templates/.claude/skills/fill-page/SKILL.md +180 -0
  96. package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +80 -0
  97. package/templates/.claude/skills/fill-page/references/section-sources.md +41 -0
  98. package/templates/.claude/skills/{provision-config → setup-deploy}/SKILL.md +8 -8
  99. package/templates/.claude/skills/{provision-config → setup-deploy}/references/env-vars-template.md +2 -2
  100. package/templates/.claude/skills/{provision-config → setup-deploy}/references/runbook-template.md +8 -8
  101. package/templates/.claude/skills/{provision-config → setup-deploy}/references/vercel-json-template.md +1 -1
  102. package/templates/.claude/skills/upgrade-plan/SKILL.md +117 -0
  103. package/templates/.claude/skills/upgrade-plan/references/options.md +24 -0
  104. package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +527 -0
  105. package/templates/.github/workflows/ci.yml +5 -0
  106. package/templates/CLAUDE.md +8 -2
  107. package/templates/DESIGN.md +52 -45
  108. package/templates/README.md +108 -46
  109. package/templates/apps/api/.env.example +2 -1
  110. package/templates/apps/api/package.json +1 -1
  111. package/templates/apps/api/src/config/__tests__/index.test.ts +37 -2
  112. package/templates/apps/api/src/config/index.ts +19 -6
  113. package/templates/apps/api/src/lib/license-key-store.ts +45 -0
  114. package/templates/apps/api/src/lib/site.ts +5 -3
  115. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +97 -0
  116. package/templates/apps/api/src/middleware/auth.ts +9 -0
  117. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +127 -5
  118. package/templates/apps/api/src/routes/content/get-page.ts +86 -2
  119. package/templates/apps/api/src/server.ts +6 -0
  120. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +75 -1
  121. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +57 -9
  122. package/templates/apps/mcp/package.json +2 -1
  123. package/templates/apps/mcp/src/index.ts +7 -0
  124. package/templates/apps/mcp/src/lib/audit-single-page.ts +36 -10
  125. package/templates/apps/mcp/src/lib/license-key-store.ts +45 -0
  126. package/templates/apps/web/__tests__/setup.ts +18 -0
  127. package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +10 -2
  128. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +2 -2
  129. package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +10 -4
  130. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +22 -14
  131. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +26 -18
  132. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +12 -4
  133. package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +35 -4
  134. package/templates/apps/web/app/[locale]/[slug]/page.tsx +49 -9
  135. package/templates/apps/web/app/[locale]/book-a-call/page.tsx +50 -0
  136. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
  137. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
  138. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +3 -4
  139. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +94 -33
  140. package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +53 -23
  141. package/templates/apps/web/app/[locale]/contact/__tests__/ContactForm.test.tsx +96 -0
  142. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +84 -2
  143. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +5 -6
  144. package/templates/apps/web/app/[locale]/contact/page.tsx +25 -7
  145. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
  146. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +3 -4
  147. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +4 -5
  148. package/templates/apps/web/app/[locale]/glossary/page.tsx +50 -0
  149. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
  150. package/templates/apps/web/app/[locale]/how-to/page.tsx +25 -15
  151. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
  152. package/templates/apps/web/app/[locale]/layout.tsx +113 -51
  153. package/templates/apps/web/app/[locale]/newsletter/page.tsx +50 -0
  154. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
  155. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
  156. package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +4 -5
  157. package/templates/apps/web/app/[locale]/{shipping → purchase-policy}/page.tsx +15 -10
  158. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +4 -5
  159. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
  160. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +14 -1
  161. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
  162. package/templates/apps/web/app/[locale]/software/page.tsx +25 -15
  163. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
  164. package/templates/apps/web/app/[locale]/tech-articles/page.tsx +25 -15
  165. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +3 -4
  166. package/templates/apps/web/app/[locale]/use-cases/[slug]/page.tsx +48 -0
  167. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +3 -4
  168. package/templates/apps/web/app/[locale]/use-cases/page.tsx +15 -2
  169. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
  170. package/templates/apps/web/app/[locale]/whitepapers/page.tsx +25 -15
  171. package/templates/apps/web/app/error-fallback.tsx +17 -45
  172. package/templates/apps/web/app/not-found.tsx +14 -38
  173. package/templates/apps/web/app/og/route.tsx +6 -0
  174. package/templates/apps/web/eslint.config.mjs +3 -0
  175. package/templates/apps/web/instrumentation.ts +14 -0
  176. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +38 -0
  177. package/templates/apps/web/lib/license-key-store.ts +52 -0
  178. package/templates/apps/web/lib/nav-config.ts +64 -12
  179. package/templates/apps/web/lib/prisma-for-auth.ts +9 -6
  180. package/templates/apps/web/lib/site-brand.tsx +1 -1
  181. package/templates/apps/web/lib/site-chrome.ts +3 -3
  182. package/templates/apps/web/lib/site-identity.ts +134 -0
  183. package/templates/apps/web/lib/site-theme.ts +11 -0
  184. package/templates/apps/web/messages/en.json +52 -37
  185. package/templates/apps/web/public/android-chrome-192x192.png +0 -0
  186. package/templates/apps/web/public/android-chrome-512x512.png +0 -0
  187. package/templates/apps/web/public/apple-touch-icon.png +0 -0
  188. package/templates/apps/web/public/favicon-16x16.png +0 -0
  189. package/templates/apps/web/public/favicon-32x32.png +0 -0
  190. package/templates/apps/web/public/favicon.ico +0 -0
  191. package/templates/apps/web/public/favicon.svg +3 -3
  192. package/templates/apps/web/public/logomark.svg +6 -3
  193. package/templates/apps/web/public/logos/ai-launch-kit-light.svg +4 -0
  194. package/templates/apps/web/public/logos/ai-launch-kit.svg +4 -0
  195. package/templates/apps/web/public/logos/atomic-agent-light.svg +4 -0
  196. package/templates/apps/web/public/logos/atomic-agent.svg +4 -0
  197. package/templates/apps/web/public/logos/salessmyth-light.svg +4 -0
  198. package/templates/apps/web/public/logos/salessmyth.svg +4 -0
  199. package/templates/apps/web/public/site.webmanifest +4 -4
  200. package/templates/apps/web/public/wordmark-light.svg +4 -0
  201. package/templates/apps/web/public/wordmark.svg +3 -3
  202. package/templates/apps/web/security-headers.config.ts +5 -1
  203. package/templates/content/_site.mdx +23 -0
  204. package/templates/content/en/AboutPage/about.mdx +150 -144
  205. package/templates/content/en/BlogList/blog.mdx +105 -0
  206. package/templates/content/en/ContactPage/contact.mdx +44 -85
  207. package/templates/content/en/FAQPage/faq.mdx +86 -57
  208. package/templates/content/en/HomePage/home.mdx +276 -217
  209. package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +182 -0
  210. package/templates/content/en/SoftwareProduct/product.mdx +175 -0
  211. package/templates/content/en/UseCasesList/use-cases.mdx +170 -0
  212. package/templates/database/CHANGELOG.md +7 -0
  213. package/templates/database/package.json +1 -1
  214. package/templates/package.json +3 -1
  215. package/templates/tools/lint-architecture.ts +315 -0
  216. package/templates/tools/tsconfig.json +14 -0
  217. package/versions.json +33 -33
  218. package/templates/.claude/skills/add-schema/SKILL.md +0 -277
  219. package/templates/.claude/skills/add-schema/references/conflict-handling.md +0 -200
  220. package/templates/.claude/skills/add-schema/references/file-finding.md +0 -123
  221. package/templates/.claude/skills/add-schema/references/schema-types.md +0 -234
  222. package/templates/.claude/skills/scaffold-page/references/page-types.md +0 -169
  223. package/templates/.claude/skills/suggest-site-pages/SKILL.md +0 -242
  224. package/templates/.claude/skills/suggest-site-pages/references/categories.md +0 -287
  225. package/templates/apps/web/app/[locale]/cancellation/page.tsx +0 -44
  226. package/templates/apps/web/app/[locale]/returns/page.tsx +0 -44
  227. package/templates/content/en/CancellationPolicyPage/cancellation.mdx +0 -108
  228. package/templates/content/en/LandingPage/blog.mdx +0 -83
  229. package/templates/content/en/LandingPage/features.mdx +0 -103
  230. package/templates/content/en/LandingPage/how-it-works.mdx +0 -143
  231. package/templates/content/en/ReturnsPolicyPage/returns.mdx +0 -108
  232. package/templates/content/en/ShippingPolicyPage/shipping.mdx +0 -108
@@ -16,13 +16,13 @@
16
16
 
17
17
  ## 1. Chrome (every page)
18
18
 
19
- | Piece | Component | Props that matter | Status |
20
- | ---------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
21
- | Shell | `MarketingShell` | `gutters="plain"`, `contentOwnsMain`, `bannerPlacement="above-nav"` | ✅ |
22
- | Announcement bar | `Banner` (chrome) | `variant="contrast"`, `routes={{ include: ["/"] }}` — **home only**, no dismiss | ✅ · 🔧 #5558 message colour |
23
- | Nav | `Nav` → `BrandLogo` (mark + wordmark, mark-only < md) | items: Product (flyout: How it works · Features · FAQ) · How it works · Pricing · About; actions: Get started (primary → `/contact`), Sign in (outline → `/sign-in`); `showThemeToggle={false}`; mobile = mark + hamburger only | ✅ |
24
- | Footer | `Footer` → `FooterBottomBar` | columns: Site pages · Product · Legal · Subscribe (`Newsletter` block); bottom bar: theme toggle · © 2026 SalesSmyth LLC · Privacy Policy · Terms of Service · social ×5 · `LocaleSwitcher` | ✅ bar · 🟡 columns + subscribe · 🔧 `LanguageSwitcher` client wrapper is scaffold code, not a block |
25
- | Cookie consent | `Banner variant="info"` + `BannerConsentIsland` (bottom) | consent copy from `messages/en.json`; hidden on the sample | 🔧 #5557 |
19
+ | Piece | Component | Props that matter | Status |
20
+ | ---------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
21
+ | Shell | `MarketingShell` | `gutters="none"` (#6536 — no gutter frame, so header/sections/footer share one left/right edge), `contentOwnsMain`, `bannerPlacement="above-nav"` | ✅ |
22
+ | Announcement bar | `Banner` (chrome) | `variant="contrast"`, `routes={{ include: ["/"] }}` — **home only**, no dismiss; **off by default** (#6469), on with `layout.announcementBanner: true` | ✅ · 🔧 #5558 message colour |
23
+ | Nav | `Nav` → `BrandLogo` (mark + wordmark, mark-only < md) | items: Product (flyout: How it works · Features · FAQ) · How it works · Pricing · About; actions: Get started (primary → `/contact`), Sign in (outline → `/sign-in`); `showThemeToggle={false}`; mobile = mark + hamburger only; `frame="contained"` (#6536 — puts the header row on the section Container's edge, matching `gutters="none"`) | ✅ |
24
+ | Footer | `Footer` → `FooterBottomBar` | columns: Site pages · Product · Legal · Subscribe (`Newsletter` block); bottom bar: theme toggle · © 2026 SalesSmyth LLC · Privacy Policy · Terms of Service · social ×5 · `LocaleSwitcher`; `bottomBarAlign="content"` (#6536 — puts the footer divider on the same edge, forwarded to `FooterBottomBar`'s own `bleed={false}`) | ✅ bar · 🟡 columns + subscribe · 🔧 `LanguageSwitcher` client wrapper is scaffold code, not a block |
25
+ | Cookie consent | `Banner variant="info"` + `BannerConsentIsland` (bottom) | consent copy from `messages/en.json`; hidden on the sample | 🔧 #5557 |
26
26
 
27
27
  ### Layout knobs (#5612)
28
28
 
@@ -39,77 +39,123 @@ The template's `layout` block — resolved with `resolveSiteChrome`, defaults fi
39
39
 
40
40
  <!-- generated:end -->
41
41
 
42
+ ### Theme (locked)
43
+
44
+ The template's `theme:` block as `_site.mdx` declares it — the shape knobs and the colour overlay. Generated, so a change to a locked template's look is a red `manifest:check`, not a silent drift (starter-template contract R3.5).
45
+
46
+ <!-- generated:begin theme -->
47
+
48
+ | Setting | Value |
49
+ | ------------------------ | ---------- |
50
+ | `corners` | `square` |
51
+ | `eyebrowCase` | `sentence` |
52
+ | `placeholders` | `fill` |
53
+ | `checkmarks` | `plain` |
54
+ | `colors.light.bg` | `#ffffff` |
55
+ | `colors.light.bgMuted` | `#ffffff` |
56
+ | `colors.light.surface` | `#ffffff` |
57
+ | `colors.light.border` | `#000000` |
58
+ | `colors.light.text` | `#000000` |
59
+ | `colors.light.textMuted` | `#333333` |
60
+ | `colors.light.primary` | `#000000` |
61
+ | `colors.light.primaryFg` | `#ffffff` |
62
+ | `colors.light.accent` | `#000000` |
63
+ | `colors.dark.bg` | `#000000` |
64
+ | `colors.dark.bgMuted` | `#000000` |
65
+ | `colors.dark.surface` | `#000000` |
66
+ | `colors.dark.border` | `#ffffff` |
67
+ | `colors.dark.text` | `#ffffff` |
68
+ | `colors.dark.textMuted` | `#cccccc` |
69
+ | `colors.dark.primary` | `#ffffff` |
70
+ | `colors.dark.primaryFg` | `#000000` |
71
+ | `colors.dark.accent` | `#ffffff` |
72
+
73
+ <!-- generated:end -->
74
+
42
75
  ## 2. Pages
43
76
 
44
77
  Sections are listed in render order. Components resolve through `component-catalog.json`; every section named here exists in `packages/ui` (§ 4). _Live_ = what the scaffold rendered on 2026-09-15; _Target_ = the standardissue-matched composition. **Corrected 2026-09-15** against the captured copy (`docs/research/standardissue-capture/copy/<slug>.txt`) after a prop-coverage check of every beat against `packages/validation/src/schemas/page-sections.ts`; three bounded fields the reproduction needs are commissioned in **#5576** (Hero `checklist`, Feature `actions`, CTA `closingLine`) and are marked 🔧 #5576 below.
45
78
 
46
- **Copy rule (Sam, 2026-09-15): verbatim, mad-lib style exactly.** Every headline, body, bullet, label and CTA is the reference's text from `copy/<slug>.txt`, braces included (`{outcome}`, `{Primary CTA}`, `{Social Proof goes here}`). Lorem ipsum stays lorem ipsum where the reference has it. Nothing is paraphrased, shortened or "improved"; the operator rewrites the copy after the match is achieved. Only chrome text differs (§ 1).
79
+ **Copy rule (Sam, 2026-09-15): verbatim, mad-lib style exactly.** Every headline, body, bullet, label and CTA is the reference's text from `copy/<slug>.txt`, braces included (`{outcome}`, `{Primary CTA}`, `{Social Proof goes here}`). Lorem ipsum stays lorem ipsum where the reference has it. Nothing is paraphrased, shortened or "improved"; the operator rewrites the copy after the match is achieved. Only chrome text differs (§ 1). Superseded for the base and overlay pages by #6469 (operator, 2026-09-22): every fill-in slot is a `{brace}` instruction and every page carries the `PLACEHOLDER — REPLACE BEFORE LAUNCH` label.
47
80
 
48
81
  ### `/` — HomePage · schema `HomePage` · `MarketingShell` · chrome on
49
82
 
50
- Reference: `screenshots/home.png`, `copy/home.txt`. Nine page sections; the newsletter and the blog list on the reference are in its footer, not the page (§ 1).
83
+ Reference: `screenshots/home.png`, `copy/home.txt`. Ten page sections; the newsletter and the blog list on the reference are in its footer, not the page (§ 1).
51
84
 
52
85
  <!-- generated:begin page=/ -->
53
86
 
54
- | # | Section | Component | Copy (first line) |
55
- | --- | ------------------------------------------------------------ | --------------- | -------------------------------------------------- |
56
- | 1 | `hero` (split · checklist ×3 · 2 CTAs · closingLine) | `Hero` | How to get {outcome} without {problem} |
57
- | 2 | `logoCloud` (logos ×6) | `LogoCloud` | Don’t just take our word for it |
58
- | 3 | `decision-split` (panels ×2) | `DecisionSplit` | There's a better way to {fix problem / get result} |
59
- | 4 | `feature` (eyebrow "Core Features" · features ×5 · 2 CTAs) | `Feature` | Everything you need to {achieve a desired outcome} |
60
- | 5 | `cta` (2 CTAs) | `CTA` | Direct integrations with your favorite tools |
61
- | 6 | `stair-steps` (tiles ×3) | `StairSteps` | Get setup in {number} easy steps |
62
- | 7 | `cta` (box · chips ×3 · 2 CTAs · closingLine) | `CTA` | Switch to {your product} in {time amount} or less |
63
- | 8 | `content-block` (media-right · eyebrow "Manifesto" · 2 CTAs) | `ContentBlock` | We want you to {ability they couldn't do before} |
64
- | 9 | `video-section` (1 CTA · playBadge) | `VideoSection` | See {your product} in action |
87
+ | # | Section | Component | Copy (first line) |
88
+ | --- | ---------------------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------- |
89
+ | 1 | `hero` (illustration · imagerySlot=true · checklist ×3 · 2 CTAs · closingLine) | `Hero` | {How to get outcome without problem} |
90
+ | 2 | `logoCloud` (layout=inline · logos ×3) | `LogoCloud` | Don’t just take our word for it |
91
+ | 3 | `decision-split` (imagerySlot=true · eyebrow "Comparison" · panels ×2) | `DecisionSplit` | {There's a better way to fix problem / get result} |
92
+ | 4 | `feature` (itemStyle=plain · actionsPosition=below · eyebrow "Core Features" · features ×5 · 2 CTAs) | `Feature` | {Everything you need to achieve a desired outcome} |
93
+ | 5 | `cta` (minimal · eyebrow "Integrations" · 2 CTAs) | `CTA` | Direct integrations with your favorite tools |
94
+ | 6 | `media-band` (imagerySlot=true) | `MediaBand` | |
95
+ | 7 | `feature` (itemStyle=plain · actionsPosition=below · imagerySlot=true · eyebrow "How It Works" · features ×3 · 2 CTAs) | `Feature` | {Get set up in number easy steps} |
96
+ | 8 | `cta` (box · imagerySlot=true · checklist ×3 · 2 CTAs · closingLine) | `CTA` | {Switch to your product in time amount or less} |
97
+ | 9 | `content-block` (media-right · imagerySlot=true · eyebrow "Manifesto" · 2 CTAs) | `ContentBlock` | {We want you to ability they couldn't do before} |
98
+ | 10 | `content-block` (eyebrow "{Your Product} Demo" · 2 CTAs) | `ContentBlock` | {See your product in action} |
65
99
 
66
100
  <!-- generated:end -->
67
101
 
68
- ### `/how-it-works` — LandingPage · schema `WebPage` · chrome on
102
+ ### `/use-cases` — UseCasesList · schema `CollectionPage` · chrome on
103
+
104
+ Rendered by the `/use-cases` route over `content/en/UseCasesList/use-cases.mdx` — a UseCasesList page composing `sections[]` (operator ruling 2026-09-23), emitting the UseCasesList builder's `CollectionPage`. Since #6658 D4 it is a real list: one `items` section of three cards, each linking a `UseCase` page and titled with that page's title, so the `ItemList` names the three pages. The how-it-works steps moved to the product page.
105
+
106
+ <!-- generated:begin page=/use-cases -->
107
+
108
+ | # | Section | Component | Copy (first line) |
109
+ | --- | -------------------------------------------------------- | -------------- | ----------------------------------------------------------------- |
110
+ | 1 | `hero` (eyebrow "Use cases" · 2 CTAs) | `Hero` | {Use cases: who your product is for} |
111
+ | 2 | `items` (columns=3 · items ×3) | `Items` | {The jobs customers hire your product to do} |
112
+ | 3 | `logoCloud` (layout=inline · logos ×6) | `LogoCloud` | Don’t just take our word for it |
113
+ | 4 | `testimonials` (quote · items ×1) | `Testimonials` | {A customer quote, in their own words, about the result they got} |
114
+ | 5 | `cta` (box · checklist ×3 · 2 CTAs · closingLine) | `CTA` | {Switch to your product in time amount or less} |
115
+ | 6 | `faq` (accordion · items ×5 · 1 CTA · initialOpen first) | `FAQ` | FAQs |
116
+
117
+ <!-- generated:end -->
69
118
 
70
- Reference: `screenshots/how-it-works.png`, `copy/how-it-works.txt`. Rendered by the generic `[slug]` route over `content/en/LandingPage/how-it-works.mdx`, emitting the LandingPage builder's `WebPage`. (`WebPage` is a schema.org @type the registry emits, not a content type the adapter accepts — the `[slug]` route's own header comment records why. A `schema` override to `HowTo` is refused by the scaffold's own `structured-data` gate, which validates every LandingPage as `WebPage`.)
119
+ ### `/use-cases/<slug>` — UseCase · schema `WebPage` → `Article` · chrome on
71
120
 
72
- <!-- generated:begin page=/how-it-works -->
121
+ Three placeholder use cases from the base layer (#6658 D4): `first-use-case`, `second-use-case` and `third-use-case`, rendered as prose by the `/use-cases/[slug]` route.
73
122
 
74
- | # | Section | Component | Copy (first line) |
75
- | --- | -------------------------------------------------------------- | -------------- | ---------------------------------------------------------------------- |
76
- | 1 | `hero` (eyebrow "How it Works" · 2 CTAs) | `Hero` | Get set up in {number} easy steps |
77
- | 2 | `feature` (alternating · numbered · features ×3) | `Feature` | The first thing they need to do to get the outcome they want |
78
- | 3 | `logoCloud` (logos ×6) | `LogoCloud` | Don’t just take our word for it |
79
- | 4 | `testimonials` (featured · items ×1) | `Testimonials` | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse … |
80
- | 5 | `cta` (box · chips ×3 · 2 CTAs · closingLine) | `CTA` | Switch to {your product} in {time amount} or less |
81
- | 6 | `faq` (accordion · items ×5 · supportLink · initialOpen first) | `FAQ` | FAQs |
123
+ <!-- generated:begin page=/use-cases/[slug] -->
82
124
 
125
+ _Detail route over `content/en/UseCase/` — 3 seed pages: `first-use-case.mdx`, `second-use-case.mdx`, `third-use-case.mdx`._
83
126
  <!-- generated:end -->
84
127
 
85
- ### `/features` — LandingPage · schema `WebPage` · chrome on
128
+ ### `/software` — code route (the product listing) · chrome on
129
+
130
+ Lists every `SoftwareProduct` page by slug. The route is core since #6658: the product's own page replaced the `/features` stand-in, so every scaffold carries it.
86
131
 
87
- Reference: `screenshots/features.png`, `copy/features.txt`. Rendered by the `[slug]` route over `content/en/LandingPage/features.mdx`. No hero: the page opens on the feature grid.
132
+ <!-- generated:begin page=/software -->
88
133
 
89
- <!-- generated:begin page=/features -->
134
+ _Code route — no content, no sections._
135
+ <!-- generated:end -->
90
136
 
91
- | # | Section | Component | Copy (first line) |
92
- | --- | ------------------------------------------------- | --------- | ------------------------------------------------- |
93
- | 1 | `feature` (eyebrow "Core Features" · features ×5) | `Feature` | Medium length section heading goes here |
94
- | 2 | `cta` (2 CTAs) | `CTA` | Direct integrations with your favorite tools |
95
- | 3 | `cta` (box · chips ×3 · 2 CTAs · closingLine) | `CTA` | Switch to {your product} in {time amount} or less |
137
+ ### `/software/<slug>` (seed: `/software/product`) — SoftwareProduct · schema `WebPage` → `SoftwareApplication` · chrome on
96
138
 
139
+ Reference: `screenshots/features.png`, `copy/features.txt`, plus the how-it-works steps. The product's own detail page (#6658 D3), rendered by the `/software/[slug]` route over `content/en/SoftwareProduct/product.mdx`. Its JSON-LD is a `WebPage` whose `mainEntity` is a `SoftwareApplication` named by the page title; its feature titles become the site's `featureList` when `_site.mdx` declares a `SoftwareApplication` secondary. It carries the former `/features` sections, with their links re-pointed to in-page anchors, and the how-it-works steps that moved off `/use-cases` (the brief's "how-it-works folds into the product page"). The nav's Features links and the home page's feature links point here.
140
+
141
+ <!-- generated:begin page=/software/[slug] -->
142
+
143
+ _Detail route over `content/en/SoftwareProduct/` — 1 seed page: `product.mdx`._
97
144
  <!-- generated:end -->
98
145
 
99
146
  ### `/pricing` — Pricing · schema `Pricing` · chrome on
100
147
 
101
- Reference: `screenshots/pricing.png`, `copy/pricing.txt`. The reference opens on a hero (eyebrow Pricing, the headline, two CTAs) ABOVE the plans section, which repeats the headline — composed as the reference and the copy have it. Route enabled by the roster (#5469 D10).
148
+ Reference: `screenshots/pricing.png`, `copy/pricing.txt`. The reference opens on a hero that repeats the plans section's own eyebrow/headline/subtitle; the template drops that hero (operator, 2026-09-23) and the plans section leads the page and owns its `<h1>` (`ownsPageTitle`). Route enabled by the roster (#5469 D10).
102
149
 
103
150
  <!-- generated:begin page=/pricing -->
104
151
 
105
- | # | Section | Component | Copy (first line) |
106
- | --- | ---------------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------------- |
107
- | 1 | `hero` (eyebrow "Pricing" · 2 CTAs) | `Hero` | Pays for itself in {tangible value or outcome} |
108
- | 2 | `pricing` (three-tiers-with-toggle · eyebrow "Pricing" · plans ×3 · billingToggle) | `Pricing` | Pays for itself in {tangible value or outcome} |
109
- | 3 | `logoCloud` (logos ×6) | `LogoCloud` | Don’t just take our word for it |
110
- | 4 | `testimonials` (featured · items ×1) | `Testimonials` | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse … |
111
- | 5 | `cta` (box · chips ×3 · 2 CTAs · closingLine) | `CTA` | Switch to {your product} in {time amount} or less |
112
- | 6 | `faq` (accordion · items ×5 · supportLink · initialOpen first) | `FAQ` | FAQs |
152
+ | # | Section | Component | Copy (first line) |
153
+ | --- | -------------------------------------------------------------------------------------------------------- | -------------- | ----------------------------------------------------------------- |
154
+ | 1 | `pricing` (three-tiers-with-toggle · cardLayout=centered · eyebrow "Pricing" · plans ×3 · billingToggle) | `Pricing` | {Pays for itself in tangible value or outcome} |
155
+ | 2 | `logoCloud` (layout=inline · logos ×3) | `LogoCloud` | Don’t just take our word for it |
156
+ | 3 | `testimonials` (quote · items ×1) | `Testimonials` | {A customer quote, in their own words, about the result they got} |
157
+ | 4 | `cta` (box · checklist ×3 · 2 CTAs · closingLine) | `CTA` | {Switch to your product in time amount or less} |
158
+ | 5 | `faq` (accordion · items ×5 · 1 CTA · initialOpen none) | `FAQ` | FAQs |
113
159
 
114
160
  <!-- generated:end -->
115
161
 
@@ -119,14 +165,13 @@ Reference: `screenshots/about.png`, `copy/about.txt`. No hero: the page opens on
119
165
 
120
166
  <!-- generated:begin page=/about -->
121
167
 
122
- | # | Section | Component | Copy (first line) |
123
- | --- | -------------------------------------------------------------- | -------------- | ---------------------------------------------------------------------- |
124
- | 1 | `content-block` (media-right · eyebrow "Manifesto" · 2 CTAs) | `ContentBlock` | We want you to {ability they couldn't do before} |
125
- | 2 | `team` (members ×5) | `Team` | Our team |
126
- | 3 | `logoCloud` (logos ×6) | `LogoCloud` | Don’t just take our word for it |
127
- | 4 | `testimonials` (featured · items ×1) | `Testimonials` | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse … |
128
- | 5 | `cta` (box · chips ×3 · 2 CTAs · closingLine) | `CTA` | Switch to {your product} in {time amount} or less |
129
- | 6 | `faq` (accordion · items ×5 · supportLink · initialOpen first) | `FAQ` | FAQs |
168
+ | # | Section | Component | Copy (first line) |
169
+ | --- | --------------------------------------------------------------------------- | -------------- | ----------------------------------------------------------------- |
170
+ | 1 | `content-block` (media-right · imagerySlot=true · eyebrow "About" · 2 CTAs) | `ContentBlock` | {We want you to ability they couldn't do before} |
171
+ | 2 | `team` (with-side-images · eyebrow "Tagline" · members ×5) | `Team` | Our team |
172
+ | 3 | `testimonials` (quote · items ×1) | `Testimonials` | {A customer quote, in their own words, about the result they got} |
173
+ | 4 | `cta` (box · imagerySlot=true · checklist ×3 · 2 CTAs · closingLine) | `CTA` | {Switch to your product in time amount or less} |
174
+ | 5 | `faq` (accordion · items ×5 · 1 CTA · initialOpen none) | `FAQ` | FAQs |
130
175
 
131
176
  <!-- generated:end -->
132
177
 
@@ -136,11 +181,11 @@ No standardissue page; folded into the Product flyout. Copy: the reference's FAQ
136
181
 
137
182
  <!-- generated:begin page=/faq -->
138
183
 
139
- | # | Section | Component | Copy (first line) |
140
- | --- | -------------------------------------------------------------- | --------- | ---------------------------------------------------------------------- |
141
- | 1 | `hero` | `Hero` | FAQs |
142
- | 2 | `faq` (accordion · items ×5 · supportLink · initialOpen first) | `FAQ` | Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas u… |
143
- | 3 | `cta` (box · chips ×3 · 2 CTAs · closingLine) | `CTA` | Switch to {your product} in {time amount} or less |
184
+ | # | Section | Component | Copy (first line) |
185
+ | --- | ------------------------------------------------------- | --------- | ---------------------------------------- |
186
+ | 1 | `hero` (gapBelow=tight · eyebrow "FAQ") | `Hero` | FAQs |
187
+ | 2 | `faq` (accordion · items ×5 · 1 CTA · initialOpen none) | `FAQ` | {A question your customers actually ask} |
188
+ | 3 | `faq` (accordion · items ×5 · 1 CTA · initialOpen none) | `FAQ` | {A second group of questions} |
144
189
 
145
190
  <!-- generated:end -->
146
191
 
@@ -150,28 +195,66 @@ Reference: `screenshots/contact.png`, `copy/contact.txt`. The reference is a spl
150
195
 
151
196
  <!-- generated:begin page=/contact -->
152
197
 
153
- | # | Section | Component | Copy (first line) |
154
- | --- | ----------------------------------------------------- | -------------- | ---------------------------------------------------------------------- |
155
- | 1 | `hero` (split · eyebrow "Book a Demo" · checklist ×3) | `Hero` | Ready to {achieve a valuable outcome}? |
156
- | 2 | `contact-form` (card · fields ×3) | `ContactForm` | Name · Email · Message |
157
- | 3 | `logoCloud` (logos ×6) | `LogoCloud` | Don’t just take our word for it |
158
- | 4 | `testimonials` (featured · items ×1) | `Testimonials` | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse … |
198
+ | # | Section | Component | Copy (first line) |
199
+ | --- | ----------------------------------------------------- | -------------- | ----------------------------------------------------------------- |
200
+ | 1 | `hero` (split · eyebrow "Book a Demo" · checklist ×3) | `Hero` | {Ready to achieve a valuable outcome?} |
201
+ | 2 | `logoCloud` (layout=inline · logos ×6) | `LogoCloud` | Don’t just take our word for it |
202
+ | 3 | `testimonials` (quote · items ×1) | `Testimonials` | {A customer quote, in their own words, about the result they got} |
203
+
204
+ <!-- generated:end -->
205
+
206
+ ### `/glossary` — GlossaryList · schema `CollectionPage` → `DefinedTermSet` · chrome on
207
+
208
+ A base-layer seed every starter carries (#6658 D5): a hero, then a `glossary-index` of five placeholder terms, each a `DefinedTerm` in the page's `DefinedTermSet`. Linked from the footer's Resources column.
209
+
210
+ <!-- generated:begin page=/glossary -->
211
+
212
+ | # | Section | Component | Copy (first line) |
213
+ | --- | ----------------------------------- | --------------- | -------------------------------------------- |
214
+ | 1 | `hero` (eyebrow "Glossary" · 1 CTA) | `Hero` | {Glossary: the terms your customers look up} |
215
+ | 2 | `glossary-index` (columns) | `GlossaryIndex` | {Terms, A to Z} |
216
+
217
+ <!-- generated:end -->
218
+
219
+ ### `/newsletter` — NewsletterSignup · schema `WebPage` → `Offer` · chrome on
220
+
221
+ A base-layer seed every starter carries (#6658 D5). The form posts to lead capture (`/v1/leads/subscribe`), which records a subscriber and sends no verification email. The frontmatter `schema:` names the free subscription as the page's `Offer`. Linked from the footer's Resources column.
222
+
223
+ <!-- generated:begin page=/newsletter -->
224
+
225
+ | # | Section | Component | Copy (first line) |
226
+ | --- | ------------------------------------- | ------------ | ------------------------------------------------ |
227
+ | 1 | `hero` (eyebrow "Newsletter" · 1 CTA) | `Hero` | {Newsletter: what subscribers get and how often} |
228
+ | 2 | `newsletter` | `Newsletter` | Subscribe |
229
+ | 3 | `faq` (expanded · items ×3) | `FAQ` | FAQs |
159
230
 
160
231
  <!-- generated:end -->
161
232
 
162
- ### `/blog` — LandingPage · schema `WebPage` · chrome on (Free teaser)
233
+ ### `/book-a-call` — BookCall · schema `WebPage` → `Offer` · chrome on
163
234
 
164
- Reference: `screenshots/blog.png`, `copy/blog.txt` for the opener and the newsletter. Free ships **one static page**: the reference's opener, a CTA to the Pro docs-blog module (the one non-verbatim block), the newsletter, and the reference's logo strip + testimonial. Pro replaces this route with the real listing by directory precedence (#5469 D3).
235
+ A base-layer seed every starter carries (#6658 D5): a hero whose call to action is `/contact`, then what happens on the call. A template carrying the scheduling module overrides the seed so the call to action opens `/meet`. Linked from the footer's Site pages column.
236
+
237
+ <!-- generated:begin page=/book-a-call -->
238
+
239
+ | # | Section | Component | Copy (first line) |
240
+ | --- | -------------------------------------- | --------- | ------------------------------------------ |
241
+ | 1 | `hero` (eyebrow "Book a call" · 1 CTA) | `Hero` | {Book a call: what a visitor gets from it} |
242
+ | 2 | `items` (columns=3 · items ×3) | `Items` | What happens on the call? |
243
+
244
+ <!-- generated:end -->
245
+
246
+ ### `/blog` — BlogList · schema `Blog` · chrome on (Free teaser)
247
+
248
+ Reference: `screenshots/blog.png`, `copy/blog.txt` for the opener and the newsletter. Free ships **one static page** with the correct page type — a BlogList (`content/en/BlogList/blog.mdx`, emitting the BlogList builder's `Blog` with an empty `ItemList`) served by the generic `[slug]` route, which probes BlogList after LandingPage: the reference's opener, a CTA to the Pro docs-blog module (the one non-verbatim block), the newsletter, and the reference's logo strip + testimonial. Pro replaces this route with the real listing by directory precedence (#5469 D3).
165
249
 
166
250
  <!-- generated:begin page=/blog -->
167
251
 
168
- | # | Section | Component | Copy (first line) |
169
- | --- | ------------------------------------ | -------------- | ---------------------------------------------------------------------- |
170
- | 1 | `hero` (centered · eyebrow "Blog") | `Hero` | Resources for {customer profile} |
171
- | 2 | `cta` (2 CTAs) | `CTA` | The blog listing ships with the Pro docs-blog module |
172
- | 3 | `newsletter` | `Newsletter` | Stay Up to Date with our {fequency} Newsletter |
173
- | 4 | `logoCloud` (logos ×6) | `LogoCloud` | Don’t just take our word for it |
174
- | 5 | `testimonials` (featured · items ×1) | `Testimonials` | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse … |
252
+ | # | Section | Component | Copy (first line) |
253
+ | --- | --------------------------------------------------- | -------------- | ----------------------------------------------------------------- |
254
+ | 1 | `hero` (centered · gapBelow=tight · eyebrow "Blog") | `Hero` | {Resources for customer profile} |
255
+ | 2 | `blog-list` (grid) | `BlogList` | |
256
+ | 3 | `logoCloud` (layout=inline · logos ×6) | `LogoCloud` | Don’t just take our word for it |
257
+ | 4 | `testimonials` (quote · items ×1) | `Testimonials` | {A customer quote, in their own words, about the result they got} |
175
258
 
176
259
  <!-- generated:end -->
177
260
 
@@ -184,6 +267,15 @@ Renders the `SignInCard` client island (providers from env) inside the locale la
184
267
  _Code route — no content, no sections._
185
268
  <!-- generated:end -->
186
269
 
270
+ ### `/sign-up` — code route (sign-up form) · chrome on
271
+
272
+ The account-creation form inside the locale layout — a code route like `/sign-in`, listed so the manifest is a complete install record (#6646). No reference page.
273
+
274
+ <!-- generated:begin page=/sign-up -->
275
+
276
+ _Code route — no content, no sections._
277
+ <!-- generated:end -->
278
+
187
279
  ### `/privacy`, `/terms` — PrivacyPage / TermsPage · schema same · chrome on
188
280
 
189
281
  Reference: `screenshots/legal--privacy-policy.png`, `copy/legal--*.txt`. Content ✅ (the `document-chassis` placeholder document, not re-authored — the two pages stay as #5565 shipped them). Route enabled by the roster (#5469 D10).
@@ -192,9 +284,9 @@ Reference: `screenshots/legal--privacy-policy.png`, `copy/legal--*.txt`. Content
192
284
 
193
285
  <!-- generated:begin page=/privacy -->
194
286
 
195
- | # | Section | Component | Copy (first line) |
196
- | --- | ------------------------------------------------------------------ | ----------------- | ----------------- |
197
- | 1 | `document-chassis` (eyebrow "PLACEHOLDER — REPLACE BEFORE LAUNCH") | `DocumentChassis` | Privacy Policy |
287
+ | # | Section | Component | Copy (first line) |
288
+ | --- | ----------------------------------- | ----------------- | ----------------- |
289
+ | 1 | `document-chassis` (layout=article) | `DocumentChassis` | Privacy Policy |
198
290
 
199
291
  <!-- generated:end -->
200
292
 
@@ -202,9 +294,21 @@ Reference: `screenshots/legal--privacy-policy.png`, `copy/legal--*.txt`. Content
202
294
 
203
295
  <!-- generated:begin page=/terms -->
204
296
 
205
- | # | Section | Component | Copy (first line) |
206
- | --- | ------------------------------------------------------------------ | ----------------- | ----------------- |
207
- | 1 | `document-chassis` (eyebrow "PLACEHOLDER — REPLACE BEFORE LAUNCH") | `DocumentChassis` | Terms of Service |
297
+ | # | Section | Component | Copy (first line) |
298
+ | --- | ----------------------------------- | ----------------- | ----------------- |
299
+ | 1 | `document-chassis` (layout=article) | `DocumentChassis` | Terms of Service |
300
+
301
+ <!-- generated:end -->
302
+
303
+ ### `/purchase-policy` — `PurchasePolicyPage` (product shape) · chrome on
304
+
305
+ One document-chassis page with the shape's policy sections — returns, shipping and refunds (#6646). Its Returns section makes the JSON-LD a `MerchantReturnPolicy` at `#return-policy`.
306
+
307
+ <!-- generated:begin page=/purchase-policy -->
308
+
309
+ | # | Section | Component | Copy (first line) |
310
+ | --- | ----------------------------------- | ----------------- | ----------------- |
311
+ | 1 | `document-chassis` (layout=article) | `DocumentChassis` | Purchase Policy |
208
312
 
209
313
  <!-- generated:end -->
210
314
 
@@ -212,25 +316,37 @@ Reference: `screenshots/legal--privacy-policy.png`, `copy/legal--*.txt`. Content
212
316
 
213
317
  Not a hub page by design (#3960). Free ships none because the contact form confirms inline. Listed so nobody re-files it.
214
318
 
319
+ ## 1b. Structured data (every page)
320
+
321
+ Every content route emits one `application/ld+json` script whose `@graph` carries the site's own entity graph, built from `content/_site.mdx` `siteIdentity` — never from a page title (#6597):
322
+
323
+ | Node | `@id` | Built from | Links |
324
+ | ------------------------------------------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
325
+ | Identity (`Organization` · `Person` · `LocalBusiness`) | `<origin>/#organization` (`#person` for a Person) | `siteIdentity` `name` · `url` · `logo`/`image` · `description` · `sameAs` | — |
326
+ | Secondary (optional) | `<origin>/#product` (a `SoftwareApplication`) · `<origin>/#organization` (a Person's company) | `siteIdentity.secondary` | product `publisher` → `#organization`, `featureList` from the product page's (`/software/product`) feature items; a Person `worksFor` its company, which has the Person as `founder` |
327
+ | `WebSite` | `<origin>/#website` | `siteName` · `baseUrl` · the render locale | `publisher` → the identity node |
328
+
329
+ Each page's primary node is `isPartOf` the `WebSite`; the home page's `mainEntity` is the secondary when declared, else the identity. A testimonials `Review` points its `itemReviewed` at the identity node, declared in the same graph. Free declares no secondary, so a fresh site emits the Organization and the WebSite. `/sign-in` emits no JSON-LD.
330
+
215
331
  ## 2a. State and persistence (every interactive element)
216
332
 
217
333
  The template is content and config; the states live in the components. This table is what the local review clicks through (#5469 AC), per element: the states, where they persist, and what a returning visitor sees.
218
334
 
219
- | Element | States | Persists in | Returning visitor sees | Empty / error state |
220
- | -------------------------------------- | ------------------------------------------ | ------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
221
- | Announcement banner (home only) | shown; no dismiss | — | shown on `/`, never elsewhere | — |
222
- | Cookie consent (`BannerConsentIsland`) | unset → shown; accepted; declined | consent cookie (the island's) | nothing until the cookie expires | a blocked storage write leaves it shown |
223
- | Theme toggle (footer) | light · dark · system | `data-theme` + localStorage (`ThemeToggle`) | last choice | falls back to system |
224
- | Locale switcher (footer) | one of `NEXT_PUBLIC_ENABLED_LOCALES` | `NEXT_LOCALE` cookie + the URL prefix | last locale, unprefixed when default | single-locale site shows one option |
225
- | Nav (mobile) | closed · open (hamburger) | — | closed | — |
226
- | Product flyout (desktop) | closed · open on hover/focus | — | closed | — |
227
- | Contact form | idle · sending · success (inline) · error | — | idle | validation errors per field; consent unchecked blocks submit |
228
- | Newsletter (footer + `/blog`) | idle · sending · success · error | — | idle | the reference's two lines: "Thank you! Your submission has been received!" / "Oops! Something went wrong…" |
229
- | Pricing billing toggle | monthly · yearly | — | monthly | — |
230
- | FAQ accordion | per item open/closed (`initialOpen`) | — | first open | no items → section hidden |
231
- | Video section | poster · playing (`playBadge`) | — | poster | missing asset → poster only |
232
- | Sign-in card | providers listed · magic-link sent · error | session cookie (auth) | signed in → redirected by `next-path` | no provider configured → honest empty state |
233
- | Legal document chassis | contents nav scroll position | — | top | — |
335
+ | Element | States | Persists in | Returning visitor sees | Empty / error state |
336
+ | -------------------------------------- | -------------------------------------------------- | ------------------------------------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
337
+ | Announcement banner (home only) | off by default (#6469); when on: shown, no dismiss | — | when on: shown on `/`, never elsewhere | — |
338
+ | Cookie consent (`BannerConsentIsland`) | unset → shown; accepted; declined | consent cookie (the island's) | nothing until the cookie expires | a blocked storage write leaves it shown |
339
+ | Theme toggle (footer) | light · dark · system | `data-theme` + localStorage (`ThemeToggle`) | last choice | falls back to system |
340
+ | Locale switcher (footer) | one of `NEXT_PUBLIC_ENABLED_LOCALES` | `NEXT_LOCALE` cookie + the URL prefix | last locale, unprefixed when default | single-locale site shows one option |
341
+ | Nav (mobile) | closed · open (hamburger) | — | closed | — |
342
+ | Product flyout (desktop) | closed · open on hover/focus | — | closed | — |
343
+ | Contact form | idle · sending · success (inline) · error | — | idle | validation errors per field; consent unchecked blocks submit |
344
+ | Newsletter (footer + `/blog`) | idle · sending · success · error | — | idle | the reference's two lines: "Thank you! Your submission has been received!" / "Oops! Something went wrong…" |
345
+ | Pricing billing toggle | monthly · yearly | — | monthly | — |
346
+ | FAQ accordion | per item open/closed (`initialOpen`) | — | first open | no items → section hidden |
347
+ | Video section | poster · playing (`playBadge`) | — | poster | missing asset → poster only |
348
+ | Sign-in card | providers listed · magic-link sent · error | session cookie (auth) | signed in → redirected by `next-path` | no provider configured → honest empty state |
349
+ | Legal document chassis | contents nav scroll position | — | top | — |
234
350
 
235
351
  ## 3. Roster, as the registry declares it
236
352
 
@@ -240,33 +356,80 @@ The template is content and config; the states live in the components. This tabl
240
356
  marketing-site-free:
241
357
  requires: [marketing]
242
358
  categories: [accounting, legal, technology]
359
+ shape: organization-product
360
+ design: standard
243
361
  roster:
244
- - { route: "/", content: ["content/en/HomePage/home.mdx"] }
245
- - { route: "/how-it-works", content: ["content/en/LandingPage/how-it-works.mdx"] }
246
- - { route: "/features", content: ["content/en/LandingPage/features.mdx"] }
247
- - { route: "/pricing", content: ["content/en/Pricing/pricing.mdx"] }
248
- - { route: "/about", content: ["content/en/AboutPage/about.mdx"] }
249
- - { route: "/faq", content: ["content/en/FAQPage/faq.mdx"] }
250
- - { route: "/contact", content: ["content/en/ContactPage/contact.mdx"] }
251
- - { route: "/sign-in" }
252
- - { route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] }
253
- - { route: "/terms", content: ["content/en/TermsPage/terms.mdx"] }
254
- - { route: "/blog", content: ["content/en/LandingPage/blog.mdx"] }
362
+ - { route: "/", kind: page, content: ["content/en/HomePage/home.mdx"] }
363
+ - { route: "/software", kind: route }
364
+ - { route: "/software/[slug]", kind: page, contentDir: "content/en/SoftwareProduct" }
365
+ - { route: "/use-cases", kind: page, content: ["content/en/UseCasesList/use-cases.mdx"] }
366
+ - { route: "/use-cases/[slug]", kind: page, contentDir: "content/en/UseCase" }
367
+ - { route: "/pricing", kind: page, content: ["content/en/Pricing/pricing.mdx"] }
368
+ - { route: "/about", kind: page, content: ["content/en/AboutPage/about.mdx"] }
369
+ - { route: "/faq", kind: page, content: ["content/en/FAQPage/faq.mdx"] }
370
+ - { route: "/contact", kind: page, content: ["content/en/ContactPage/contact.mdx"] }
371
+ - { route: "/glossary", kind: page, content: ["content/en/GlossaryList/glossary.mdx"] }
372
+ - { route: "/newsletter", kind: page, content: ["content/en/NewsletterSignup/newsletter.mdx"] }
373
+ - { route: "/book-a-call", kind: page, content: ["content/en/BookCall/book-call.mdx"] }
374
+ - { route: "/sign-in", kind: route }
375
+ - { route: "/sign-up", kind: route }
376
+ - { route: "/privacy", kind: page, content: ["content/en/PrivacyPage/privacy.mdx"] }
377
+ - { route: "/terms", kind: page, content: ["content/en/TermsPage/terms.mdx"] }
378
+ - { route: "/purchase-policy", kind: page, content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"] }
379
+ - { route: "/blog", kind: page, content: ["content/en/BlogList/blog.mdx"] }
255
380
  ```
256
381
 
257
382
  <!-- generated:end -->
258
383
 
259
- All eleven rows are declared on the registry (`TEMPLATE_BASE_ROSTER` + the Free `/blog` teaser row, #5469 D3/D4), so the template is one declared page set whichever mechanism scaffolds each: the always-copied overlay for the core pages, `site-templates/marketing-site-free/content/**` for the three module-less ones.
384
+ All eighteen rows are declared on the registry (`TEMPLATE_BASE_ROSTER` + the Free `/blog` teaser row, #5469 D3/D4, re-derived by #6658), so the template is one declared page set whichever mechanism scaffolds each: the always-copied overlay for the core pages, `site-templates/_base/content/**` for the module-less ones and the three use cases. The scaffold carries this roster as `.ailk-site-manifest.json` at its root (#6658 D7); this Markdown stays in the template.
385
+
386
+ ### 3a. Deviations from the standard roster (recorded, #6658)
387
+
388
+ The roster is the standard page set for this template's shape, edited only by
389
+ the rows below. The standard set is the `page_type` column of
390
+ `python3 scripts/derive-roster.py --entity-type software --offering-type software --primary-goal convert --scale global --registry packages/schema/src/registry/entries.ts`
391
+ (20 rows, `mainEntity: SoftwareApplication`) — the `--shape organization-product`
392
+ invocation once claude-setup#9145's `--shape` flag is vendored into this repo.
393
+ The roster's page rows equal that set minus the dropped rows, plus the added
394
+ rows (`R = (S − D) ∪ A`). This supersedes the 2026-09-23 disposition, whose
395
+ three omissions (`GlossaryList`, `BookCall`, `NewsletterSignup`) the brief
396
+ reversed (`docs/decisions/starter-roster-page-set.md` D4, D7).
397
+
398
+ **Standard rows dropped:**
399
+
400
+ | Standard row | Reason |
401
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------ |
402
+ | `IntegrationsList` | a placeholder starter has no integrations to list |
403
+ | `Integration` | a placeholder starter has no integrations to list |
404
+ | `CoursesList` | there is no course offering |
405
+ | `Course` | there is no course offering |
406
+ | `CaseStudiesList` | proof pages need real customers; the use-cases page carries one placeholder testimonial and one logo strip instead |
407
+ | `CaseStudy` | proof pages need real customers; the use-cases page carries one placeholder testimonial and one logo strip instead |
408
+ | `TestimonialsList` | proof pages need real customers; the use-cases page carries one placeholder testimonial and one logo strip instead |
409
+ | `ClientsList` | proof pages need real customers; the use-cases page carries one placeholder testimonial and one logo strip instead |
410
+
411
+ **Rows added:**
412
+
413
+ | Added row | Reason |
414
+ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
415
+ | `SoftwareProduct` | the single product's own detail page — the standard's multi-product opt-in, taken by the one product |
416
+ | `PurchasePolicyPage` | the product-shape purchase policy every shape carries (#6646 D3) |
417
+ | `BlogList` (the `/blog` teaser) | the standard's `convert` goal carries no blog (`blog_enabled: false`); the Free teaser stays by operator ruling 2026-09-24, and where the docs-blog module is present its own `BlogList` serves `/blog` instead |
418
+ | `/software`, `/sign-in`, `/sign-up` | code routes (`kind: route`): the product listing and the two auth pages carry no page type of their own |
419
+
420
+ ### 3b. Site entity (operator-disposed 2026-09-24)
421
+
422
+ `derive-roster.py` names `SoftwareApplication` as the main entity for this template's inputs. The template deliberately declares the **Organization** as the site's primary node and the software as its **secondary** node (`siteIdentity.secondary`, kind `SoftwareApplication`, #6597): the Free template is a company's own site about its product, so the entity the site is _about_ is the maker. The inverse — `SoftwareApplication` primary — is for a product whose canonical site is elsewhere (Positionary, whose maker has its own site). A fresh Free scaffold declares no `secondary` until the owner names the product; the overlay `_site.mdx` documents the field.
260
423
 
261
424
  ## 4. Component inventory (Free, by tier)
262
425
 
263
426
  <!-- generated:begin inventory -->
264
427
 
265
- | Tier | Used by this template |
266
- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
267
- | Shell | `MarketingShell` |
268
- | Chrome | `Nav`, `Footer`, `Banner` (+ `BannerConsentIsland`, `BannerDismissIsland`) |
269
- | Sections | `ContactForm`, `ContentBlock`, `CTA`, `DecisionSplit`, `DocumentChassis`, `FAQ`, `Feature`, `Hero`, `LogoCloud`, `Newsletter`, `Pricing`, `StairSteps`, `Team`, `Testimonials`, `VideoSection` |
428
+ | Tier | Used by this template |
429
+ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
430
+ | Shell | `MarketingShell` |
431
+ | Chrome | `Nav`, `Footer`, `Banner` (+ `BannerConsentIsland`, `BannerDismissIsland`) |
432
+ | Sections | `BlogList`, `ContentBlock`, `CTA`, `DecisionSplit`, `DocumentChassis`, `FAQ`, `Feature`, `GlossaryIndex`, `Hero`, `Items`, `LogoCloud`, `MediaBand`, `Newsletter`, `Pricing`, `Team`, `Testimonials` |
270
433
 
271
434
  <!-- generated:end -->
272
435
 
@@ -284,3 +447,20 @@ Every section above already exists in `packages/ui`; the reproduction is composi
284
447
  | Footer columns + subscribe not composed on the default path | this template's build |
285
448
  | `/meet` rename (Pro) | #5563 |
286
449
  | `ReportPage` (Pro) | #5562 |
450
+ | CTA `box` variant's checklist + imagery-slot split (the product page's switch box) | #6526 |
451
+
452
+ ## 6. Not included (starter-template contract R2.4)
453
+
454
+ Named so nothing is assumed. Each is a scaffold-time or post-launch addition, not a gap in this template.
455
+
456
+ | Not included | What the template does instead |
457
+ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
458
+ | Email delivery of form submissions | the contact form persists in file mode (`AILK_LOCAL_LEAD_CAPTURE`) or to the leads API; no mail is sent |
459
+ | Newsletter backend | the footer Subscribe block is composed but posts nowhere until the owner wires a provider (§ 5) |
460
+ | Translated content | one locale (`en`); the i18n routing and message files ship, the copy does not |
461
+ | Error monitoring | none wired; the scaffold carries no Sentry or equivalent |
462
+ | Blog | `/blog` is a teaser (`BlogList`, empty list by design); posts need the `docs` module (Pro) |
463
+ | Auth-backed pages | `/sign-in` renders; sessions need Postgres (README § When you need a database) |
464
+ | Payments | none; commerce is the add-on (`docs/strategy/OFFERINGS.md`) |
465
+ | Analytics | `analytics.vercelAnalytics: false` in `_site.mdx`; the consent banner ships, nothing loads behind it until toggled |
466
+ | Search | none |