create-ailk 0.4.0 → 0.6.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 (396) hide show
  1. package/README.md +55 -8
  2. package/component-catalog.json +12248 -0
  3. package/component-catalog.md +193 -68
  4. package/dist/cli.js +29 -1
  5. package/dist/derive-architecture.js +5 -2
  6. package/dist/lib/api-boot-assertion.d.ts +46 -0
  7. package/dist/lib/api-boot-assertion.js +70 -0
  8. package/dist/lib/extract-module-bundle.d.ts +50 -2
  9. package/dist/lib/extract-module-bundle.js +223 -15
  10. package/dist/lib/fetch-guard.d.ts +28 -0
  11. package/dist/lib/fetch-guard.js +101 -0
  12. package/dist/lib/fetch-module.js +4 -0
  13. package/dist/lib/fetch-template.js +4 -0
  14. package/dist/lib/import-graph.d.ts +29 -0
  15. package/dist/lib/import-graph.js +140 -0
  16. package/dist/module-architecture.d.ts +60 -8
  17. package/dist/module-architecture.js +587 -242
  18. package/dist/parse-args.js +6 -2
  19. package/dist/programmatic.d.ts +10 -0
  20. package/dist/programmatic.js +134 -19
  21. package/dist/site-chrome.d.ts +80 -0
  22. package/dist/site-chrome.js +135 -0
  23. package/dist/surfaces.d.ts +21 -6
  24. package/dist/surfaces.js +209 -36
  25. package/dist/template-manifest.d.ts +88 -3
  26. package/dist/template-manifest.js +281 -29
  27. package/dist/template-names.d.ts +1 -1
  28. package/dist/template-names.js +2 -0
  29. package/package.json +10 -2
  30. package/site-templates/_base/ailk-template.json +6 -0
  31. package/site-templates/_base/content/en/Pricing/pricing.mdx +169 -0
  32. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +351 -0
  33. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +400 -0
  34. package/site-templates/marketing-site/ailk-template.json +11 -0
  35. package/site-templates/marketing-site/content/en/blog/05-this-vc-morning-routine-will-make-you-super-annoying.mdx +36 -0
  36. package/site-templates/marketing-site/provenance.json +4 -0
  37. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +288 -0
  38. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +286 -0
  39. package/site-templates/marketing-site-free/ailk-template.json +2 -1
  40. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +279 -0
  41. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +336 -0
  42. package/site-templates/minimalism-site/ailk-template.json +22 -0
  43. package/site-templates/minimalism-site/assets/avatar-placeholder-1.svg +7 -0
  44. package/site-templates/minimalism-site/assets/avatar-placeholder-2.svg +7 -0
  45. package/site-templates/minimalism-site/assets/avatar-placeholder-3.svg +7 -0
  46. package/site-templates/minimalism-site/assets/avatar-placeholder-4.svg +7 -0
  47. package/site-templates/minimalism-site/assets/avatar-placeholder-5.svg +7 -0
  48. package/site-templates/minimalism-site/assets/avatar-placeholder-6.svg +7 -0
  49. package/site-templates/minimalism-site/assets/hero-backdrop.svg +17 -0
  50. package/site-templates/minimalism-site/assets/logo-placeholder-1.svg +6 -0
  51. package/site-templates/minimalism-site/assets/logo-placeholder-2.svg +6 -0
  52. package/site-templates/minimalism-site/assets/logo-placeholder-3.svg +6 -0
  53. package/site-templates/minimalism-site/assets/wordmark-placeholder.svg +28 -0
  54. package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +110 -0
  55. package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +68 -0
  56. package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +57 -0
  57. package/site-templates/minimalism-site/content/en/HomePage/home.mdx +244 -0
  58. package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +77 -0
  59. package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +73 -0
  60. package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +52 -0
  61. package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +52 -0
  62. package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +52 -0
  63. package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +52 -0
  64. package/site-templates/minimalism-site/content/en/Service/first-engagement.mdx +38 -0
  65. package/site-templates/minimalism-site/content/en/Service/second-engagement.mdx +38 -0
  66. package/site-templates/minimalism-site/content/en/Service/third-engagement.mdx +38 -0
  67. package/site-templates/minimalism-site/content/en/ServicesList/services.mdx +73 -0
  68. package/site-templates/minimalism-site/flows/referral.flow.json +71 -0
  69. package/site-templates/minimalism-site/provenance.json +4 -0
  70. package/site-templates/saas-product/TEMPLATE-MANIFEST.md +61 -0
  71. package/site-templates/saas-product/ailk-template.json +16 -0
  72. package/site-templates/saas-product/provenance.json +10 -0
  73. package/site-templates/simple-service/TEMPLATE-MANIFEST.json +240 -0
  74. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +278 -0
  75. package/site-templates/simple-service/ailk-template.json +10 -0
  76. package/site-templates/simple-service/content/en/AboutPage/about.mdx +38 -0
  77. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +67 -0
  78. package/site-templates/simple-service/content/en/FAQPage/faq.mdx +56 -0
  79. package/site-templates/simple-service/content/en/HomePage/home.mdx +85 -0
  80. package/site-templates/simple-service/content/en/Service/landscape-design.mdx +40 -0
  81. package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +40 -0
  82. package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +40 -0
  83. package/site-templates/simple-service/content/en/ServicesList/services.mdx +72 -0
  84. package/site-templates/simple-service/provenance.json +4 -0
  85. package/templates/.claude/skills/README.md +16 -25
  86. package/templates/.env.example +102 -12
  87. package/templates/.github/workflows/ci.yml +48 -0
  88. package/templates/README.md +3 -1
  89. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +8 -0
  90. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +12 -0
  91. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +12 -0
  92. package/templates/apps/api/.env.example +13 -0
  93. package/templates/apps/api/CLAUDE.md +29 -2
  94. package/templates/apps/api/eslint.config.mjs +69 -0
  95. package/templates/apps/api/jest.config.cjs +3 -0
  96. package/templates/apps/api/package.json +7 -2
  97. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +407 -0
  98. package/templates/apps/api/src/__tests__/module-exclusion.test.ts +89 -9
  99. package/templates/apps/api/src/__tests__/review-surface-registration.test.ts +167 -0
  100. package/templates/apps/api/src/__tests__/server.test.ts +471 -0
  101. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +45 -0
  102. package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +10 -1
  103. package/templates/apps/api/src/config/index.ts +62 -0
  104. package/templates/apps/api/src/config/modules.ts +7 -3
  105. package/templates/apps/api/src/lib/__mocks__/prisma.ts +241 -2
  106. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +143 -0
  107. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +23 -0
  108. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +125 -0
  109. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +20 -0
  110. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +317 -0
  111. package/templates/apps/api/src/lib/__tests__/site.test.ts +238 -0
  112. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +75 -0
  113. package/templates/apps/api/src/lib/auth-email-budget.ts +160 -0
  114. package/templates/apps/api/src/lib/content-adapter.ts +57 -31
  115. package/templates/apps/api/src/lib/deliverable-asset-store.ts +76 -0
  116. package/templates/apps/api/src/lib/error-serializer.ts +23 -3
  117. package/templates/apps/api/src/lib/outbound-http.ts +7 -2
  118. package/templates/apps/api/src/lib/require-commerce-claim.ts +250 -0
  119. package/templates/apps/api/src/lib/site.ts +208 -9
  120. package/templates/apps/api/src/lib/stripe.ts +66 -0
  121. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +521 -0
  122. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +150 -0
  123. package/templates/apps/api/src/middleware/default-tenant.ts +136 -0
  124. package/templates/apps/api/src/middleware/rate-limit.ts +7 -1
  125. package/templates/apps/api/src/openapi/spec.ts +543 -2
  126. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +48 -0
  127. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +309 -0
  128. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +123 -0
  129. package/templates/apps/api/src/routes/auth/transactional-email.ts +273 -0
  130. package/templates/apps/api/src/routes/auth/user.ts +61 -0
  131. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +434 -0
  132. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +888 -0
  133. package/templates/apps/api/src/routes/checkout/index.ts +34 -0
  134. package/templates/apps/api/src/routes/checkout/session.ts +139 -0
  135. package/templates/apps/api/src/routes/checkout/sessions.ts +197 -0
  136. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +554 -0
  137. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +108 -0
  138. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +450 -0
  139. package/templates/apps/api/src/routes/content/get-page.ts +94 -12
  140. package/templates/apps/api/src/routes/content/index.ts +13 -73
  141. package/templates/apps/api/src/routes/content/list-pages.ts +15 -3
  142. package/templates/apps/api/src/routes/content/rate-limit.ts +15 -6
  143. package/templates/apps/api/src/routes/content/search.ts +129 -0
  144. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +447 -31
  145. package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +171 -0
  146. package/templates/apps/api/src/routes/leads/index.ts +100 -13
  147. package/templates/apps/api/src/routes/leads/list.ts +104 -0
  148. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +51 -0
  149. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +351 -0
  150. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +51 -0
  151. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +5 -2
  152. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +4 -1
  153. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +58 -0
  154. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +107 -6
  155. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +87 -2
  156. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +51 -0
  157. package/templates/apps/api/src/routes/project-listings/start.ts +5 -1
  158. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +686 -0
  159. package/templates/apps/api/src/routes/requests/confirm.ts +601 -0
  160. package/templates/apps/api/src/routes/requests/index.ts +54 -0
  161. package/templates/apps/api/src/routes/webhooks/README.md +265 -0
  162. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +749 -0
  163. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +330 -0
  164. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +262 -0
  165. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +285 -0
  166. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +213 -0
  167. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +301 -0
  168. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +648 -0
  169. package/templates/apps/api/src/routes/webhooks/index.ts +89 -0
  170. package/templates/apps/api/src/routes/webhooks/stripe.ts +1399 -0
  171. package/templates/apps/api/src/server.ts +521 -55
  172. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +39 -0
  173. package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +217 -40
  174. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +620 -0
  175. package/templates/apps/api/src/services/__tests__/consent.test.ts +2 -0
  176. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +300 -5
  177. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +20 -0
  178. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +368 -0
  179. package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +408 -0
  180. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +160 -0
  181. package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +329 -0
  182. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +166 -0
  183. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +154 -0
  184. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +137 -0
  185. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +444 -0
  186. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +238 -0
  187. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +78 -0
  188. package/templates/apps/api/src/services/abandon-email.ts +8 -2
  189. package/templates/apps/api/src/services/aeo-score.ts +49 -12
  190. package/templates/apps/api/src/services/audit-log.ts +668 -0
  191. package/templates/apps/api/src/services/consent.ts +18 -0
  192. package/templates/apps/api/src/services/default-tenant.ts +300 -0
  193. package/templates/apps/api/src/services/deliverable-fulfillment.ts +141 -13
  194. package/templates/apps/api/src/services/dunning-policy.ts +294 -0
  195. package/templates/apps/api/src/services/entitlements.ts +80 -0
  196. package/templates/apps/api/src/services/lead-promotion.ts +160 -0
  197. package/templates/apps/api/src/services/lead-routing.ts +161 -2
  198. package/templates/apps/api/src/services/leads-inbox.ts +284 -0
  199. package/templates/apps/api/src/services/listing-config.ts +27 -9
  200. package/templates/apps/api/src/services/owner-workspaces.ts +132 -0
  201. package/templates/apps/api/src/services/project-listings.ts +201 -6
  202. package/templates/apps/api/src/services/public-site-resolver.ts +106 -0
  203. package/templates/apps/api/src/services/request-confirm.ts +646 -0
  204. package/templates/apps/api/src/services/revalidation.ts +173 -0
  205. package/templates/apps/api/src/services/verified-email.ts +71 -0
  206. package/templates/apps/api/src/vercel-handler.ts +75 -35
  207. package/templates/apps/mcp/.env.example +17 -0
  208. package/templates/apps/mcp/CLAUDE.md +58 -25
  209. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +6 -0
  210. package/templates/apps/mcp/__tests__/audit.test.ts +137 -8
  211. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +79 -36
  212. package/templates/apps/mcp/__tests__/get_offerings.test.ts +111 -2
  213. package/templates/apps/mcp/__tests__/get_pricing.test.ts +82 -2
  214. package/templates/apps/mcp/__tests__/http-transport.test.ts +541 -2
  215. package/templates/apps/mcp/__tests__/index.test.ts +39 -0
  216. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +143 -0
  217. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +111 -0
  218. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +65 -0
  219. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +188 -0
  220. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +165 -0
  221. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +124 -0
  222. package/templates/apps/mcp/__tests__/list_pages.test.ts +116 -0
  223. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +7 -1
  224. package/templates/apps/mcp/__tests__/parity.test.ts +12 -9
  225. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +89 -22
  226. package/templates/apps/mcp/__tests__/read_content.test.ts +322 -1
  227. package/templates/apps/mcp/__tests__/search_content.test.ts +105 -2
  228. package/templates/apps/mcp/__tests__/server.test.ts +67 -14
  229. package/templates/apps/mcp/__tests__/start_purchase.test.ts +252 -0
  230. package/templates/apps/mcp/__tests__/tools/{scaffold.test.ts → create_project.test.ts} +23 -23
  231. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +300 -123
  232. package/templates/apps/mcp/eslint.config.mjs +69 -0
  233. package/templates/apps/mcp/jest.config.cjs +13 -0
  234. package/templates/apps/mcp/package.json +8 -2
  235. package/templates/apps/mcp/src/abuse/index.ts +159 -24
  236. package/templates/apps/mcp/src/config/modules.ts +10 -5
  237. package/templates/apps/mcp/src/http-transport.ts +102 -29
  238. package/templates/apps/mcp/src/index.ts +73 -11
  239. package/templates/apps/mcp/src/lib/audit-single-page.ts +90 -3
  240. package/templates/apps/mcp/src/lib/commerce-claim.ts +94 -0
  241. package/templates/apps/mcp/src/lib/content-adapter.ts +113 -0
  242. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +139 -0
  243. package/templates/apps/mcp/src/lib/prisma.ts +39 -0
  244. package/templates/apps/mcp/src/lib/public-workspace.ts +133 -0
  245. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +59 -0
  246. package/templates/apps/mcp/src/server.ts +61 -37
  247. package/templates/apps/mcp/src/tools/audit.ts +26 -2
  248. package/templates/apps/mcp/src/tools/{scaffold.ts → create_project.ts} +3 -3
  249. package/templates/apps/mcp/src/tools/get_business_hours.ts +4 -3
  250. package/templates/apps/mcp/src/tools/get_faq.ts +4 -3
  251. package/templates/apps/mcp/src/tools/get_locations.ts +5 -3
  252. package/templates/apps/mcp/src/tools/get_offerings.ts +16 -4
  253. package/templates/apps/mcp/src/tools/get_pricing.ts +25 -6
  254. package/templates/apps/mcp/src/tools/get_site_info.ts +4 -3
  255. package/templates/apps/mcp/src/tools/index.ts +9 -7
  256. package/templates/apps/mcp/src/tools/list_pages.ts +4 -3
  257. package/templates/apps/mcp/src/tools/purchase.ts +128 -45
  258. package/templates/apps/mcp/src/tools/read_content.ts +20 -6
  259. package/templates/apps/mcp/src/tools/search_content.ts +11 -4
  260. package/templates/apps/web/.env.example +74 -8
  261. package/templates/apps/web/CLAUDE.md +46 -0
  262. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +18 -2
  263. package/templates/apps/web/app/.well-known/mcp.json/route.ts +11 -3
  264. package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +282 -0
  265. package/templates/apps/web/app/[locale]/(auth)/__tests__/password-reset.test.tsx +515 -0
  266. package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +89 -0
  267. package/templates/apps/web/app/[locale]/(auth)/forgot-password/page.tsx +109 -0
  268. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +92 -0
  269. package/templates/apps/web/app/[locale]/(auth)/reset-password/page.tsx +135 -0
  270. package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +109 -0
  271. package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/page.test.tsx +48 -2
  272. package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/page.tsx +20 -6
  273. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +125 -0
  274. package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +96 -0
  275. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +101 -0
  276. package/templates/apps/web/app/[locale]/(auth)/use-auth-card-flow.ts +102 -0
  277. package/templates/apps/web/app/[locale]/(auth)/verify-email/page.tsx +87 -0
  278. package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +20 -10
  279. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +84 -0
  280. package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +58 -0
  281. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +67 -14
  282. package/templates/apps/web/app/[locale]/(authed)/layout.tsx +19 -2
  283. package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +181 -0
  284. package/templates/apps/web/app/[locale]/(authed)/leads/components/LeadsTable.tsx +137 -0
  285. package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +111 -0
  286. package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +1 -1
  287. package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +111 -0
  288. package/templates/apps/web/app/[locale]/[slug]/page.tsx +65 -0
  289. package/templates/apps/web/app/[locale]/cancellation/page.tsx +44 -0
  290. package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +1 -1
  291. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +1 -1
  292. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +6 -5
  293. package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +1 -1
  294. package/templates/apps/web/app/[locale]/layout.tsx +308 -65
  295. package/templates/apps/web/app/[locale]/purchase/__tests__/cancel.test.tsx +162 -0
  296. package/templates/apps/web/app/[locale]/purchase/__tests__/module-scope.test.ts +68 -0
  297. package/templates/apps/web/app/[locale]/purchase/__tests__/success.test.tsx +361 -0
  298. package/templates/apps/web/app/[locale]/purchase/cancel/page.tsx +115 -0
  299. package/templates/apps/web/app/[locale]/purchase/success/page.tsx +307 -0
  300. package/templates/apps/web/app/[locale]/returns/page.tsx +44 -0
  301. package/templates/apps/web/app/[locale]/shipping/page.tsx +44 -0
  302. package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +670 -0
  303. package/templates/apps/web/app/api/revalidate/route.ts +194 -0
  304. package/templates/apps/web/auth.ts +407 -8
  305. package/templates/apps/web/components/google-analytics.tsx +18 -1
  306. package/templates/apps/web/eslint.config.mjs +69 -0
  307. package/templates/apps/web/jest.config.cjs +15 -19
  308. package/templates/apps/web/lib/__tests__/auth-email.test.ts +214 -0
  309. package/templates/apps/web/lib/__tests__/auth-routes.test.ts +74 -0
  310. package/templates/apps/web/lib/__tests__/meeting-slugs.test.ts +72 -0
  311. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +50 -6
  312. package/templates/apps/web/lib/auth-email.ts +318 -0
  313. package/templates/apps/web/lib/auth-env.ts +85 -0
  314. package/templates/apps/web/lib/auth-routes.ts +55 -0
  315. package/templates/apps/web/lib/meeting-slugs.ts +53 -0
  316. package/templates/apps/web/lib/nav-config.ts +27 -7
  317. package/templates/apps/web/lib/server-api.ts +1 -1
  318. package/templates/apps/web/lib/site-chrome.ts +29 -0
  319. package/templates/apps/web/lib/telemetry-scrub.ts +50 -0
  320. package/templates/apps/web/messages/en.json +216 -2
  321. package/templates/apps/web/next.config.mjs +20 -0
  322. package/templates/apps/web/package.json +8 -3
  323. package/templates/apps/web/sentry.client.config.ts +131 -0
  324. package/templates/apps/web/sentry.edge.config.ts +72 -0
  325. package/templates/apps/web/sentry.server.config.ts +72 -0
  326. package/templates/apps/web/src/lib/commerce-claim.ts +33 -0
  327. package/templates/apps/web/src/lib/commerce-sections.ts +61 -0
  328. package/templates/apps/web/src/lib/routes.ts +13 -18
  329. package/templates/brand_assets/README.md +24 -0
  330. package/templates/content/en/AboutPage/about.mdx +160 -15
  331. package/templates/content/en/CancellationPolicyPage/cancellation.mdx +108 -0
  332. package/templates/content/en/ContactPage/contact.mdx +90 -13
  333. package/templates/content/en/FAQPage/faq.mdx +62 -22
  334. package/templates/content/en/HomePage/home.mdx +244 -20
  335. package/templates/content/en/LandingPage/blog.mdx +83 -0
  336. package/templates/content/en/LandingPage/features.mdx +103 -0
  337. package/templates/content/en/LandingPage/how-it-works.mdx +143 -0
  338. package/templates/content/en/ReturnsPolicyPage/returns.mdx +108 -0
  339. package/templates/content/en/ShippingPolicyPage/shipping.mdx +108 -0
  340. package/templates/database/CHANGELOG.md +149 -0
  341. package/templates/database/README.md +10 -3
  342. package/templates/database/__tests__/appointment.db.test.ts +106 -0
  343. package/templates/database/__tests__/artifact-content-store.db.test.ts +316 -0
  344. package/templates/database/__tests__/composite-fence.db.test.ts +206 -0
  345. package/templates/database/__tests__/fence-fan-out.db.test.ts +711 -0
  346. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +79 -0
  347. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +100 -0
  348. package/templates/database/__tests__/flow-workspace-key.db.test.ts +263 -0
  349. package/templates/database/__tests__/prefixed-ids.db.test.ts +85 -9
  350. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +111 -0
  351. package/templates/database/__tests__/seed.test.ts +1 -1
  352. package/templates/database/__tests__/tenancy.test.ts +141 -0
  353. package/templates/database/config/schema.prisma +79 -2
  354. package/templates/database/content/schema.prisma +87 -11
  355. package/templates/database/eslint.config.mjs +69 -0
  356. package/templates/database/inbox/schema.prisma +452 -9
  357. package/templates/database/jest.config.cjs +5 -3
  358. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +15 -0
  359. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +158 -0
  360. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +40 -0
  361. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +67 -0
  362. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +70 -0
  363. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +181 -0
  364. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +172 -0
  365. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +41 -0
  366. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +185 -0
  367. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +70 -0
  368. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +57 -0
  369. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +68 -0
  370. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +1067 -0
  371. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +210 -0
  372. package/templates/database/package.json +7 -3
  373. package/templates/database/seed.ts +1 -1
  374. package/templates/database/tenancy.ts +86 -1
  375. package/templates/database/tsconfig.json +1 -0
  376. package/templates/package.json +1 -14
  377. package/versions.json +52 -0
  378. package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +0 -103
  379. package/templates/apps/api/src/routes/content/__tests__/create.test.ts +0 -253
  380. package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +0 -215
  381. package/templates/apps/api/src/routes/content/__tests__/update.test.ts +0 -266
  382. package/templates/apps/api/src/routes/content/create.ts +0 -115
  383. package/templates/apps/api/src/routes/content/delete.ts +0 -82
  384. package/templates/apps/api/src/routes/content/update.ts +0 -112
  385. package/templates/apps/mcp/__tests__/create_page.test.ts +0 -202
  386. package/templates/apps/mcp/__tests__/delete_page.test.ts +0 -177
  387. package/templates/apps/mcp/__tests__/update_page.test.ts +0 -196
  388. package/templates/apps/mcp/src/tools/create_page.ts +0 -96
  389. package/templates/apps/mcp/src/tools/delete_page.ts +0 -74
  390. package/templates/apps/mcp/src/tools/update_page.ts +0 -92
  391. package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +0 -123
  392. /package/site-templates/{marketing-site-free → _base}/content/en/PrivacyPage/privacy.mdx +0 -0
  393. /package/site-templates/{marketing-site-free → _base}/content/en/TermsPage/terms.mdx +0 -0
  394. /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/next-path.test.ts +0 -0
  395. /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/next-path.ts +0 -0
  396. /package/templates/apps/web/{src/components → components}/SiteNav.tsx +0 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The deployment's `commerce` add-on claim, resolved PER REQUEST (#6084 D12).
3
+ *
4
+ * Extracted from `app/.well-known/mcp.json/route.ts`'s own inline
5
+ * `resolveCommerceClaim()` (#5971) — that route's behaviour is unchanged;
6
+ * only its import line moves. `/purchase/success` and `/purchase/cancel`
7
+ * need the identical check (D12's shape-2 gate: the pages ship BASE TREE
8
+ * and gate at REQUEST time on this claim, exactly as the checkout
9
+ * primitives do — `apps/api/src/lib/require-commerce-claim.ts`), so this is
10
+ * extracted ONCE and imported three times rather than copied a third time.
11
+ *
12
+ * Fail-closed (NFR-3 mirror): anything short of a positively-held,
13
+ * unrevoked claim reads as absent, and a licence read that throws never
14
+ * takes the caller down with it. Called PER REQUEST rather than memoised —
15
+ * unlike `apps/mcp/src/lib/commerce-claim.ts`'s boot-time memoisation — so a
16
+ * site that buys commerce after its last deploy starts serving immediately
17
+ * rather than waiting on a redeploy.
18
+ */
19
+ import { checkLicense } from "@working-theory/license";
20
+
21
+ /** The licence `features[]` claim that turns the commerce add-on on. */
22
+ const COMMERCE_FEATURE = "commerce";
23
+
24
+ export async function resolveCommerceClaim(): Promise<boolean> {
25
+ try {
26
+ const result = await checkLicense();
27
+ return (
28
+ result.revoked !== true && result.features.includes(COMMERCE_FEATURE)
29
+ );
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Lazily registers the paid `@working-theory/ui-commerce` slice's sections
3
+ * (`payment-receipt`) — never a static top-level import (#6084, code-review
4
+ * finding on this issue's PR).
5
+ *
6
+ * `/purchase/success` and `/purchase/cancel` ship in the BASE TREE
7
+ * (`surfaces.ts` `CORE_ROUTE_DIRS`, D12) so a site that buys the `commerce`
8
+ * add-on after its last deploy gets working return pages without a
9
+ * redeploy. But a KEYLESS scaffold carries NO `ui-commerce` dependency by
10
+ * design — `packages/create-ailk/scripts/build-templates.mjs`'s
11
+ * `transformPaidUiPackages()` strips it from a keyless `apps/web/package.json`,
12
+ * and `__tests__/paid-module-honest-states.test.ts`'s "#5581 U6" suite
13
+ * asserts a keyless scaffold declares NONE of the four paid `ui-*` packages
14
+ * as a dependency. A plain top-level, STATIC named-import of that package's
15
+ * `registerCommerceSections` export would leave every keyless customer's
16
+ * build failing with `ERR_MODULE_NOT_FOUND` — webpack resolves a static
17
+ * import at BUILD time regardless of whether the code path importing it
18
+ * ever executes at runtime, so gating the CALL at request time (as
19
+ * `resolveCommerceClaim()` already does) is not enough on its own.
20
+ *
21
+ * The `webpackIgnore` magic comment tells webpack to leave this `import()`
22
+ * unresolved at build time; Node's own ESM loader then attempts it at
23
+ * RUNTIME, where a keyless deployment's absent package throws a genuine
24
+ * (caught) resolution error instead of a build failure. This repo's `dev`
25
+ * and `build` scripts both force `--webpack` (never Turbopack, which does
26
+ * not honor this comment), so the magic comment is reliably honored here.
27
+ *
28
+ * On success, the real `payment-receipt` renderer is registered and the
29
+ * caller may build a `payment-receipt` section as usual. On failure (the
30
+ * package genuinely is not installed), the caller MUST NOT construct a bare
31
+ * `payment-receipt` section anyway — `SectionRenderer`'s dispatch table
32
+ * falls back to `ModuleAbsent`, which renders `null` in production
33
+ * (`packages/ui/src/sections/ModuleAbsent.tsx`) — silently dropping the
34
+ * title/message/status that is this page's entire point. The caller must
35
+ * build an OSS `content-block` fallback carrying the same copy instead.
36
+ *
37
+ * Registered (or found absent) once per process — memoised, so a concurrent
38
+ * request never double-registers or double-attempts a failed resolution.
39
+ * This is a build-presence fact, not the license claim itself (which
40
+ * `resolveCommerceClaim()` deliberately re-checks every request); a
41
+ * process only changes which packages are on disk via a fresh deploy, which
42
+ * is a fresh process.
43
+ */
44
+ let registration: Promise<boolean> | undefined;
45
+
46
+ export function ensureCommerceSectionsRegistered(): Promise<boolean> {
47
+ if (!registration) {
48
+ registration = (async () => {
49
+ try {
50
+ const mod = await import(
51
+ /* webpackIgnore: true */ "@working-theory/ui-commerce"
52
+ );
53
+ mod.registerCommerceSections();
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ })();
59
+ }
60
+ return registration;
61
+ }
@@ -5,6 +5,8 @@
5
5
  * handlers to avoid copy-paste duplication.
6
6
  */
7
7
 
8
+ import { routeFor } from "@working-theory/templates/routes";
9
+
8
10
  import { SITE_BASE_URL } from "../../lib/site-brand";
9
11
 
10
12
  /**
@@ -29,22 +31,15 @@ export function resolveBaseUrl(): string {
29
31
  /**
30
32
  * Maps a content-adapter page type + slug to a site-relative path.
31
33
  * Drives both /llms.txt and /sitemap.xml URL generation.
34
+ *
35
+ * A lookup over the routes map (#5572 U2, spec § D4 row 1) — `routeFor` is
36
+ * byte-identical to the switch this replaced for its six `case` literals and
37
+ * the `` `/${slug}` `` default (proven by
38
+ * `packages/templates/src/__tests__/routes-map.test.ts`'s table test and
39
+ * `apps/web/__tests__/routes/routes-map-identity.test.ts`'s differential
40
+ * test over the live content tree). The signature is annotated explicitly so
41
+ * this stays the exact `(type: string, slug: string) => string` contract the
42
+ * three call sites (`sitemap.xml`, `llms.txt`, `docs-blog/llms-route.ts`)
43
+ * depend on, even though `routeFor`'s own `slug` parameter is optional.
32
44
  */
33
- export function slugToPath(type: string, slug: string): string {
34
- switch (type) {
35
- case "HomePage":
36
- return "/";
37
- case "BlogPosting":
38
- return `/blog/${slug}`;
39
- case "Product":
40
- return `/products/${slug}`;
41
- case "Service":
42
- return `/services/${slug}`;
43
- case "AboutPage":
44
- return "/about";
45
- case "ContactPage":
46
- return "/contact";
47
- default:
48
- return `/${slug}`;
49
- }
50
- }
45
+ export const slugToPath: (type: string, slug: string) => string = routeFor;
@@ -0,0 +1,24 @@
1
+ # brand_assets/
2
+
3
+ This folder is where you put your project's real brand material. It ships
4
+ empty — nothing here is required to run `pnpm dev` — but populating it is
5
+ what lets Claude Code (and anyone else building this site) use your actual
6
+ brand instead of inventing placeholder colors and copy.
7
+
8
+ `apps/web/CLAUDE.md` reads from this folder before designing a page. If a
9
+ file below is present, it's used; if it's absent, generic defaults are used
10
+ instead.
11
+
12
+ ## What goes here
13
+
14
+ | File / folder | Contents |
15
+ | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
16
+ | `logo.svg` (or `.png`) | Your logo, ideally an SVG. Add light/dark variants if your mark needs them (e.g. `logo-dark.svg`). |
17
+ | `brand-guide.md` | The global theme — brand colors, type direction, tone of voice, do's and don'ts — used when choosing layout and components for a page. |
18
+ | `brand-brief.md` | Positioning, messaging, and the target citation phrases a page's content should work toward. |
19
+ | `favicon.ico` / `favicon-*.png` | Favicon assets for `apps/web/app/favicon.ico` and any additional sizes your deploy target wants. |
20
+ | `photos/` | Real photography — team, product, office — to use instead of stock or placeholder images. |
21
+ | `reference/` | Mockups, screenshots, or other visual references to match when building or reviewing a page's design. |
22
+
23
+ None of these are mandatory. Add what you have; the rest can stay
24
+ placeholder until you're ready.
@@ -1,29 +1,174 @@
1
1
  ---
2
2
  type: "AboutPage"
3
3
  slug: "about"
4
- title: "About {{COMPANY_NAME}}"
5
- description: "Replace this with a sentence about who you are and why you do this work."
4
+ title: "We want you to {ability they couldn't do before}"
5
+ description: "We want you to {ability they couldn't do before}"
6
6
  sections:
7
7
  [
8
8
  {
9
- "id": "hero",
10
- "type": "hero",
11
- "data":
12
- {
13
- "headline": "About {{COMPANY_NAME}}",
14
- "subheadline": "Replace this with the short version of your story.",
9
+ "id": "manifesto",
10
+ "type": "content-block",
11
+ "data": {
12
+ "variant": "media-right",
13
+ "eyebrow": "Manifesto",
14
+ "headline": "We want you to {ability they couldn't do before}",
15
+ "body": "Hey, I’m {your name}, the founder of {your company}.\n\nWrite a few sentences introducing the problems you solve. You can even ask a rhetorical question to get people thinking about their own personal experiences with a problem they might have encountered.\n\nThis is your chance to tell the backstory of why your product exists and explain the gap your product fills. Don’t be afraid to take a stance and plant your flag.\n\nWe believe that {you should be able to X without Y}.\n\nWe’ll help you:\n\nSolve this problem\n\nSolve another problem\n\nSolve this other problem\n\nIf that resonates with you, you're in the right place.\n\n- (your name)",
16
+ "cta": {
17
+ "label": "Sign Up",
18
+ "href": "/sign-in"
15
19
  },
20
+ "secondaryCta": {
21
+ "label": "More about us",
22
+ "href": "/about",
23
+ "variant": "outline"
24
+ }
25
+ }
16
26
  },
17
27
  {
18
- "id": "why-we-exist",
19
- "type": "content-block",
20
- "data":
21
- {
22
- "headline": "Why we exist",
23
- "body": "Replace this paragraph with the reason your organization exists — the problem you kept running into, or the gap you decided to fill. Concrete beats aspirational.",
28
+ "id": "team",
29
+ "type": "team",
30
+ "data": {
31
+ "headline": "Our team",
32
+ "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
33
+ "members": [
34
+ {
35
+ "name": "Anya Lind",
36
+ "role": "Head of Growth",
37
+ "bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
38
+ },
39
+ {
40
+ "name": "Narciso Gerlach",
41
+ "role": "Head of Sales",
42
+ "bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
43
+ },
44
+ {
45
+ "name": "Edythe Sanford",
46
+ "role": "Head of Content",
47
+ "bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
48
+ },
49
+ {
50
+ "name": "Angeline Watsica",
51
+ "role": "Head of Conversion",
52
+ "bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
53
+ },
54
+ {
55
+ "name": "Gerardo Ullrich",
56
+ "role": "Head of Marketing",
57
+ "bio": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique."
58
+ }
59
+ ]
60
+ }
61
+ },
62
+ {
63
+ "id": "logo-cloud",
64
+ "type": "logoCloud",
65
+ "data": {
66
+ "headline": "Don’t just take our word for it",
67
+ "logos": [
68
+ {
69
+ "name": "Placeholder logo",
70
+ "src": "/logomark.svg"
71
+ },
72
+ {
73
+ "name": "Placeholder logo",
74
+ "src": "/logomark.svg"
75
+ },
76
+ {
77
+ "name": "Placeholder logo",
78
+ "src": "/logomark.svg"
79
+ },
80
+ {
81
+ "name": "Placeholder logo",
82
+ "src": "/logomark.svg"
83
+ },
84
+ {
85
+ "name": "Placeholder logo",
86
+ "src": "/logomark.svg"
87
+ },
88
+ {
89
+ "name": "Placeholder logo",
90
+ "src": "/logomark.svg"
91
+ }
92
+ ],
93
+ "layout": "inline",
94
+ "treatment": "monochrome"
95
+ }
96
+ },
97
+ {
98
+ "id": "testimonial",
99
+ "type": "testimonials",
100
+ "data": {
101
+ "variant": "featured",
102
+ "items": [
103
+ {
104
+ "quote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat.",
105
+ "author": "John Smith",
106
+ "role": "CEO, Google"
107
+ }
108
+ ]
109
+ }
110
+ },
111
+ {
112
+ "id": "switch",
113
+ "type": "cta",
114
+ "data": {
115
+ "variant": "box",
116
+ "headline": "Switch to {your product} in {time amount} or less",
117
+ "description": "You shouldn't have to {experience a painful problem}. With {your product}, you can finally {achieve a value outcome or get a big improvement}.",
118
+ "chips": [
119
+ "No credit card required",
120
+ "Cancel any time",
121
+ "Live chat support"
122
+ ],
123
+ "primaryCta": {
124
+ "label": "{Primary CTA}",
125
+ "href": "/contact"
126
+ },
127
+ "secondaryCta": {
128
+ "label": "{Secondary CTA}",
129
+ "href": "/pricing",
130
+ "variant": "outline"
24
131
  },
132
+ "closingLine": "{Social Proof goes here}"
133
+ }
25
134
  },
135
+ {
136
+ "id": "faq",
137
+ "type": "faq",
138
+ "data": {
139
+ "headline": "FAQs",
140
+ "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
141
+ "supportLink": {
142
+ "label": "Contact",
143
+ "href": "/contact"
144
+ },
145
+ "presentation": "accordion",
146
+ "initialOpen": "first",
147
+ "items": [
148
+ {
149
+ "question": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa?",
150
+ "answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
151
+ },
152
+ {
153
+ "question": "Dolorem consectetur quia maxime sunt ut sint. Fuga optio dolorem animi voluptatem laudantium error. Quis accusamus deleniti rer?",
154
+ "answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
155
+ },
156
+ {
157
+ "question": "Totam nihil esse. Itaque optio temporibus adipisci. Rerum nisi aperiam aliquid doloremque aliquam?",
158
+ "answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
159
+ },
160
+ {
161
+ "question": "Delectus minus officiis et. Perspiciatis illum nisi vitae. Sed consequuntur animi corrupti distinctio ipsam accusamus?",
162
+ "answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
163
+ },
164
+ {
165
+ "question": "Aperiam perferendis voluptatem est sit enim sed eaque perspiciatis enim. Est explicabo ea explicabo et et dignissimos aliquid?",
166
+ "answer": "Vel odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa odio odit voluptatum ut veritatis. Ex rerum aspernatur voluptas unde officia. Dolorem officiis laboriosa."
167
+ }
168
+ ]
169
+ }
170
+ }
26
171
  ]
27
172
  ---
28
173
 
29
- {/* Rendered from frontmatter `sections[]`. A `team` section is a good next addition here once you have people to list. */}
174
+ {/* Rendered from frontmatter `sections[]`. Placeholder copy, verbatim from the reference — replace the manifesto and the team before you launch. */}
@@ -0,0 +1,108 @@
1
+ ---
2
+ type: "CancellationPolicyPage"
3
+ slug: "cancellation"
4
+ title: "Cancellation Policy"
5
+ description: "How to cancel or reschedule a booking on this site, the notice required, and what a late cancellation or no-show costs."
6
+ updatedAt: "2026-09-17"
7
+ sections:
8
+ [
9
+ {
10
+ "id": "cancellation-document",
11
+ "type": "document-chassis",
12
+ "data":
13
+ {
14
+ "headline": "Cancellation Policy",
15
+ "backHref": "/",
16
+ "backLabel": "Back home",
17
+ "navGroupLabel": "Contents",
18
+ "stats":
19
+ [
20
+ { "label": "Last updated", "sublabel": "17 September 2026" },
21
+ { "label": "Applies to", "sublabel": "Bookings made on this site" },
22
+ ],
23
+ "sections":
24
+ [
25
+ {
26
+ "id": "intro",
27
+ "heading": "Cancellation Policy",
28
+ "blocks":
29
+ [
30
+ {
31
+ "kind": "paragraph",
32
+ "text": "This page explains how cancellations and reschedules work for bookings made on this site. Replace the starter copy below with the policy you actually operate — the headings are the ones a customer and an agent both look for, so keep them and fill in your own terms.",
33
+ },
34
+ ],
35
+ },
36
+ {
37
+ "id": "notice",
38
+ "heading": "How much notice is required",
39
+ "blocks":
40
+ [
41
+ {
42
+ "kind": "paragraph",
43
+ "text": "State the notice period in hours before the appointment, and say how it is measured. A customer reading at midnight should be able to work out, without arithmetic you have not shown them, whether they are still inside it.",
44
+ },
45
+ ],
46
+ },
47
+ {
48
+ "id": "how-to-cancel",
49
+ "heading": "How to cancel or reschedule",
50
+ "blocks":
51
+ [
52
+ {
53
+ "kind": "paragraph",
54
+ "text": "Give one route to cancel and one to reschedule, and say whether a reschedule inside the notice period counts as a cancellation. If a booking confirmation carries a self-service link, name it here.",
55
+ },
56
+ ],
57
+ },
58
+ {
59
+ "id": "fees",
60
+ "heading": "Late cancellations and no-shows",
61
+ "blocks":
62
+ [
63
+ {
64
+ "kind": "paragraph",
65
+ "text": "Say what a late cancellation costs and what a no-show costs, as a figure or a share of the booking, and when each is charged. If you hold a deposit, say what happens to it in each case.",
66
+ },
67
+ ],
68
+ },
69
+ {
70
+ "id": "our-cancellations",
71
+ "heading": "If we cancel",
72
+ "blocks":
73
+ [
74
+ {
75
+ "kind": "paragraph",
76
+ "text": "Set out what a customer gets if you cancel or move an appointment — a full refund, a rebooking, or both — and how quickly you tell them. A policy that only binds one side reads as one.",
77
+ },
78
+ ],
79
+ },
80
+ {
81
+ "id": "exceptions",
82
+ "heading": "Exceptions",
83
+ "blocks":
84
+ [
85
+ {
86
+ "kind": "paragraph",
87
+ "text": "Name the circumstances in which you waive a fee — illness, bereavement, severe weather — and say what you need from the customer to apply the waiver. Vague discretion is worse for you than a short written list.",
88
+ },
89
+ ],
90
+ },
91
+ {
92
+ "id": "contact",
93
+ "heading": "Questions about a booking",
94
+ "blocks":
95
+ [
96
+ {
97
+ "kind": "paragraph",
98
+ "text": "Point to the one place a customer should write, and say roughly how quickly you answer.",
99
+ },
100
+ ],
101
+ },
102
+ ],
103
+ },
104
+ },
105
+ ]
106
+ ---
107
+
108
+ {/* Rendered from frontmatter `sections[]`; the MDX body is not read by the section-catalog renderer. schema.org has no cancellation-policy type, so this page emits a plain WebPage (#5947, D2) — a real policy field reaches the JSON-LD through the `schema:` escape hatch, never a coined @type. */}
@@ -2,27 +2,104 @@
2
2
  type: "ContactPage"
3
3
  slug: "contact"
4
4
  title: "Contact {{COMPANY_NAME}}"
5
- description: "How to reach {{COMPANY_NAME}}. Replace this with the channels you actually monitor."
5
+ description: "Find out if {your product} is a good fit for you in just {time amount}."
6
6
  sections:
7
7
  [
8
8
  {
9
9
  "id": "hero",
10
10
  "type": "hero",
11
- "data":
12
- {
13
- "headline": "Contact {{COMPANY_NAME}}",
14
- "subheadline": "Replace this with how you prefer to be reached, and how quickly you reply.",
15
- },
11
+ "data": {
12
+ "variant": "split",
13
+ "eyebrow": "Book a Demo",
14
+ "headline": "Ready to {achieve a valuable outcome}?",
15
+ "subheadline": "Find out if {your product} is a good fit for you in just {time amount}.",
16
+ "checklist": [
17
+ "Use these bullet points to describe what to expect on the call",
18
+ "Alleviate any fears or hesitations visitors might have before scheduling",
19
+ "Frame the meeting around what they get out of it instead of what you get out of it"
20
+ ]
21
+ }
16
22
  },
17
23
  {
18
- "id": "channels",
19
- "type": "content-block",
20
- "data":
21
- {
22
- "body": "Replace this with your contact channels — email, a booking link, a form. List only the ones you actually monitor: a published channel nobody watches is worse than no channel.",
23
- },
24
+ "id": "contact-form",
25
+ "type": "contact-form",
26
+ "data": {
27
+ "variant": "card",
28
+ "fields": [
29
+ {
30
+ "name": "name",
31
+ "label": "Name",
32
+ "type": "text",
33
+ "required": true
34
+ },
35
+ {
36
+ "name": "email",
37
+ "label": "Email",
38
+ "type": "email",
39
+ "required": true
40
+ },
41
+ {
42
+ "name": "message",
43
+ "label": "Message",
44
+ "type": "textarea",
45
+ "required": true
46
+ }
47
+ ],
48
+ "consentText": "I accept the Terms",
49
+ "successMessage": "Thank you! Your submission has been received!",
50
+ "action": "/v1/leads/submit"
51
+ }
24
52
  },
53
+ {
54
+ "id": "logo-cloud",
55
+ "type": "logoCloud",
56
+ "data": {
57
+ "headline": "Don’t just take our word for it",
58
+ "logos": [
59
+ {
60
+ "name": "Placeholder logo",
61
+ "src": "/logomark.svg"
62
+ },
63
+ {
64
+ "name": "Placeholder logo",
65
+ "src": "/logomark.svg"
66
+ },
67
+ {
68
+ "name": "Placeholder logo",
69
+ "src": "/logomark.svg"
70
+ },
71
+ {
72
+ "name": "Placeholder logo",
73
+ "src": "/logomark.svg"
74
+ },
75
+ {
76
+ "name": "Placeholder logo",
77
+ "src": "/logomark.svg"
78
+ },
79
+ {
80
+ "name": "Placeholder logo",
81
+ "src": "/logomark.svg"
82
+ }
83
+ ],
84
+ "layout": "inline",
85
+ "treatment": "monochrome"
86
+ }
87
+ },
88
+ {
89
+ "id": "testimonial",
90
+ "type": "testimonials",
91
+ "data": {
92
+ "variant": "featured",
93
+ "items": [
94
+ {
95
+ "quote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat.",
96
+ "author": "John Smith",
97
+ "role": "CEO, Google"
98
+ }
99
+ ]
100
+ }
101
+ }
25
102
  ]
26
103
  ---
27
104
 
28
- {/* Rendered from frontmatter `sections[]`. Swap the content-block above for a `contact-channels` section once you know your channels. */}
105
+ {/* Rendered from frontmatter `sections[]`. The form posts to the site's own API (`/v1/leads/submit`) and confirms inline. Placeholder copy — replace before you launch. */}