create-ailk 0.8.0 → 0.10.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 (238) hide show
  1. package/README.md +71 -3
  2. package/component-catalog.json +279 -45
  3. package/dist/add-module.d.ts +20 -0
  4. package/dist/add-module.js +43 -7
  5. package/dist/add-route.d.ts +56 -0
  6. package/dist/add-route.js +286 -0
  7. package/dist/apply-design-md.d.ts +7 -0
  8. package/dist/apply-design-md.js +50 -0
  9. package/dist/apply-design.d.ts +64 -0
  10. package/dist/apply-design.js +273 -0
  11. package/dist/claude-md.d.ts +111 -0
  12. package/dist/claude-md.js +334 -0
  13. package/dist/cli.js +104 -5
  14. package/dist/derive-architecture.js +41 -36
  15. package/dist/design-compile.d.ts +71 -0
  16. package/dist/design-compile.js +98 -0
  17. package/dist/design-package.d.ts +83 -0
  18. package/dist/design-package.js +468 -0
  19. package/dist/design-presets.d.ts +86 -0
  20. package/dist/design-presets.js +642 -0
  21. package/dist/design-scaffold.d.ts +76 -0
  22. package/dist/design-scaffold.js +220 -0
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.js +4 -1
  25. package/dist/legacy-nav-renderers.d.ts +45 -0
  26. package/dist/legacy-nav-renderers.js +545 -0
  27. package/dist/lib/auth-secret-file.d.ts +19 -0
  28. package/dist/lib/auth-secret-file.js +112 -0
  29. package/dist/lib/design-checks.d.ts +78 -0
  30. package/dist/lib/design-checks.js +174 -0
  31. package/dist/lib/license-key-files.d.ts +9 -0
  32. package/dist/lib/license-key-files.js +2 -2
  33. package/dist/lib/module-license-gate.d.ts +48 -32
  34. package/dist/lib/module-license-gate.js +117 -8
  35. package/dist/lib/render-verdict.d.ts +52 -0
  36. package/dist/lib/render-verdict.js +77 -0
  37. package/dist/lib/scaffold-render-sweep.d.ts +105 -0
  38. package/dist/lib/scaffold-render-sweep.js +236 -0
  39. package/dist/module-architecture.d.ts +19 -16
  40. package/dist/module-architecture.js +67 -23
  41. package/dist/parse-args.d.ts +12 -2
  42. package/dist/parse-args.js +74 -13
  43. package/dist/programmatic.d.ts +30 -6
  44. package/dist/programmatic.js +216 -19
  45. package/dist/site-chrome.d.ts +19 -9
  46. package/dist/site-chrome.js +23 -13
  47. package/dist/site-manifest.d.ts +25 -0
  48. package/dist/site-manifest.js +254 -0
  49. package/dist/site-roster.d.ts +41 -0
  50. package/dist/site-roster.js +141 -8
  51. package/dist/starter-grid.d.ts +16 -63
  52. package/dist/starter-grid.js +102 -84
  53. package/dist/surfaces.d.ts +41 -9
  54. package/dist/surfaces.js +200 -83
  55. package/dist/template-manifest.d.ts +30 -13
  56. package/dist/template-manifest.js +53 -28
  57. package/package.json +6 -3
  58. package/release-scope.json +25 -0
  59. package/site-templates/_base/content/en/UseCase/persona-1.mdx +7 -6
  60. package/site-templates/_base/content/en/UseCase/persona-2.mdx +7 -6
  61. package/site-templates/_base/content/en/UseCase/persona-3.mdx +7 -6
  62. package/site-templates/designs/minimalism/DESIGN.md +98 -6
  63. package/site-templates/designs/minimalism/sample/README.md +48 -0
  64. package/site-templates/{minimalism-site → designs/minimalism/sample}/content/en/HomePage/home.mdx +1 -1
  65. package/site-templates/designs/standard/DESIGN.md +98 -6
  66. package/site-templates/marketing-site/DESIGN.md +98 -6
  67. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +60 -27
  68. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +50 -30
  69. package/site-templates/marketing-site-free/DESIGN.md +98 -6
  70. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +60 -24
  71. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +44 -27
  72. package/site-templates/marketing-site-free/ailk-template.json +1 -1
  73. package/site-templates/saas-product/DESIGN.md +98 -6
  74. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.json +127 -18
  75. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +74 -20
  76. package/site-templates/shapes/local-business-service/ailk-template.json +1 -1
  77. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +127 -18
  78. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +74 -20
  79. package/site-templates/shapes/organization-service/ailk-template.json +1 -1
  80. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +127 -18
  81. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +75 -21
  82. package/site-templates/shapes/person-service/ailk-template.json +1 -1
  83. package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +1 -1
  84. package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +2 -2
  85. package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +4 -2
  86. package/site-templates/shapes/person-service/content/en/ServicesList/services.mdx +1 -1
  87. package/templates/.claude/agents/web.md +10 -8
  88. package/templates/.claude/rules/architecture.md +17 -7
  89. package/templates/.claude/skills/README.md +3 -2
  90. package/templates/.claude/skills/add-auth/SKILL.md +142 -90
  91. package/templates/.claude/skills/add-auth/references/env-vars.md +32 -17
  92. package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +17 -8
  93. package/templates/.claude/skills/add-page/SKILL.md +241 -238
  94. package/templates/.claude/skills/add-page/references/page-types.md +94 -86
  95. package/templates/.claude/skills/add-page/scripts/site-pages.mjs +87 -0
  96. package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +99 -0
  97. package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +8 -18
  98. package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +43 -0
  99. package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +52 -0
  100. package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +38 -0
  101. package/templates/.claude/skills/check-site/SKILL.md +51 -18
  102. package/templates/.claude/skills/check-site/references/common-errors.md +12 -9
  103. package/templates/.claude/skills/check-site/references/findings-glossary.md +4 -4
  104. package/templates/.claude/skills/check-site/references/severity-levels.md +3 -3
  105. package/templates/.claude/skills/fill-page/SKILL.md +26 -7
  106. package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +1 -1
  107. package/templates/.claude/skills/setup-deploy/SKILL.md +75 -38
  108. package/templates/.claude/skills/update-page/SKILL.md +117 -0
  109. package/templates/.claude/skills/update-page/scripts/update-page.ts +640 -0
  110. package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +31 -0
  111. package/templates/.claude/skills/upgrade-plan/SKILL.md +12 -8
  112. package/templates/.env.example +23 -2
  113. package/templates/.github/workflows/ci.yml +4 -0
  114. package/templates/.prettierignore +1 -0
  115. package/templates/CLAUDE.md +146 -103
  116. package/templates/DESIGN.md +98 -6
  117. package/templates/README.md +50 -38
  118. package/templates/apps/api/.env.example +2 -1
  119. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +2 -0
  120. package/templates/apps/api/src/__tests__/server.test.ts +116 -0
  121. package/templates/apps/api/src/lib/stripe.ts +9 -0
  122. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +140 -0
  123. package/templates/apps/api/src/middleware/auth.ts +54 -0
  124. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +5 -2
  125. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +628 -0
  126. package/templates/apps/api/src/routes/checkout/sessions.ts +222 -24
  127. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +1 -1
  128. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +5 -1
  129. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +521 -20
  130. package/templates/apps/api/src/routes/webhooks/stripe.ts +124 -32
  131. package/templates/apps/api/src/server.ts +28 -0
  132. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +90 -15
  133. package/templates/apps/api/src/services/checkout-buyer.ts +72 -0
  134. package/templates/apps/api/src/services/revalidation.ts +60 -15
  135. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +30 -24
  136. package/templates/apps/mcp/src/tools/purchase.ts +4 -2
  137. package/templates/apps/web/.env.example +13 -0
  138. package/templates/apps/web/CLAUDE.md +22 -28
  139. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +1 -1
  140. package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +24 -0
  141. package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +17 -6
  142. package/templates/apps/web/app/[locale]/[slug]/[detail]/__tests__/page.test.tsx +110 -0
  143. package/templates/apps/web/app/[locale]/[slug]/[detail]/page.tsx +60 -0
  144. package/templates/apps/web/app/[locale]/[slug]/page.tsx +1 -1
  145. package/templates/apps/web/app/[locale]/alternatives/__tests__/page.test.tsx +161 -0
  146. package/templates/apps/web/app/[locale]/alternatives/page.tsx +104 -0
  147. package/templates/apps/web/app/[locale]/{use-cases → for}/[slug]/page.tsx +4 -3
  148. package/templates/apps/web/app/[locale]/for/__tests__/page-renderer-migration.test.tsx +73 -0
  149. package/templates/apps/web/app/[locale]/{use-cases → for}/page.tsx +8 -7
  150. package/templates/apps/web/app/[locale]/glossary/page.tsx +1 -1
  151. package/templates/apps/web/app/[locale]/layout.tsx +35 -19
  152. package/templates/apps/web/app/[locale]/newsletter/page.tsx +1 -1
  153. package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +1 -1
  154. package/templates/apps/web/app/[locale]/portfolio/page.tsx +1 -1
  155. package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +112 -0
  156. package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +70 -0
  157. package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +236 -44
  158. package/templates/apps/web/app/api/revalidate/route.ts +78 -36
  159. package/templates/apps/web/lib/__tests__/site-brand.test.ts +79 -0
  160. package/templates/apps/web/lib/__tests__/site-theme.test.ts +104 -11
  161. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +21 -4
  162. package/templates/apps/web/lib/locale-guard.ts +18 -0
  163. package/templates/apps/web/lib/meet-placeholder.ts +5 -0
  164. package/templates/apps/web/lib/nav-config.ts +14 -13
  165. package/templates/apps/web/lib/site-brand.tsx +13 -9
  166. package/templates/apps/web/lib/site-logo.tsx +36 -0
  167. package/templates/apps/web/lib/site-theme.ts +46 -26
  168. package/templates/apps/web/messages/en.json +23 -9
  169. package/templates/apps/web/middleware.ts +28 -4
  170. package/templates/content/en/BookCall/book-a-call.mdx +80 -0
  171. package/templates/content/en/BookCall/onsite-estimate.mdx +56 -0
  172. package/templates/content/en/BookCall/onsite-service.mdx +56 -0
  173. package/templates/content/en/BookCall/start-project.mdx +56 -0
  174. package/templates/content/en/ContactPage/contact.mdx +40 -1
  175. package/templates/content/en/HomePage/home.mdx +2 -6
  176. package/templates/content/en/LandingPage/meet.mdx +59 -0
  177. package/templates/content/en/UseCasesList/{use-cases.mdx → for.mdx} +19 -18
  178. package/templates/database/CHANGELOG.md +7 -0
  179. package/templates/database/package.json +1 -1
  180. package/templates/package.json +4 -1
  181. package/templates/tools/check-claude-md.ts +128 -0
  182. package/versions.json +33 -33
  183. package/dist/modules/commerce/0.6.0.tar.gz +0 -0
  184. package/dist/modules/commerce/0.6.1.tar.gz +0 -0
  185. package/dist/modules/docs-blog/0.6.0.tar.gz +0 -0
  186. package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
  187. package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
  188. package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
  189. package/dist/modules/multi-tenant/0.6.0.tar.gz +0 -0
  190. package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
  191. package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
  192. package/dist/modules/scheduling/0.6.0.tar.gz +0 -0
  193. package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
  194. package/dist/modules/signal-collectors/0.6.0.tar.gz +0 -0
  195. package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
  196. package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
  197. package/dist/modules/workspace/0.6.0.tar.gz +0 -0
  198. package/dist/modules/workspace/0.6.1.tar.gz +0 -0
  199. package/site-templates/_base/content/en/BookCall/book-call.mdx +0 -52
  200. package/site-templates/minimalism-site/DESIGN.md +0 -162
  201. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +0 -506
  202. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +0 -458
  203. package/site-templates/minimalism-site/ailk-template.json +0 -23
  204. package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +0 -110
  205. package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +0 -52
  206. package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +0 -34
  207. package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +0 -57
  208. package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +0 -77
  209. package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +0 -73
  210. package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +0 -123
  211. package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +0 -52
  212. package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +0 -52
  213. package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +0 -52
  214. package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +0 -52
  215. package/site-templates/minimalism-site/content/en/Service/first-engagement.mdx +0 -38
  216. package/site-templates/minimalism-site/content/en/Service/second-engagement.mdx +0 -38
  217. package/site-templates/minimalism-site/content/en/Service/third-engagement.mdx +0 -38
  218. package/site-templates/minimalism-site/content/en/ServicesList/services.mdx +0 -73
  219. package/site-templates/minimalism-site/flows/referral.flow.json +0 -71
  220. package/site-templates/minimalism-site/provenance.json +0 -4
  221. package/templates/.claude/skills/add-page/templates/route.tsx.tmpl +0 -28
  222. package/templates/.claude/skills/setup-deploy/references/env-vars-template.md +0 -175
  223. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +0 -8
  224. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +0 -12
  225. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +0 -12
  226. package/templates/apps/web/app/[locale]/book-a-call/page.tsx +0 -50
  227. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +0 -72
  228. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-1.svg +0 -0
  229. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-2.svg +0 -0
  230. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-3.svg +0 -0
  231. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-4.svg +0 -0
  232. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-5.svg +0 -0
  233. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-6.svg +0 -0
  234. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/hero-backdrop.svg +0 -0
  235. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-1.svg +0 -0
  236. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-2.svg +0 -0
  237. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-3.svg +0 -0
  238. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/wordmark-placeholder.svg +0 -0
@@ -1,17 +1,16 @@
1
- <!-- GENERATED — do not hand-edit. Regenerate with:
2
- cd packages/create-ailk && pnpm page-types:build
3
- Source: packages/schema/src/registry/entries.ts
4
- Generator: packages/create-ailk/scripts/generate-page-types-reference.ts
1
+ <!-- GENERATED — do not hand-edit. AI Launch Kit generates this file
2
+ from its page-type registry and ships it with the scaffold. The
3
+ source of record for this site's own page-type registry is `pageTypeRegistry` in the installed `@working-theory/schema` package.
5
4
  -->
6
5
 
7
6
  # Page-Type → schema.org Registry Reference
8
7
 
9
8
  The full page-type catalog the `add-page` skill reads at runtime to
10
9
  resolve a slug or page-purpose hint to a family, chassis, schema.org
11
- `@type`, and route convention. Generated from
12
- `packages/schema/src/registry/entries.ts` — every registered page type
13
- appears exactly once, list/detail pairs are shown together, and no row
14
- here can name a type the registry doesn't have.
10
+ `@type`, and route convention. Generated from the page-type registry
11
+ `@working-theory/schema` exports — every registered page type appears
12
+ exactly once, list/detail pairs are shown together, and no row here
13
+ can name a type the registry doesn't have.
15
14
 
16
15
  The skill resolves in this order:
17
16
 
@@ -20,96 +19,105 @@ The skill resolves in this order:
20
19
  3. **Free-text hint match** — "company story" / "team" → `AboutPage`.
21
20
  4. **Ask** — if nothing matches, ask the consumer rather than guessing.
22
21
 
22
+ **Level** and **Module** name what a page type needs: the module whose
23
+ code renders it, and the level that module comes with. Read the site's
24
+ `.ailk-site-manifest.json` `modules` first — a page type whose Module is
25
+ not in that list is one this site cannot render, so it is never offered;
26
+ name its module and level instead (the `upgrade-plan` skill explains the
27
+ levels). The level is the module's, never a claim about this site's key.
28
+
23
29
  `<slug>` in a route below is the page's own slug (e.g. `hello-world`);
24
30
  `<Type>` families using two-layer builders route supplementary schema
25
31
  through the `schema:` frontmatter override — see this skill's
26
- [Adding schema to an existing page](../SKILL.md#adding-schema-to-an-existing-page) section, or `packages/schema/README.md` for the full
27
- override contract.
32
+ [Adding schema to an existing page](../SKILL.md#adding-schema-to-an-existing-page) section, or the installed `@working-theory/schema`
33
+ package's README for the full override contract.
28
34
 
29
35
  ## Core
30
36
 
31
- | Key | `@type` | Family | Chassis | Route |
32
- | --- | --- | --- | --- | --- |
33
- | `HomePage` | `HomePage` | core | home | / |
34
- | `AboutPage` | `AboutPage` | core | detail | /about |
35
- | `ContactPage` | `ContactPage` | core | detail | /contact |
36
- | `PrivacyPage` | `WebPage` | core | detail | /privacy |
37
- | `TermsPage` | `WebPage` | core | detail | /terms |
38
- | `PurchasePolicyPage` | `WebPage` | core | detail | /purchase-policy |
39
- | `WorkingAgreementPage` | `WebPage` | core | detail | /working-agreement |
40
- | `LandingPage` | `WebPage` | core | home | /<slug> |
41
- | `ThankYouPage` | `WebPage` | core | detail | /thanks/<slug> |
42
- | `BookCall` | `WebPage` | core | home | /book-a-call |
43
- | `NewsletterSignup` | `WebPage` | core | home | /newsletter |
44
- | `DemoRequest` | `WebPage` | core | home | /demo-request |
45
- | `TrialSignup` | `WebPage` | core | home | /trial-signup |
46
- | `Waitlist` | `WebPage` | core | home | /waitlist |
47
- | `Assessment` | `WebApplication` | core | home | /assessment |
48
- | `Calculator` | `WebApplication` | core | home | /calculator |
49
- | `CampaignLP` | `WebPage` | core | home | /<slug> |
37
+ | Key | `@type` | Family | Chassis | Route | Level | Module |
38
+ | --- | --- | --- | --- | --- | --- | --- |
39
+ | `HomePage` | `HomePage` | core | home | / | Free | `marketing` |
40
+ | `AboutPage` | `AboutPage` | core | detail | /about | Free | `marketing` |
41
+ | `ContactPage` | `ContactPage` | core | detail | /contact | Free | `marketing` |
42
+ | `PrivacyPage` | `WebPage` | core | detail | /privacy | Free | `marketing` |
43
+ | `TermsPage` | `WebPage` | core | detail | /terms | Free | `marketing` |
44
+ | `PurchasePolicyPage` | `WebPage` | core | detail | /purchase-policy | Free | `marketing` |
45
+ | `WorkingAgreementPage` | `WebPage` | core | detail | /working-agreement | Free | `marketing` |
46
+ | `LandingPage` | `WebPage` | core | home | /<slug> | Free | `marketing` |
47
+ | `ThankYouPage` | `WebPage` | core | detail | /thanks/<slug> | Free | `marketing` |
48
+ | `BookCall` | `WebPage` | core | home | /meet/:slug | Pro | `scheduling` |
49
+ | `NewsletterSignup` | `WebPage` | core | home | /newsletter | Free | `marketing` |
50
+ | `DemoRequest` | `WebPage` | core | home | /demo-request | Free | `marketing` |
51
+ | `TrialSignup` | `WebPage` | core | home | /trial-signup | Free | `marketing` |
52
+ | `Waitlist` | `WebPage` | core | home | /waitlist | Free | `marketing` |
53
+ | `Assessment` | `WebApplication` | core | home | /assessment | Pro | `signal-collectors` |
54
+ | `Calculator` | `WebApplication` | core | home | /calculator | Pro | `signal-collectors` |
55
+ | `CampaignLP` | `WebPage` | core | home | /<slug> | Free | `marketing` |
50
56
 
51
57
  ## Identity
52
58
 
53
- | Key | `@type` | Family | Chassis | Route |
54
- | --- | --- | --- | --- | --- |
55
- | `Organization` | `Organization` | identity | detail | — site-wide identity — emitted on the home page or in a layout |
56
- | `Person` | `Person` | identity | detail | — site-wide identity — emitted on the home page or in a layout |
57
- | `BreadcrumbList` | `BreadcrumbList` | identity | detail | — site-wide — attached alongside another page's own schema |
58
- | `ContactPoint` | `ContactPoint` | identity | detail | — site-wide — embedded in `Organization` or `Person` |
59
+ | Key | `@type` | Family | Chassis | Route | Level | Module |
60
+ | --- | --- | --- | --- | --- | --- | --- |
61
+ | `Organization` | `Organization` | identity | detail | — site-wide identity — emitted on the home page or in a layout | Free | `marketing` |
62
+ | `Person` | `Person` | identity | detail | — site-wide identity — emitted on the home page or in a layout | Free | `marketing` |
63
+ | `BreadcrumbList` | `BreadcrumbList` | identity | detail | — site-wide — attached alongside another page's own schema | Free | `marketing` |
64
+ | `ContactPoint` | `ContactPoint` | identity | detail | — site-wide — embedded in `Organization` or `Person` | Free | `marketing` |
59
65
 
60
66
  ## Canonical
61
67
 
62
- | Key | `@type` | Family | Chassis | Route |
63
- | --- | --- | --- | --- | --- |
64
- | `ServicesList` | `CollectionPage` | canonical-list | list | /services |
65
- | `Service` | `Service` | canonical-detail | detail | /services/<slug> |
66
- | `ProductsList` | `CollectionPage` | canonical-list | list | /products |
67
- | `Product` | `Product` | canonical-detail | detail | /products/<slug> |
68
- | `ProjectsList` | `CollectionPage` | canonical-list | list | /projects |
69
- | `Project` | `CreativeWork` | canonical-detail | detail | /projects/<slug> |
70
- | `FAQPage` | `FAQPage` | canonical-list | list | /faq |
71
- | `CareersList` | `CollectionPage` | canonical-list | list | /careers |
72
- | `JobPosting` | `JobPosting` | canonical-detail | detail | /careers/<slug> |
73
- | `UseCasesList` | `CollectionPage` | canonical-list | list | /use-cases |
74
- | `UseCase` | `WebPage` | canonical-detail | detail | /use-cases/<slug> |
75
- | `PortfolioList` | `CollectionPage` | canonical-list | list | /portfolio |
76
- | `PortfolioItem` | `WebPage` | canonical-detail | detail | /portfolio/<slug> |
77
- | `FeaturesList` | `CollectionPage` | canonical-list | list | /features |
78
- | `Feature` | `WebPage` | canonical-detail | detail | /features/<slug> |
79
- | `TestimonialsList` | `CollectionPage` | canonical-list | list | /testimonials |
80
- | `ClientsList` | `CollectionPage` | canonical-list | list | /clients |
81
- | `DownloadsList` | `CollectionPage` | canonical-list | list | /downloads |
82
- | `EventsList` | `CollectionPage` | canonical-list | list | /events |
83
- | `Event` | `Event` | canonical-detail | detail | /events/<slug> |
84
- | `CoursesList` | `CollectionPage` | canonical-list | list | /courses |
85
- | `Course` | `Course` | canonical-detail | detail | /courses/<slug> |
86
- | `TeamList` | `CollectionPage` | canonical-list | list | /team |
87
- | `TeamMember` | `ProfilePage` | canonical-detail | detail | /team/<slug> |
88
- | `PartnersList` | `CollectionPage` | canonical-list | list | /partners |
89
- | `Partner` | `AboutPage` | canonical-detail | detail | /partners/<slug> |
90
- | `IntegrationsList` | `CollectionPage` | canonical-list | list | /integrations |
91
- | `Integration` | `WebPage` | canonical-detail | detail | /integrations/<slug> |
92
- | `GlossaryList` | `CollectionPage` | canonical-list | list | /glossary |
93
- | `LocationsList` | `CollectionPage` | canonical-list | list | /locations |
94
- | `Location` | `Place` | canonical-detail | detail | /locations/<slug> |
95
- | `DocsList` | `CollectionPage` | canonical-list | list | /docs |
96
- | `SoftwareProduct` | `WebPage` | canonical-detail | detail | /software/<slug> |
97
- | `ServiceAreaPage` | `WebPage` | canonical-detail | detail | /service-areas/<slug> |
98
- | `Pricing` | `WebPage` | canonical-detail | detail | /pricing |
99
- | `ComparisonPage` | `WebPage` | canonical-detail | detail | /comparisons/<slug> |
100
- | `ReportPage` | `Report` | canonical-detail | detail | /reports/<slug> |
68
+ | Key | `@type` | Family | Chassis | Route | Level | Module |
69
+ | --- | --- | --- | --- | --- | --- | --- |
70
+ | `ServicesList` | `CollectionPage` | canonical-list | list | /services | Free | `marketing` |
71
+ | `Service` | `Service` | canonical-detail | detail | /services/<slug> | Free | `marketing` |
72
+ | `ProductsList` | `CollectionPage` | canonical-list | list | /products | Free | `marketing` |
73
+ | `Product` | `Product` | canonical-detail | detail | /products/<slug> | Free | `marketing` |
74
+ | `ProjectsList` | `CollectionPage` | canonical-list | list | /projects | Free | `marketing` |
75
+ | `Project` | `CreativeWork` | canonical-detail | detail | /projects/<slug> | Free | `marketing` |
76
+ | `FAQPage` | `FAQPage` | canonical-list | list | /faq | Free | `marketing` |
77
+ | `CareersList` | `CollectionPage` | canonical-list | list | /careers | Free | `marketing` |
78
+ | `JobPosting` | `JobPosting` | canonical-detail | detail | /careers/<slug> | Free | `marketing` |
79
+ | `UseCasesList` | `CollectionPage` | canonical-list | list | /for | Free | `marketing` |
80
+ | `UseCase` | `WebPage` | canonical-detail | detail | /for/<slug> | Free | `marketing` |
81
+ | `PortfolioList` | `CollectionPage` | canonical-list | list | /portfolio | Free | `marketing` |
82
+ | `PortfolioItem` | `WebPage` | canonical-detail | detail | /portfolio/<slug> | Free | `marketing` |
83
+ | `FeaturesList` | `CollectionPage` | canonical-list | list | /features | Free | `marketing` |
84
+ | `Feature` | `WebPage` | canonical-detail | detail | /features/<slug> | Free | `marketing` |
85
+ | `ComparisonsList` | `CollectionPage` | canonical-list | list | /alternatives | Free | `marketing` |
86
+ | `ComparisonPage` | `WebPage` | canonical-detail | detail | /vs/<slug> | Free | `marketing` |
87
+ | `ReportsList` | `CollectionPage` | canonical-list | list | /reports | Free | `marketing` |
88
+ | `ReportPage` | `Report` | canonical-detail | detail | /reports/<slug> | Pro | `signal-collectors` |
89
+ | `TestimonialsList` | `CollectionPage` | canonical-list | list | /testimonials | Free | `marketing` |
90
+ | `ClientsList` | `CollectionPage` | canonical-list | list | /clients | Free | `marketing` |
91
+ | `DownloadsList` | `CollectionPage` | canonical-list | list | /downloads | Free | `marketing` |
92
+ | `EventsList` | `CollectionPage` | canonical-list | list | /events | Free | `marketing` |
93
+ | `Event` | `Event` | canonical-detail | detail | /events/<slug> | Free | `marketing` |
94
+ | `CoursesList` | `CollectionPage` | canonical-list | list | /courses | Free | `marketing` |
95
+ | `Course` | `Course` | canonical-detail | detail | /courses/<slug> | Free | `marketing` |
96
+ | `TeamList` | `CollectionPage` | canonical-list | list | /team | Free | `marketing` |
97
+ | `TeamMember` | `ProfilePage` | canonical-detail | detail | /team/<slug> | Free | `marketing` |
98
+ | `PartnersList` | `CollectionPage` | canonical-list | list | /partners | Free | `marketing` |
99
+ | `Partner` | `AboutPage` | canonical-detail | detail | /partners/<slug> | Free | `marketing` |
100
+ | `IntegrationsList` | `CollectionPage` | canonical-list | list | /integrations | Free | `marketing` |
101
+ | `Integration` | `WebPage` | canonical-detail | detail | /integrations/<slug> | Free | `marketing` |
102
+ | `GlossaryList` | `CollectionPage` | canonical-list | list | /glossary | Free | `marketing` |
103
+ | `LocationsList` | `CollectionPage` | canonical-list | list | /locations | Free | `marketing` |
104
+ | `Location` | `Place` | canonical-detail | detail | /locations/<slug> | Free | `marketing` |
105
+ | `DocsList` | `CollectionPage` | canonical-list | list | /docs | Pro | `docs-blog` |
106
+ | `SoftwareProduct` | `WebPage` | canonical-detail | detail | /software/<slug> | Free | `marketing` |
107
+ | `ServiceAreaPage` | `WebPage` | canonical-detail | detail | /service-areas/<slug> | Free | `marketing` |
108
+ | `Pricing` | `WebPage` | canonical-detail | detail | /pricing | Free | `marketing` |
101
109
 
102
110
  ## Editorial
103
111
 
104
- | Key | `@type` | Family | Chassis | Route |
105
- | --- | --- | --- | --- | --- |
106
- | `BlogList` | `Blog` | editorial-list | list | /blog |
107
- | `BlogPosting` | `BlogPosting` | editorial-detail | detail | /blog/<slug> |
108
- | `ResourcesHub` | `CollectionPage` | editorial-list | list | /resources |
109
- | `ResourceDetail` | `Article` | editorial-detail | detail | /resources/<slug> |
110
- | `CaseStudiesList` | `CollectionPage` | editorial-list | list | /case-studies |
111
- | `CaseStudy` | `Article` | editorial-detail | detail | /case-studies/<slug> |
112
- | `HowTo` | `HowTo` | editorial-detail | detail | /how-to/<slug> |
113
- | `Whitepaper` | `Article` | editorial-detail | detail | /whitepapers/<slug> |
114
- | `TechArticle` | `TechArticle` | editorial-detail | detail | /tech-articles/<slug> |
115
- | `DocsDetail` | `TechArticle` | editorial-detail | detail | /docs/<slug> |
112
+ | Key | `@type` | Family | Chassis | Route | Level | Module |
113
+ | --- | --- | --- | --- | --- | --- | --- |
114
+ | `BlogList` | `Blog` | editorial-list | list | /blog | Free | `marketing` |
115
+ | `BlogPosting` | `BlogPosting` | editorial-detail | detail | /blog/<slug> | Pro | `docs-blog` |
116
+ | `ResourcesHub` | `CollectionPage` | editorial-list | list | /resources | Free | `marketing` |
117
+ | `ResourceDetail` | `Article` | editorial-detail | detail | /resources/<slug> | Free | `marketing` |
118
+ | `CaseStudiesList` | `CollectionPage` | editorial-list | list | /case-studies | Free | `marketing` |
119
+ | `CaseStudy` | `Article` | editorial-detail | detail | /case-studies/<slug> | Free | `marketing` |
120
+ | `HowTo` | `HowTo` | editorial-detail | detail | /how-to/<slug> | Free | `marketing` |
121
+ | `Whitepaper` | `Article` | editorial-detail | detail | /whitepapers/<slug> | Free | `marketing` |
122
+ | `TechArticle` | `TechArticle` | editorial-detail | detail | /tech-articles/<slug> | Free | `marketing` |
123
+ | `DocsDetail` | `TechArticle` | editorial-detail | detail | /docs/<slug> | Pro | `docs-blog` |
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ // site-pages.mjs — report what THIS site can serve, read from the site itself.
3
+ //
4
+ // Usage: node .claude/skills/add-page/scripts/site-pages.mjs [--json] [<site-root>]
5
+ //
6
+ // It scans apps/web/app/[locale]/**/page.tsx for the page type each route
7
+ // renders (the `type: "X"` literal in renderPage / renderPageMetadata, or a
8
+ // getMdxSource("X", …) call), then pairs each type with its content folder and
9
+ // the pages already written there. It also echoes .ailk-site-manifest.json's
10
+ // shape, design and (when recorded) level. Read-only: it never writes.
11
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
12
+ import { join, relative, sep } from "node:path";
13
+
14
+ const args = process.argv.slice(2);
15
+ const asJson = args.includes("--json");
16
+ const root = args.find((a) => !a.startsWith("--")) ?? process.cwd();
17
+ const appRoot = join(root, "apps/web/app/[locale]");
18
+ if (!existsSync(appRoot)) {
19
+ console.error(`site-pages: ${appRoot} not found — run from the site's root.`);
20
+ process.exit(2);
21
+ }
22
+
23
+ // Types whose content lives outside content/<locale>/<Type>.
24
+ const CONTENT_OVERRIDES = {
25
+ BlogPosting: "apps/web/content/en/blog",
26
+ BlogList: "apps/web/content/en/blog",
27
+ DocsDetail: "apps/web/content/en/docs",
28
+ DocsList: "apps/web/content/en/docs",
29
+ };
30
+
31
+ function walk(dir, out = []) {
32
+ for (const name of readdirSync(dir)) {
33
+ const abs = join(dir, name);
34
+ if (name === "__tests__" || name === "node_modules") continue;
35
+ if (statSync(abs).isDirectory()) walk(abs, out);
36
+ else if (name === "page.tsx") out.push(abs);
37
+ }
38
+ return out;
39
+ }
40
+
41
+ const routes = [];
42
+ for (const file of walk(appRoot)) {
43
+ const src = readFileSync(file, "utf8");
44
+ const types = new Set();
45
+ for (const m of src.matchAll(/type:\s*"([A-Z][A-Za-z]+)"/g)) types.add(m[1]);
46
+ for (const m of src.matchAll(/getMdxSource\(\s*"([A-Z][A-Za-z]+)"/g)) types.add(m[1]);
47
+ const dir = relative(appRoot, file).split(sep).slice(0, -1);
48
+ // Route groups like (auth) do not appear in the URL.
49
+ const path = "/" + dir.filter((s) => !/^\(.*\)$/.test(s)).join("/");
50
+ const dynamic = dir.some((s) => s.startsWith("["));
51
+ routes.push({ route: path === "/" ? "/" : path, file: relative(root, file), types: [...types], dynamic });
52
+ }
53
+
54
+ const byType = {};
55
+ for (const r of routes) {
56
+ for (const t of r.types) {
57
+ const entry = (byType[t] ??= { type: t, routes: [], contentDir: CONTENT_OVERRIDES[t] ?? `content/en/${t}`, pages: [] });
58
+ entry.routes.push(r.route);
59
+ }
60
+ }
61
+ for (const e of Object.values(byType)) {
62
+ const abs = join(root, e.contentDir);
63
+ if (existsSync(abs)) {
64
+ e.pages = readdirSync(abs).filter((f) => /\.mdx?$/.test(f)).map((f) => f.replace(/\.mdx?$/, ""));
65
+ }
66
+ // A type served by a dynamic route takes new pages; a static-only type is one page.
67
+ e.takesNewPages = routes.some((r) => r.dynamic && r.types.includes(e.type));
68
+ }
69
+
70
+ let manifest = null;
71
+ const manifestPath = join(root, ".ailk-site-manifest.json");
72
+ if (existsSync(manifestPath)) {
73
+ const m = JSON.parse(readFileSync(manifestPath, "utf8"));
74
+ manifest = { shape: m.shape ?? null, design: m.design ?? null, level: m.level ?? null, modules: m.modules ?? m.requires ?? null };
75
+ }
76
+
77
+ const result = { manifest, types: Object.values(byType).sort((a, b) => a.type.localeCompare(b.type)) };
78
+ if (asJson) {
79
+ console.log(JSON.stringify(result, null, 2));
80
+ } else {
81
+ if (manifest) console.log(`shape: ${manifest.shape} design: ${manifest.design} level: ${manifest.level ?? "(not recorded)"}`);
82
+ console.log("");
83
+ console.log("type".padEnd(22) + "route(s)".padEnd(34) + "new pages?".padEnd(12) + "existing");
84
+ for (const e of result.types) {
85
+ console.log(e.type.padEnd(22) + e.routes.join(" ").padEnd(34) + (e.takesNewPages ? "yes" : "no").padEnd(12) + (e.pages.join(", ") || "—"));
86
+ }
87
+ }
@@ -0,0 +1,99 @@
1
+ ---
2
+ type: ComparisonPage
3
+ slug: {{SLUG}}
4
+ placeholder: true
5
+ title: {{TITLE}}
6
+ description: {{DESCRIPTION}}
7
+ sections:
8
+ [
9
+ {
10
+ "id": "hero",
11
+ "type": "hero",
12
+ "data":
13
+ {
14
+ "eyebrow": "Comparisons",
15
+ "headline": "{{TITLE}}",
16
+ "subheadline": "{{DESCRIPTION}}",
17
+ "primaryCta": { "label": "{Primary CTA}", "href": "/contact" },
18
+ },
19
+ },
20
+ {
21
+ "id": "decision-split",
22
+ "type": "decision-split",
23
+ "data":
24
+ {
25
+ "headline": "{Which one fits you}",
26
+ "panels":
27
+ [
28
+ {
29
+ "title": "{{TITLE}}",
30
+ "checklist":
31
+ [
32
+ "{Reason 1 to choose us}",
33
+ "{Reason 2 to choose us}",
34
+ "{Reason 3 to choose us}",
35
+ ],
36
+ },
37
+ {
38
+ "title": "{The alternative}",
39
+ "glyph": "cross",
40
+ "checklist":
41
+ [
42
+ "{Reason 1 to choose them instead}",
43
+ "{Reason 2 to choose them instead}",
44
+ ],
45
+ },
46
+ ],
47
+ },
48
+ },
49
+ {
50
+ "id": "comparison-table",
51
+ "type": "comparison-table",
52
+ "data":
53
+ {
54
+ "headline": "{How they compare}",
55
+ "columns":
56
+ [
57
+ { "key": "us", "name": "{{TITLE}}", "highlighted": true },
58
+ { "key": "them", "name": "{The alternative}" },
59
+ ],
60
+ "groups":
61
+ [
62
+ {
63
+ "groupName": "{Core features}",
64
+ "rows":
65
+ [
66
+ {
67
+ "featureName": "{Feature 1}",
68
+ "values": { "us": true, "them": false },
69
+ },
70
+ {
71
+ "featureName": "{Feature 2}",
72
+ "values": { "us": true, "them": true },
73
+ },
74
+ ],
75
+ },
76
+ ],
77
+ },
78
+ },
79
+ {
80
+ "id": "cta",
81
+ "type": "cta",
82
+ "data":
83
+ {
84
+ "variant": "box",
85
+ "headline": "{Ready to switch?}",
86
+ "description": "{One sentence on what happens next}",
87
+ "primaryCta": { "label": "{Primary CTA}", "href": "/contact" },
88
+ "secondaryCta":
89
+ {
90
+ "label": "See all alternatives",
91
+ "href": "/alternatives",
92
+ "variant": "outline",
93
+ },
94
+ },
95
+ },
96
+ ]
97
+ ---
98
+
99
+ {/* Rendered from frontmatter `sections[]` by the /vs/<slug> route (D10 — the generic detail chassis: hero, decision-split, comparison-table, cta; no dedicated comparison section). Listed automatically by the /alternatives hub. Placeholder copy — replace every {brace} with your own words before you launch. */}
@@ -5,24 +5,14 @@ title: {{TITLE}}
5
5
  description: {{DESCRIPTION}}
6
6
  ---
7
7
 
8
+ {/*
9
+ Written by the add-page skill, used only when this site had no other page of
10
+ this type to copy. The frontmatter drives the page's route and its JSON-LD:
11
+ keep `type` as it is, and make `description` a true one-sentence summary.
12
+ Run `fill-page` to write the real copy, then `check-site` to score it.
13
+ Extra structured data goes in a `schema:` block — see the add-page skill.
14
+ */}
15
+
8
16
  # {{TITLE}}
9
17
 
10
18
  {{DESCRIPTION}}
11
-
12
- <!--
13
- This is the MDX content stub emitted by `add-page`.
14
- The frontmatter is the source of truth for JSON-LD — the
15
- `{{BUILDER}}(page)` call in `app/{{SLUG}}/page.tsx` reads it.
16
-
17
- Edit this file freely:
18
- - Add sections, prose, components imported from your project.
19
- - Update `description` (it's used both as the meta description
20
- and as input to the JSON-LD builder).
21
- - Don't change `type` unless you also update the route's import
22
- to match a different `@working-theory/schema` builder.
23
-
24
- When you're happy with the page, run `check-site` to see
25
- how it scores on citation-readiness. Use the `schema:` frontmatter
26
- override to add supplementary schema (FAQPage, HowTo, etc.) without
27
- re-scaffolding.
28
- -->
@@ -0,0 +1,43 @@
1
+ ---
2
+ type: LandingPage
3
+ slug: {{SLUG}}
4
+ placeholder: true
5
+ title: {{TITLE}}
6
+ description: {{DESCRIPTION}}
7
+ sections:
8
+ [
9
+ {
10
+ "id": "hero",
11
+ "type": "hero",
12
+ "data":
13
+ {
14
+ "variant": "centered",
15
+ "eyebrow": "{{TITLE}}",
16
+ "headline": "{{TITLE}}",
17
+ "subheadline": "{{DESCRIPTION}}",
18
+ "primaryCta":
19
+ { "label": "{Get started →}", "href": "/flows/{{FLOW_SLUG}}/start" },
20
+ "ctaSize": "xl",
21
+ },
22
+ },
23
+ {
24
+ "id": "request",
25
+ "type": "cta",
26
+ "data":
27
+ {
28
+ "variant": "minimal",
29
+ "headline": "{Ready?}",
30
+ "primaryCta":
31
+ { "label": "{Get started →}", "href": "/flows/{{FLOW_SLUG}}/start" },
32
+ },
33
+ },
34
+ ]
35
+ ---
36
+
37
+ {/* This page's CTA opens the `{{FLOW_SLUG}}` flow at
38
+ /flows/{{FLOW_SLUG}}/start — a signal-collectors module route, not a page
39
+ this seed owns. The flow definition itself
40
+ (`database/flows/{{FLOW_SLUG}}.flow.json`) is a separate artifact this
41
+ skill does not write; seed it via the flow engine before this page's CTA
42
+ resolves. Placeholder copy — replace every {brace} with your own words
43
+ before you launch. */}
@@ -0,0 +1,52 @@
1
+ ---
2
+ type: ReportPage
3
+ slug: {{SLUG}}
4
+ placeholder: true
5
+ title: {{TITLE}}
6
+ description: {{DESCRIPTION}}
7
+ schema:
8
+ datePublished: "{{DATE_PUBLISHED}}"
9
+ author:
10
+ "@type": Organization
11
+ name: "{Your Company}"
12
+ sections:
13
+ [
14
+ {
15
+ "id": "header",
16
+ "type": "report-header",
17
+ "data":
18
+ {
19
+ "title": "{{TITLE}}",
20
+ "eyebrow": "{{DATE_LABEL}}",
21
+ "backHref": "/reports",
22
+ "backLabel": "All reports",
23
+ "tone": "on-dark",
24
+ },
25
+ },
26
+ {
27
+ "id": "document",
28
+ "type": "document-viewer",
29
+ "data":
30
+ {
31
+ "src": "/reports/sample-report.pdf",
32
+ "geometry": "16:9",
33
+ "pages": 8,
34
+ "downloadFilename": "{{SLUG}}.pdf",
35
+ "outline":
36
+ [
37
+ { "id": "opening", "label": "Opening", "startPage": 1 },
38
+ { "id": "findings", "label": "Findings", "startPage": 3 },
39
+ { "id": "outlook", "label": "Outlook", "startPage": 6 },
40
+ ],
41
+ },
42
+ },
43
+ ]
44
+ ---
45
+
46
+ {/* A PLACEHOLDER report. Its bytes are the signal-collectors module's own
47
+ sample PDF (apps/web/public/reports/sample-report.pdf), shared by every
48
+ sample report so the site ships no binary of its own. Point `src` at your
49
+ real document and set `pages` to its real page count. Rendered by the
50
+ signal-collectors module's own /reports/<slug> route (`app/[locale]/reports/[slug]/page.tsx`)
51
+ and listed automatically by the /reports hub (ReportsList) — never
52
+ hand-list a report there. */}
@@ -0,0 +1,38 @@
1
+ ---
2
+ type: ReportsList
3
+ slug: reports
4
+ placeholder: true
5
+ title: {{TITLE}}
6
+ description: {{DESCRIPTION}}
7
+ sections:
8
+ [
9
+ {
10
+ "id": "hero",
11
+ "type": "hero",
12
+ "data":
13
+ {
14
+ "variant": "centered",
15
+ "eyebrow": "Reports",
16
+ "headline": "{{TITLE}}",
17
+ "subheadline": "{{DESCRIPTION}}",
18
+ },
19
+ },
20
+ {
21
+ "id": "closing",
22
+ "type": "cta",
23
+ "data":
24
+ {
25
+ "variant": "minimal",
26
+ "headline": "{Want the next one as it lands?}",
27
+ "primaryCta": { "label": "{Contact me →}", "href": "/contact" },
28
+ },
29
+ },
30
+ ]
31
+ ---
32
+
33
+ {/* Rendered from frontmatter `sections[]` by the /reports route
34
+ (`app/[locale]/reports/page.tsx`). Its card list is GENERATED, not
35
+ authored here (spec 6892 D2): the route appends one `reports-list`
36
+ section listing every ReportPage seed, so this seed carries only its own
37
+ hero and closing cta. Placeholder copy — replace every {brace} with your
38
+ own words before you launch. */}