create-ailk 0.5.0 → 0.6.1

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 (329) hide show
  1. package/README.md +55 -8
  2. package/component-catalog.json +336 -27
  3. package/component-catalog.md +25 -12
  4. package/dist/cli.js +54 -5
  5. package/dist/copy.d.ts +14 -0
  6. package/dist/copy.js +38 -1
  7. package/dist/lib/api-boot-assertion.d.ts +46 -0
  8. package/dist/lib/api-boot-assertion.js +70 -0
  9. package/dist/lib/extract-module-bundle.d.ts +20 -1
  10. package/dist/lib/extract-module-bundle.js +64 -5
  11. package/dist/lib/import-graph.d.ts +29 -0
  12. package/dist/lib/import-graph.js +140 -0
  13. package/dist/lib/module-license-gate.d.ts +6 -1
  14. package/dist/lib/module-license-gate.js +6 -1
  15. package/dist/lib/pro-callout.js +1 -1
  16. package/dist/module-architecture.d.ts +1 -0
  17. package/dist/module-architecture.js +253 -127
  18. package/dist/modules/commerce/0.6.0.tar.gz +0 -0
  19. package/dist/modules/docs-blog/0.6.0.tar.gz +0 -0
  20. package/dist/modules/multi-tenant/0.6.0.tar.gz +0 -0
  21. package/dist/modules/scheduling/0.6.0.tar.gz +0 -0
  22. package/dist/modules/signal-collectors/0.6.0.tar.gz +0 -0
  23. package/dist/modules/workspace/0.6.0.tar.gz +0 -0
  24. package/dist/programmatic.js +14 -10
  25. package/dist/surfaces.js +105 -7
  26. package/dist/template-manifest.d.ts +33 -0
  27. package/dist/template-manifest.js +99 -16
  28. package/dist/template-names.d.ts +1 -1
  29. package/dist/template-names.js +1 -0
  30. package/package.json +3 -2
  31. package/site-templates/marketing-site/DESIGN.md +148 -0
  32. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +22 -2
  33. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +9 -2
  34. package/site-templates/marketing-site/ailk-template.json +1 -1
  35. package/site-templates/marketing-site-free/DESIGN.md +148 -0
  36. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +2 -2
  37. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +1 -0
  38. package/site-templates/minimalism-site/DESIGN.md +148 -0
  39. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +10 -2
  40. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +47 -35
  41. package/site-templates/minimalism-site/ailk-template.json +2 -1
  42. package/site-templates/minimalism-site/assets/wordmark-placeholder.svg +28 -0
  43. package/site-templates/minimalism-site/content/en/HomePage/home.mdx +49 -19
  44. package/site-templates/saas-product/DESIGN.md +148 -0
  45. package/site-templates/simple-service/DESIGN.md +148 -0
  46. package/site-templates/simple-service/TEMPLATE-MANIFEST.json +240 -0
  47. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +278 -0
  48. package/site-templates/simple-service/ailk-template.json +10 -0
  49. package/site-templates/simple-service/content/en/AboutPage/about.mdx +38 -0
  50. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +67 -0
  51. package/site-templates/simple-service/content/en/FAQPage/faq.mdx +56 -0
  52. package/site-templates/simple-service/content/en/HomePage/home.mdx +85 -0
  53. package/site-templates/simple-service/content/en/Service/landscape-design.mdx +40 -0
  54. package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +40 -0
  55. package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +40 -0
  56. package/site-templates/simple-service/content/en/ServicesList/services.mdx +72 -0
  57. package/site-templates/simple-service/provenance.json +4 -0
  58. package/templates/.env.example +72 -7
  59. package/templates/CLAUDE.md +2 -3
  60. package/templates/DESIGN.md +155 -0
  61. package/templates/README.md +42 -8
  62. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +8 -0
  63. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +12 -0
  64. package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +12 -0
  65. package/templates/apps/api/.env.example +13 -0
  66. package/templates/apps/api/CLAUDE.md +26 -2
  67. package/templates/apps/api/jest.config.cjs +3 -0
  68. package/templates/apps/api/package.json +1 -0
  69. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +407 -0
  70. package/templates/apps/api/src/__tests__/module-exclusion.test.ts +83 -7
  71. package/templates/apps/api/src/__tests__/server.test.ts +471 -0
  72. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +45 -0
  73. package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +2 -0
  74. package/templates/apps/api/src/config/index.ts +62 -0
  75. package/templates/apps/api/src/config/modules.ts +7 -3
  76. package/templates/apps/api/src/lib/__mocks__/prisma.ts +238 -2
  77. package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +143 -0
  78. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +23 -0
  79. package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +125 -0
  80. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +20 -0
  81. package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +317 -0
  82. package/templates/apps/api/src/lib/__tests__/site.test.ts +238 -0
  83. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +75 -0
  84. package/templates/apps/api/src/lib/auth-email-budget.ts +160 -0
  85. package/templates/apps/api/src/lib/content-adapter.ts +57 -31
  86. package/templates/apps/api/src/lib/deliverable-asset-store.ts +76 -0
  87. package/templates/apps/api/src/lib/error-serializer.ts +23 -3
  88. package/templates/apps/api/src/lib/outbound-http.ts +7 -2
  89. package/templates/apps/api/src/lib/require-commerce-claim.ts +250 -0
  90. package/templates/apps/api/src/lib/site.ts +208 -9
  91. package/templates/apps/api/src/lib/stripe.ts +66 -0
  92. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +182 -0
  93. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +42 -0
  94. package/templates/apps/api/src/middleware/rate-limit.ts +7 -1
  95. package/templates/apps/api/src/openapi/spec.ts +543 -2
  96. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +48 -0
  97. package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +309 -0
  98. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +123 -0
  99. package/templates/apps/api/src/routes/auth/transactional-email.ts +273 -0
  100. package/templates/apps/api/src/routes/auth/user.ts +61 -0
  101. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +434 -0
  102. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +888 -0
  103. package/templates/apps/api/src/routes/checkout/index.ts +34 -0
  104. package/templates/apps/api/src/routes/checkout/session.ts +139 -0
  105. package/templates/apps/api/src/routes/checkout/sessions.ts +197 -0
  106. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +554 -0
  107. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +108 -0
  108. package/templates/apps/api/src/routes/content/__tests__/search.test.ts +450 -0
  109. package/templates/apps/api/src/routes/content/get-page.ts +94 -12
  110. package/templates/apps/api/src/routes/content/index.ts +13 -73
  111. package/templates/apps/api/src/routes/content/list-pages.ts +15 -3
  112. package/templates/apps/api/src/routes/content/rate-limit.ts +15 -6
  113. package/templates/apps/api/src/routes/content/search.ts +129 -0
  114. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +447 -31
  115. package/templates/apps/api/src/routes/leads/index.ts +100 -13
  116. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +51 -0
  117. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +351 -0
  118. package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +51 -0
  119. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +5 -2
  120. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +4 -1
  121. package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +58 -0
  122. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +107 -6
  123. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +87 -2
  124. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +51 -0
  125. package/templates/apps/api/src/routes/project-listings/start.ts +5 -1
  126. package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +686 -0
  127. package/templates/apps/api/src/routes/requests/confirm.ts +601 -0
  128. package/templates/apps/api/src/routes/requests/index.ts +54 -0
  129. package/templates/apps/api/src/routes/webhooks/README.md +265 -0
  130. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +749 -0
  131. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +330 -0
  132. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +262 -0
  133. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +285 -0
  134. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +213 -0
  135. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +301 -0
  136. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +648 -0
  137. package/templates/apps/api/src/routes/webhooks/index.ts +89 -0
  138. package/templates/apps/api/src/routes/webhooks/stripe.ts +1399 -0
  139. package/templates/apps/api/src/server.ts +439 -49
  140. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +39 -0
  141. package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +217 -40
  142. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +620 -0
  143. package/templates/apps/api/src/services/__tests__/consent.test.ts +2 -0
  144. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +300 -5
  145. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +20 -0
  146. package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +368 -0
  147. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +160 -0
  148. package/templates/apps/api/src/services/__tests__/listing-config.test.ts +166 -0
  149. package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +154 -0
  150. package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +137 -0
  151. package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +444 -0
  152. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +238 -0
  153. package/templates/apps/api/src/services/__tests__/verified-email.test.ts +78 -0
  154. package/templates/apps/api/src/services/abandon-email.ts +8 -2
  155. package/templates/apps/api/src/services/aeo-score.ts +49 -12
  156. package/templates/apps/api/src/services/audit-log.ts +668 -0
  157. package/templates/apps/api/src/services/consent.ts +18 -0
  158. package/templates/apps/api/src/services/default-tenant.ts +70 -31
  159. package/templates/apps/api/src/services/deliverable-fulfillment.ts +141 -13
  160. package/templates/apps/api/src/services/dunning-policy.ts +294 -0
  161. package/templates/apps/api/src/services/entitlements.ts +80 -0
  162. package/templates/apps/api/src/services/lead-promotion.ts +13 -14
  163. package/templates/apps/api/src/services/lead-routing.ts +161 -2
  164. package/templates/apps/api/src/services/leads-inbox.ts +23 -2
  165. package/templates/apps/api/src/services/listing-config.ts +27 -9
  166. package/templates/apps/api/src/services/project-listings.ts +201 -6
  167. package/templates/apps/api/src/services/public-site-resolver.ts +106 -0
  168. package/templates/apps/api/src/services/request-confirm.ts +646 -0
  169. package/templates/apps/api/src/services/revalidation.ts +173 -0
  170. package/templates/apps/api/src/services/verified-email.ts +71 -0
  171. package/templates/apps/api/src/vercel-handler.ts +75 -35
  172. package/templates/apps/mcp/.env.example +17 -0
  173. package/templates/apps/mcp/CLAUDE.md +57 -24
  174. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +6 -0
  175. package/templates/apps/mcp/__tests__/audit.test.ts +137 -8
  176. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +79 -36
  177. package/templates/apps/mcp/__tests__/get_offerings.test.ts +111 -2
  178. package/templates/apps/mcp/__tests__/get_pricing.test.ts +82 -2
  179. package/templates/apps/mcp/__tests__/http-transport.test.ts +541 -2
  180. package/templates/apps/mcp/__tests__/index.test.ts +39 -0
  181. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +143 -0
  182. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +111 -0
  183. package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +65 -0
  184. package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +188 -0
  185. package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +165 -0
  186. package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +124 -0
  187. package/templates/apps/mcp/__tests__/list_pages.test.ts +116 -0
  188. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +7 -1
  189. package/templates/apps/mcp/__tests__/parity.test.ts +10 -7
  190. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +89 -22
  191. package/templates/apps/mcp/__tests__/read_content.test.ts +322 -1
  192. package/templates/apps/mcp/__tests__/search_content.test.ts +105 -2
  193. package/templates/apps/mcp/__tests__/server.test.ts +67 -14
  194. package/templates/apps/mcp/__tests__/start_purchase.test.ts +252 -0
  195. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +300 -123
  196. package/templates/apps/mcp/jest.config.cjs +13 -0
  197. package/templates/apps/mcp/package.json +2 -0
  198. package/templates/apps/mcp/src/abuse/index.ts +159 -24
  199. package/templates/apps/mcp/src/config/modules.ts +10 -5
  200. package/templates/apps/mcp/src/http-transport.ts +102 -29
  201. package/templates/apps/mcp/src/index.ts +73 -11
  202. package/templates/apps/mcp/src/lib/audit-single-page.ts +90 -3
  203. package/templates/apps/mcp/src/lib/commerce-claim.ts +94 -0
  204. package/templates/apps/mcp/src/lib/content-adapter.ts +113 -0
  205. package/templates/apps/mcp/src/lib/empty-content-adapter.ts +139 -0
  206. package/templates/apps/mcp/src/lib/prisma.ts +39 -0
  207. package/templates/apps/mcp/src/lib/public-workspace.ts +133 -0
  208. package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +59 -0
  209. package/templates/apps/mcp/src/server.ts +59 -35
  210. package/templates/apps/mcp/src/tools/audit.ts +26 -2
  211. package/templates/apps/mcp/src/tools/get_business_hours.ts +4 -3
  212. package/templates/apps/mcp/src/tools/get_faq.ts +4 -3
  213. package/templates/apps/mcp/src/tools/get_locations.ts +5 -3
  214. package/templates/apps/mcp/src/tools/get_offerings.ts +16 -4
  215. package/templates/apps/mcp/src/tools/get_pricing.ts +25 -6
  216. package/templates/apps/mcp/src/tools/get_site_info.ts +4 -3
  217. package/templates/apps/mcp/src/tools/index.ts +6 -4
  218. package/templates/apps/mcp/src/tools/list_pages.ts +4 -3
  219. package/templates/apps/mcp/src/tools/purchase.ts +128 -45
  220. package/templates/apps/mcp/src/tools/read_content.ts +20 -6
  221. package/templates/apps/mcp/src/tools/search_content.ts +11 -4
  222. package/templates/apps/web/.env.example +71 -5
  223. package/templates/apps/web/CLAUDE.md +44 -0
  224. package/templates/apps/web/PRODUCT.md +86 -0
  225. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +18 -2
  226. package/templates/apps/web/app/.well-known/mcp.json/route.ts +11 -3
  227. package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +282 -0
  228. package/templates/apps/web/app/[locale]/(auth)/__tests__/password-reset.test.tsx +515 -0
  229. package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +89 -0
  230. package/templates/apps/web/app/[locale]/(auth)/forgot-password/page.tsx +109 -0
  231. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +92 -0
  232. package/templates/apps/web/app/[locale]/(auth)/reset-password/page.tsx +135 -0
  233. package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +109 -0
  234. package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/page.test.tsx +48 -2
  235. package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/page.tsx +20 -6
  236. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +125 -0
  237. package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +96 -0
  238. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +101 -0
  239. package/templates/apps/web/app/[locale]/(auth)/use-auth-card-flow.ts +102 -0
  240. package/templates/apps/web/app/[locale]/(auth)/verify-email/page.tsx +87 -0
  241. package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +20 -10
  242. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +84 -0
  243. package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +58 -0
  244. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +63 -8
  245. package/templates/apps/web/app/[locale]/(authed)/layout.tsx +18 -1
  246. package/templates/apps/web/app/[locale]/cancellation/page.tsx +44 -0
  247. package/templates/apps/web/app/[locale]/layout.tsx +133 -87
  248. package/templates/apps/web/app/[locale]/purchase/__tests__/cancel.test.tsx +162 -0
  249. package/templates/apps/web/app/[locale]/purchase/__tests__/module-scope.test.ts +68 -0
  250. package/templates/apps/web/app/[locale]/purchase/__tests__/success.test.tsx +361 -0
  251. package/templates/apps/web/app/[locale]/purchase/cancel/page.tsx +115 -0
  252. package/templates/apps/web/app/[locale]/purchase/success/page.tsx +307 -0
  253. package/templates/apps/web/app/[locale]/returns/page.tsx +44 -0
  254. package/templates/apps/web/app/[locale]/shipping/page.tsx +44 -0
  255. package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +670 -0
  256. package/templates/apps/web/app/api/revalidate/route.ts +194 -0
  257. package/templates/apps/web/auth.ts +407 -8
  258. package/templates/apps/web/jest.config.cjs +8 -4
  259. package/templates/apps/web/lib/__tests__/auth-email.test.ts +214 -0
  260. package/templates/apps/web/lib/__tests__/auth-routes.test.ts +74 -0
  261. package/templates/apps/web/lib/__tests__/meeting-slugs.test.ts +72 -0
  262. package/templates/apps/web/lib/__tests__/site-theme.test.ts +135 -20
  263. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +18 -1
  264. package/templates/apps/web/lib/auth-email.ts +318 -0
  265. package/templates/apps/web/lib/auth-env.ts +85 -0
  266. package/templates/apps/web/lib/auth-routes.ts +55 -0
  267. package/templates/apps/web/lib/meeting-slugs.ts +53 -0
  268. package/templates/apps/web/lib/site-brand.tsx +4 -8
  269. package/templates/apps/web/lib/telemetry-scrub.ts +5 -1
  270. package/templates/apps/web/messages/en.json +187 -0
  271. package/templates/apps/web/middleware.ts +1 -1
  272. package/templates/apps/web/package.json +2 -1
  273. package/templates/apps/web/src/lib/commerce-claim.ts +33 -0
  274. package/templates/apps/web/src/lib/commerce-sections.ts +93 -0
  275. package/templates/content/_site.mdx +18 -3
  276. package/templates/content/en/CancellationPolicyPage/cancellation.mdx +108 -0
  277. package/templates/content/en/ReturnsPolicyPage/returns.mdx +108 -0
  278. package/templates/content/en/ShippingPolicyPage/shipping.mdx +108 -0
  279. package/templates/database/CHANGELOG.md +149 -0
  280. package/templates/database/README.md +10 -3
  281. package/templates/database/__tests__/appointment.db.test.ts +106 -0
  282. package/templates/database/__tests__/artifact-content-store.db.test.ts +316 -0
  283. package/templates/database/__tests__/composite-fence.db.test.ts +206 -0
  284. package/templates/database/__tests__/fence-fan-out.db.test.ts +711 -0
  285. package/templates/database/__tests__/fixtures/appointment-create-probe.ts +79 -0
  286. package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +100 -0
  287. package/templates/database/__tests__/flow-workspace-key.db.test.ts +263 -0
  288. package/templates/database/__tests__/prefixed-ids.db.test.ts +85 -9
  289. package/templates/database/__tests__/project-listing-consent-at.db.test.ts +111 -0
  290. package/templates/database/__tests__/tenancy.test.ts +141 -0
  291. package/templates/database/config/schema.prisma +79 -2
  292. package/templates/database/content/schema.prisma +87 -11
  293. package/templates/database/inbox/schema.prisma +452 -9
  294. package/templates/database/jest.config.cjs +5 -3
  295. package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +15 -0
  296. package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +158 -0
  297. package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +40 -0
  298. package/templates/database/migrations/20260918120000_add_appointment/migration.sql +67 -0
  299. package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +70 -0
  300. package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +181 -0
  301. package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +172 -0
  302. package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +41 -0
  303. package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +185 -0
  304. package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +70 -0
  305. package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +57 -0
  306. package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +68 -0
  307. package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +1067 -0
  308. package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +210 -0
  309. package/templates/database/package.json +3 -2
  310. package/templates/database/tenancy.ts +86 -1
  311. package/templates/database/tsconfig.json +1 -0
  312. package/versions.json +34 -34
  313. package/templates/apps/api/src/routes/content/__tests__/create.test.ts +0 -253
  314. package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +0 -215
  315. package/templates/apps/api/src/routes/content/__tests__/update.test.ts +0 -266
  316. package/templates/apps/api/src/routes/content/create.ts +0 -115
  317. package/templates/apps/api/src/routes/content/delete.ts +0 -82
  318. package/templates/apps/api/src/routes/content/update.ts +0 -112
  319. package/templates/apps/mcp/__tests__/create_page.test.ts +0 -202
  320. package/templates/apps/mcp/__tests__/delete_page.test.ts +0 -177
  321. package/templates/apps/mcp/__tests__/update_page.test.ts +0 -196
  322. package/templates/apps/mcp/src/tools/create_page.ts +0 -96
  323. package/templates/apps/mcp/src/tools/delete_page.ts +0 -74
  324. package/templates/apps/mcp/src/tools/update_page.ts +0 -92
  325. package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +0 -123
  326. package/templates/apps/web/public/logo-dark.svg +0 -21
  327. package/templates/apps/web/public/logo-light.svg +0 -21
  328. /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/next-path.test.ts +0 -0
  329. /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/next-path.ts +0 -0
package/dist/surfaces.js CHANGED
@@ -66,12 +66,32 @@ export const CORE_ROUTE_DIRS = [
66
66
  // copies all of apps/web verbatim, no `--surfaces` gating on this route),
67
67
  // so joining CORE_ROUTE_DIRS only makes the REGISTRY match what already
68
68
  // ships — it does not change what a fresh scaffold carries.
69
- `${ROUTE_ROOT}/sign-in`,
69
+ //
70
+ // #5963 moved `sign-in` INTO the `(auth)` route group and added four
71
+ // siblings, so the group is what is listed now. It stays CORE rather than
72
+ // taking its own surface id the way `(authed)` did: `(authed)` is gated
73
+ // authed-app surface reported under its own identity, whereas these five
74
+ // are the public auth entry points that have always shipped ungated —
75
+ // registering the group keeps `sign-in`'s existing `core` identity exactly.
76
+ `${ROUTE_ROOT}/(auth)`,
70
77
  // #5469 D2 — always copied: it is what serves the Free template's
71
78
  // /how-it-works, /features and /blog pages, and it is inert for every slug
72
79
  // that has no LandingPage MDX (notFound), so a scaffold carrying it and no
73
80
  // content is byte-for-byte a scaffold with three more 404s, nothing else.
74
81
  `${ROUTE_ROOT}/[slug]`,
82
+ // #6084 D12 (the operator's shape-2 disposition) — the checkout return
83
+ // pair. The launchers pointing at them (`apps/mcp/src/tools/purchase.ts`,
84
+ // `apps/web/.../dev/purchase/purchase.actions.ts`) are ALREADY
85
+ // unconditional base-tree code under D-64, so gating the return pages
86
+ // behind a scaffold-time surface would leave a licence-added commerce
87
+ // site with a working checkout and a 404 return page — the exact defect
88
+ // this issue exists to close. `CORE_ROUTE_DIRS` is the right home for the
89
+ // same reason `[slug]` immediately above is: inert (a request-time
90
+ // `notFound()`, `src/lib/commerce-claim.ts`) for every scaffold that never
91
+ // buys the `commerce` claim, so carrying it costs nothing beyond two more
92
+ // 404s. Neither `GATEABLE_SURFACES` nor `MODULE_SURFACES.commerce` gains
93
+ // an entry — the claim decides whether the pages serve, not the scaffold.
94
+ `${ROUTE_ROOT}/purchase`,
75
95
  ];
76
96
  /**
77
97
  * Directory names skipped by `listTemplateRouteDirs`'s walker even though they
@@ -482,6 +502,11 @@ export const ROUTE_SINCE = {
482
502
  // question set is the SITE's content. A scaffolded site adds its own route
483
503
  // beside this file and passes its own config.
484
504
  "projects/apply": "0.18.0",
505
+ // #6084 — two genuinely new route directories, attaching at today's
506
+ // fixed-group version, the same "attach at today's version" rule #5977,
507
+ // #5678, #5479, #5371 and #5048 applied.
508
+ "purchase/success": "0.24.0",
509
+ "purchase/cancel": "0.24.0",
485
510
  resources: "0.0.0",
486
511
  "resources/[slug]": "0.0.0",
487
512
  services: "0.0.0",
@@ -524,10 +549,36 @@ export const ROUTE_SINCE = {
524
549
  "(authed)/admin": "0.22.1",
525
550
  "(authed)/admin/site": "0.22.1",
526
551
  "(authed)/admin/team": "0.22.1",
552
+ // #5977 — the Pro content host's editor routes (spec 5872 FR1/FR2), added
553
+ // to apps/web by #5957. Genuinely new route directories, so they attach at
554
+ // today's fixed-group version, the same "attach at today's version" rule
555
+ // #5678, #5479, #5371 and #5048 applied.
556
+ //
557
+ // They are registered here but do NOT ship in a scaffold: the pair is
558
+ // excluded from the template snapshot by `EXCLUDE_TEMPLATE_DIRS` in
559
+ // `scripts/build-templates.mjs` (see that entry for the two spec-5872-D11
560
+ // constraints behind the choice). The entries are kept because ROUTE_SINCE
561
+ // is the route registry for `apps/web`, not a mirror of what the snapshot
562
+ // happens to carry — sync-routes' AC-5 coverage test knows the exclusion
563
+ // and treats the absence as justified.
564
+ "(authed)/edit": "0.24.0",
565
+ "(authed)/edit/[type]/[slug]": "0.24.0",
527
566
  "(authed)/waitlist": "0.18.0",
528
567
  "(authed)/waitlist/[experimentId]": "0.18.0",
529
568
  "(authed)/waitlist/[experimentId]/signups/[leadId]": "0.18.0",
530
- "sign-in": "0.18.0",
569
+ // #5963 — the `(auth)` route group. `sign-in` keeps its ORIGINAL version
570
+ // under its new key: ROUTE_SINCE tracks when a route was introduced, not
571
+ // when it was moved, exactly as the #5637 workspace -> admin rename above
572
+ // left `(authed)/admin` at 0.22.1. The group's own layout and the four new
573
+ // pages are genuinely new route directories, so they attach at today's
574
+ // fixed-group version — the same rule #5977, #5678, #5479, #5371 and #5048
575
+ // applied.
576
+ "(auth)": "0.24.0",
577
+ "(auth)/sign-in": "0.18.0",
578
+ "(auth)/sign-up": "0.24.0",
579
+ "(auth)/forgot-password": "0.24.0",
580
+ "(auth)/reset-password": "0.24.0",
581
+ "(auth)/verify-email": "0.24.0",
531
582
  // #5469 D2 — the generic `[slug]` content route. A genuinely new route
532
583
  // directory, so it attaches at today's fixed-group version, the same rule
533
584
  // #5479, #5371 and #5048 applied.
@@ -566,7 +617,17 @@ export function surfaceForRouteDir(routeDir) {
566
617
  * that the waitlist dashboard also uses, rather than duplicating them.
567
618
  */
568
619
  export const ROUTE_DEPENDENCIES = {
569
- "sign-in": ["apps/web/lib/auth-env.ts", "apps/web/lib/site-brand.tsx"],
620
+ // #5963 — the (auth) group's layout renders the brand mark through
621
+ // `siteLogo()`, and the LOCALE layout above it branches on
622
+ // `isAuthPath()` to drop the marketing chrome for these five paths: without
623
+ // `auth-routes.ts` a synced group renders inside the Nav + Footer it exists
624
+ // to replace. The sign-in page no longer imports `site-brand` — the mark is
625
+ // the shell's since #5963 — so its own list is just the env reader.
626
+ "(auth)": ["apps/web/lib/site-brand.tsx", "apps/web/lib/auth-routes.ts"],
627
+ "(auth)/sign-in": ["apps/web/lib/auth-env.ts"],
628
+ "(auth)/sign-up": ["apps/web/lib/auth-env.ts"],
629
+ "(auth)/forgot-password": ["apps/web/lib/auth-env.ts"],
630
+ "(auth)/reset-password": ["apps/web/lib/auth-env.ts"],
570
631
  "(authed)": ["apps/web/auth.ts", "apps/web/lib/auth-env.ts"],
571
632
  "(authed)/account": [
572
633
  "apps/web/lib/account-config.ts",
@@ -574,11 +635,37 @@ export const ROUTE_DEPENDENCIES = {
574
635
  `${ROUTE_ROOT}/(authed)/waitlist/components/ForbiddenState.tsx`,
575
636
  `${ROUTE_ROOT}/(authed)/waitlist/format.ts`,
576
637
  ],
577
- "(authed)/admin": ["apps/web/lib/server-api.ts"],
638
+ "(authed)/admin": [
639
+ "apps/web/lib/server-api.ts",
640
+ `${ROUTE_ROOT}/(authed)/waitlist/components/ForbiddenState.tsx`,
641
+ ],
578
642
  "(authed)/leads": ["apps/web/lib/server-api.ts"],
579
- "(authed)/admin/site": ["apps/web/lib/server-api.ts"],
580
- "(authed)/admin/team": ["apps/web/lib/server-api.ts"],
643
+ // #5977 — the editor routes' own imports, read from their sources: both
644
+ // pages call `forwardedCookieInit`/`unwrapApiResult` from `lib/server-api`
645
+ // and render the shared `ForbiddenState` on the tenant guard's 403, the
646
+ // same pair `(authed)/admin` already declares. Declared for registry
647
+ // completeness; inert in practice while the routes are excluded from the
648
+ // snapshot (see ROUTE_SINCE above).
649
+ "(authed)/edit": [
650
+ "apps/web/lib/server-api.ts",
651
+ `${ROUTE_ROOT}/(authed)/waitlist/components/ForbiddenState.tsx`,
652
+ ],
653
+ "(authed)/edit/[type]/[slug]": [
654
+ "apps/web/lib/server-api.ts",
655
+ `${ROUTE_ROOT}/(authed)/waitlist/components/ForbiddenState.tsx`,
656
+ ],
657
+ "(authed)/admin/site": [
658
+ "apps/web/lib/server-api.ts",
659
+ `${ROUTE_ROOT}/(authed)/waitlist/components/ForbiddenState.tsx`,
660
+ ],
661
+ "(authed)/admin/team": [
662
+ "apps/web/lib/server-api.ts",
663
+ `${ROUTE_ROOT}/(authed)/waitlist/components/ForbiddenState.tsx`,
664
+ ],
581
665
  "(authed)/waitlist": ["apps/web/lib/server-api.ts"],
666
+ // #6183 S9b D5 — both /meet pages call the shared enabled-slug read.
667
+ meet: ["apps/web/lib/meeting-slugs.ts"],
668
+ "meet/[slug]": ["apps/web/lib/meeting-slugs.ts"],
582
669
  };
583
670
  /**
584
671
  * i18n message namespaces (dot-path into `apps/web/messages/<locale>.json`) a
@@ -590,10 +677,21 @@ export const ROUTE_DEPENDENCIES = {
590
677
  * to the site owner, same as any other reported gap.
591
678
  */
592
679
  export const ROUTE_MESSAGE_NAMESPACES = {
593
- "sign-in": ["signIn"],
680
+ // #5963 — `signIn` is untouched and still the sign-in page's namespace; the
681
+ // group's layout and the four new pages read the new `auth` namespace.
682
+ "(auth)": ["auth"],
683
+ "(auth)/sign-in": ["signIn"],
684
+ "(auth)/sign-up": ["auth"],
685
+ "(auth)/forgot-password": ["auth"],
686
+ "(auth)/reset-password": ["auth"],
687
+ "(auth)/verify-email": ["auth"],
594
688
  "(authed)/account": ["account"],
595
689
  "(authed)/admin": ["admin"],
596
690
  "(authed)/leads": ["leadsInbox"],
691
+ // #5977 — every string on both editor routes comes from the `edit`
692
+ // namespace (spec 5872 D10).
693
+ "(authed)/edit": ["edit"],
694
+ "(authed)/edit/[type]/[slug]": ["edit"],
597
695
  "(authed)/admin/site": ["admin"],
598
696
  "(authed)/admin/team": ["admin"],
599
697
  "(authed)/waitlist": ["waitlistDashboard.gate"],
@@ -1,3 +1,20 @@
1
+ /**
2
+ * Site-template registry, and the roster merge that composes a template with
3
+ * the modules it takes (spec 5478, unit A of the site-templates mechanism;
4
+ * design record docs/specs/5462-site-templates-module-bundles-spec.md).
5
+ *
6
+ * A site template is DATA AND CONTENT, NOT CODE: a page roster, seed content
7
+ * and config — never a `page.tsx` (parent § D16). This file declares what a
8
+ * template IS. It declares no delivery channel, reads no licence, and touches
9
+ * no disk: the `--template` flag, the bundle fetch and the landing order are
10
+ * #5481's, and `GET /v1/templates/:name/:version` is #5480's.
11
+ *
12
+ * A CODE registry, not per-template JSON (parent § D2): in TypeScript,
13
+ * `requires` is checked against `RECOGNIZED_MODULES` at compile time, and this
14
+ * package already twice records that a fixed template FILE is the drift a
15
+ * registry removes.
16
+ */
17
+ import type { CategorySlug } from "@working-theory/schema/categories";
1
18
  import { type PageRosterRow } from "./module-architecture.js";
2
19
  import type { ModuleName } from "./parse-args.js";
3
20
  import type { TemplateLayout } from "./site-chrome.js";
@@ -24,6 +41,22 @@ export interface TemplateManifest {
24
41
  * unrecognized name fails type-check rather than a runtime validation.
25
42
  */
26
43
  requires: readonly ModuleName[];
44
+ /**
45
+ * The business categories this template is FOR — one or more LEAF slugs from
46
+ * the site-category registry (`@working-theory/schema/categories`, #5830),
47
+ * shared with content's frontmatter `categories`. Required, and typed against
48
+ * `CategorySlug`, for the same reason `requires` is typed against
49
+ * `ModuleName`: an unrecognized name fails type-check rather than a runtime
50
+ * validation, and every template must be findable under at least one
51
+ * category on the hub's "Browse by business" band.
52
+ *
53
+ * LEAVES ONLY. A group slug (`professional-services`, `home-and-trades`, …)
54
+ * is never a valid value: the group is DERIVED through `groupOf`, so a
55
+ * template that fits "professional services" names `accounting` and `legal`.
56
+ * Where a leaf is genuinely missing, the operator adds a leaf to the
57
+ * registry — never a group here.
58
+ */
59
+ categories: readonly CategorySlug[];
27
60
  /**
28
61
  * The template this one EXTENDS — its lineage, never its level (#5618 D2).
29
62
  * A single parent, not a list: "later layers win file by file" needs a
@@ -1,19 +1,3 @@
1
- /**
2
- * Site-template registry, and the roster merge that composes a template with
3
- * the modules it takes (spec 5478, unit A of the site-templates mechanism;
4
- * design record docs/specs/5462-site-templates-module-bundles-spec.md).
5
- *
6
- * A site template is DATA AND CONTENT, NOT CODE: a page roster, seed content
7
- * and config — never a `page.tsx` (parent § D16). This file declares what a
8
- * template IS. It declares no delivery channel, reads no licence, and touches
9
- * no disk: the `--template` flag, the bundle fetch and the landing order are
10
- * #5481's, and `GET /v1/templates/:name/:version` is #5480's.
11
- *
12
- * A CODE registry, not per-template JSON (parent § D2): in TypeScript,
13
- * `requires` is checked against `RECOGNIZED_MODULES` at compile time, and this
14
- * package already twice records that a fixed template FILE is the drift a
15
- * registry removes.
16
- */
17
1
  import { classifyModules } from "./lib/module-tier.js";
18
2
  import { MODULE_SLICES, normalizeModules, } from "./module-architecture.js";
19
3
  /**
@@ -125,6 +109,60 @@ const MINIMALISM_ROSTER = [
125
109
  { route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
126
110
  { route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
127
111
  ];
112
+ /**
113
+ * `simple-service`'s own rows (#6087) — the T1 lawn-care roster of Epic #5778.
114
+ * The second declared template that does not reuse `TEMPLATE_BASE_ROSTER`: a
115
+ * lawn-care site sells three named services from `/services`, not from a
116
+ * pricing table, so `/how-it-works`, `/features` and `/pricing` are absent —
117
+ * `/pricing`'s `_base` seed still lands on disk, it simply has no rostered
118
+ * route, exactly as it does for `minimalism-site`.
119
+ *
120
+ * `/meet`, `/meet/[slug]`, `/meet/confirmed` and `/appointments` are absent
121
+ * here on purpose: they are the `scheduling` module's own
122
+ * `pageContributions`, merged in by `mergeRoster`. Declaring one here would
123
+ * make that merge refuse the template outright (§ D8's both-claimants
124
+ * refusal).
125
+ *
126
+ * `/purchase/success` and `/purchase/cancel` ARE declared here, and that is a
127
+ * documented divergence from spec § D3. The spec was written at a pin where
128
+ * #6084 was expected to add the pair to `MODULE_SLICES.commerce`'s
129
+ * `pageContributions`. It did not: the operator's shape-2 disposition
130
+ * (#6084 D12) ships the return pair BASE TREE — `CORE_ROUTE_DIRS` carries
131
+ * `[locale]/purchase`, and neither `GATEABLE_SURFACES` nor
132
+ * `MODULE_SURFACES.commerce` gained an entry — so the `commerce` slice
133
+ * contributes no rows at all and nothing else claims these two routes. The
134
+ * issue's AC-1 requires the merged roster to carry them; with no module
135
+ * claimant, the template's own roster is the only place that can declare
136
+ * them, and doing so trips no collision.
137
+ *
138
+ * `/account` carries no `content`: it is a code route (the `(authed)` group),
139
+ * like `/sign-in` on the base roster and like the API-backed rows the
140
+ * scheduling module contributes. `/services/[slug]` likewise declares none —
141
+ * its seed is a whole DIRECTORY (`content/en/Service`), and a roster row's
142
+ * `content` names files the manifest generator reads frontmatter from.
143
+ */
144
+ const SIMPLE_SERVICE_ROSTER = [
145
+ { route: "/", content: ["content/en/HomePage/home.mdx"] },
146
+ { route: "/services", content: ["content/en/ServicesList/services.mdx"] },
147
+ { route: "/services/[slug]" },
148
+ { route: "/about", content: ["content/en/AboutPage/about.mdx"] },
149
+ { route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
150
+ { route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
151
+ { route: "/returns", content: ["content/en/ReturnsPolicyPage/returns.mdx"] },
152
+ {
153
+ route: "/cancellation",
154
+ content: ["content/en/CancellationPolicyPage/cancellation.mdx"],
155
+ },
156
+ {
157
+ route: "/shipping",
158
+ content: ["content/en/ShippingPolicyPage/shipping.mdx"],
159
+ },
160
+ { route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
161
+ { route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
162
+ { route: "/account" },
163
+ { route: "/purchase/success" },
164
+ { route: "/purchase/cancel" },
165
+ ];
128
166
  /**
129
167
  * The three settled templates and their fixed `requires` lists — settled by
130
168
  * Sam, 2026-09-14 (parent § D12). The plain name is the Pro one: it is the
@@ -156,6 +194,7 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
156
194
  "marketing-site-free": {
157
195
  name: "marketing-site-free",
158
196
  requires: ["marketing"],
197
+ categories: ["accounting", "legal", "technology"],
159
198
  extends: BASE_LAYER_DIR,
160
199
  roster: [...TEMPLATE_BASE_ROSTER, FREE_BLOG_TEASER_ROW],
161
200
  },
@@ -167,6 +206,21 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
167
206
  "marketing-site": {
168
207
  name: "marketing-site",
169
208
  requires: ["marketing", "docs-blog", "scheduling", "signal-collectors"],
209
+ // The flagship is the general-purpose template: it carries the whole
210
+ // registry, so every group tile on the hub has at least one template.
211
+ categories: [
212
+ "accounting",
213
+ "legal",
214
+ "hvac",
215
+ "roofing",
216
+ "plumbing",
217
+ "electrical",
218
+ "landscaping",
219
+ "auto-repair",
220
+ "real-estate",
221
+ "technology",
222
+ "medical-specialty",
223
+ ],
170
224
  extends: BASE_LAYER_DIR,
171
225
  roster: TEMPLATE_BASE_ROSTER,
172
226
  },
@@ -188,6 +242,7 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
188
242
  "signal-collectors",
189
243
  "multi-tenant",
190
244
  ],
245
+ categories: ["technology", "medical-specialty"],
191
246
  extends: BASE_LAYER_DIR,
192
247
  roster: TEMPLATE_BASE_ROSTER,
193
248
  },
@@ -222,6 +277,7 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
222
277
  "minimalism-site": {
223
278
  name: "minimalism-site",
224
279
  requires: ["marketing", "scheduling", "signal-collectors"],
280
+ categories: ["real-estate", "technology", "legal"],
225
281
  extends: BASE_LAYER_DIR,
226
282
  roster: MINIMALISM_ROSTER,
227
283
  layout: {
@@ -231,6 +287,33 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
231
287
  home: "deck",
232
288
  },
233
289
  },
290
+ /**
291
+ * The T1 lawn-care template (#6087, Epic #5778) — the first site shape
292
+ * that composes `scheduling` and `commerce`: three priced services, a
293
+ * booker, a checkout return pair and the three #5947 policy pages.
294
+ *
295
+ * `requires` lists `marketing` for the registry convention every other
296
+ * manifest keeps: it is free (`module-tier.ts`'s `FREE_MODULES`), so it
297
+ * cannot change `templateDelivery`'s verdict, and listing it keeps the
298
+ * template's own declaration — not `DEFAULT_MODULES` — the authority for
299
+ * what a bare `--template simple-service` run installs. The order is
300
+ * `RECOGNIZED_MODULES` order, which is also `normalizeModules`' output
301
+ * order, so the declared list and the merge order read the same.
302
+ *
303
+ * `scheduling` and `commerce` are both paid, so `templateDelivery`
304
+ * returns `"paid"` from either one alone.
305
+ *
306
+ * It declares NO `layout` block: the default marketing-site chrome is the
307
+ * one a lawn-care site wants, and the issue's STOP boundary excludes
308
+ * layout knobs the spec does not name.
309
+ */
310
+ "simple-service": {
311
+ name: "simple-service",
312
+ requires: ["marketing", "scheduling", "commerce"],
313
+ categories: ["landscaping"],
314
+ extends: BASE_LAYER_DIR,
315
+ roster: SIMPLE_SERVICE_ROSTER,
316
+ },
234
317
  });
235
318
  /** Look up a declared template. @throws TemplateError on an undeclared name. */
236
319
  export function resolveTemplate(name) {
@@ -37,5 +37,5 @@
37
37
  * is consumed as a plain array across the package.
38
38
  */
39
39
  /** The declared site templates, in `TEMPLATE_MANIFESTS` declaration order. */
40
- export declare const RECOGNIZED_TEMPLATES: readonly ["marketing-site-free", "marketing-site", "saas-product", "minimalism-site"];
40
+ export declare const RECOGNIZED_TEMPLATES: readonly ["marketing-site-free", "marketing-site", "saas-product", "minimalism-site", "simple-service"];
41
41
  export type TemplateName = (typeof RECOGNIZED_TEMPLATES)[number];
@@ -42,4 +42,5 @@ export const RECOGNIZED_TEMPLATES = [
42
42
  "marketing-site",
43
43
  "saas-product",
44
44
  "minimalism-site",
45
+ "simple-service",
45
46
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ailk",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Scaffolder for AI Launch Kit — `pnpm create ailk@latest <dir>` produces a starter repo consuming @working-theory/* from npm (per ADR 0007).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,8 @@
25
25
  "tar": "^7.5.21"
26
26
  },
27
27
  "devDependencies": {
28
- "@working-theory/templates": "0.24.0"
28
+ "@working-theory/schema": "0.26.0",
29
+ "@working-theory/templates": "0.26.0"
29
30
  },
30
31
  "repository": {
31
32
  "type": "git",
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: Marketing site (Pro) — marketing-site
3
+ description: The Pro flagship: the Standard marketing pages plus blog, docs, booking and signal-collector pages, on the base foundation.
4
+ colors:
5
+ bg: "#ffffff"
6
+ fg: "#000000"
7
+ surface: "#ffffff"
8
+ surface-secondary: "#ffffff"
9
+ border: "#000000"
10
+ text-muted: "#333333"
11
+ brand: "#000000"
12
+ fg-on-brand: "#ffffff"
13
+ accent: "#000000"
14
+ bg-dark: "#000000"
15
+ fg-dark: "#ffffff"
16
+ border-dark: "#ffffff"
17
+ brand-dark: "#ffffff"
18
+ typography:
19
+ display:
20
+ fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
21
+ fontSize: "6rem"
22
+ fontWeight: 400
23
+ lineHeight: 1
24
+ letterSpacing: "-0.05em"
25
+ heading-section:
26
+ fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
27
+ fontSize: "2.25rem"
28
+ fontWeight: 400
29
+ lineHeight: 1.25
30
+ letterSpacing: "-0.05em"
31
+ heading-item:
32
+ fontSize: "1.25rem"
33
+ fontWeight: 600
34
+ lineHeight: 1.375
35
+ body:
36
+ fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
37
+ fontSize: "1.125rem"
38
+ fontWeight: 400
39
+ lineHeight: 1.5
40
+ eyebrow:
41
+ fontSize: "0.875rem"
42
+ fontWeight: 600
43
+ lineHeight: 1.4
44
+ letterSpacing: "0.05em"
45
+ rounded:
46
+ button: "0.25rem"
47
+ card: "0.75rem"
48
+ spacing:
49
+ section: "4rem"
50
+ card: "1.5rem"
51
+ grid: "1.5rem"
52
+ container: "1280px"
53
+ ---
54
+
55
+ <!--
56
+ Source template: marketing-site
57
+ Version: create-ailk {{CREATE_AILK_VERSION}}
58
+ Extends: _base — installing this template replaces the base scaffold's
59
+ DESIGN.md with this file. Its tokens are the base foundation's, unchanged:
60
+ this template carries no theme of its own.
61
+
62
+ The tokens above describe what the site RENDERS today. Colours come from
63
+ content/_site.mdx (`theme.colors`); type, radius and spacing are platform
64
+ defaults a site cannot override yet — see "Where this is heading" below.
65
+ -->
66
+
67
+ # Marketing site (Pro)
68
+
69
+ ## Overview
70
+
71
+ The Pro flagship template. It carries the same nine-beat home and marketing pages as Standard (Free), and adds the pages its four Pro modules bring: the blog, the docs, the booking pages under `/meet`, and the signal-collector surfaces. It runs on the base foundation unchanged.
72
+
73
+ ## Colors
74
+
75
+ ### Primary
76
+
77
+ **Black** (`brand` `#000000`) fills the primary button; its label is white. The secondary button is white with a black hairline and black label.
78
+
79
+ ### Neutral
80
+
81
+ Pure white ground (`bg` `#ffffff`), pure black ink for headings (`fg` `#000000`), and near-black `#333333` for body copy — well above AA on white. **Borders are black** (`#000000`): card outlines, the rule under the navigation, the rules between sections and the rule above the footer are all 1px black lines. Cards are white, not tinted (`surface-secondary` is white too). There is no accent colour — `accent` is black.
82
+
83
+ Dark mode inverts: black ground, white ink, white rules, white primary button with black label.
84
+
85
+ ### Named Rules
86
+
87
+ - **Rules, not fills.** A container is drawn with a black hairline on the white ground. Grey fills are reserved for image placeholders.
88
+
89
+ ## Typography
90
+
91
+ System sans throughout; no web font.
92
+
93
+ ### Hierarchy
94
+
95
+ | Role | Size | Weight | Notes |
96
+ | --------------- | -------- | ------ | --------------------------------------------------------------------------- |
97
+ | Hero headline | 6rem | 400 | Tracking -0.05em, line-height 1 |
98
+ | Section heading | 2.25rem | 400 | Tracking -0.05em — light and tight, not bold |
99
+ | Item heading | 1.25rem | 600 | Card, feature and step titles |
100
+ | Body | 1.125rem | 400 | `#333333`, line-height 1.5 |
101
+ | Section label | 0.875rem | 600 | Uppercase, +0.05em tracking today — the small label above a section heading |
102
+
103
+ Measured from the rendered scaffold (1440px wide), not transcribed from tokens.
104
+
105
+ The small label above a section heading is **kept** as part of this foundation's voice (operator-disposed 2026-09-22) and is headed toward the treatment below.
106
+
107
+ ## Layout
108
+
109
+ Full navigation with the announcement banner; a multi-column footer; the default home. Every page and its sections are listed in `TEMPLATE-MANIFEST.md` in this directory. Shared foundation: a 1280px container, sections at 4rem, card grids at 1.5rem, breakpoints 320 / 768 / 1024 / 1440.
110
+
111
+ ## Shapes
112
+
113
+ Two radii today: buttons at 0.25rem, cards and outlined boxes at 0.75rem. Headed toward square corners — see below.
114
+
115
+ ## Components
116
+
117
+ ### Buttons
118
+
119
+ Primary: black fill, white label, 0.25rem corners. Secondary: transparent with a black 1px outline and black label. Both are the library `Button`.
120
+
121
+ ### Cards / Containers
122
+
123
+ White panels with a black 1px outline, 0.75rem corners, `card` (1.5rem) padding. The one exception today: the "how it works" steps render as dark filled cards (see below).
124
+
125
+ ### Navigation
126
+
127
+ Full navigation: wordmark left, page links, an outlined and a filled button at the far right, the announcement banner above. A black hairline separates it from the page.
128
+
129
+ ## Where this is heading
130
+
131
+ The foundation's pinned direction is the pacing of a classic wireframe marketing kit — `standardissue.webflow.io` is the reference for rhythm, type scale, spacing density and section pacing only; no image, copy or code is taken from it. Six parts of that direction cannot be expressed through a site's theme today, so they wait on a platform change rather than being hand-coded. Until they land, this file describes the rendered site above, not these targets.
132
+
133
+ | Target | Reference value | Blocked by |
134
+ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
135
+ | Square corners on buttons, cards and inputs | radius 0 | A site's `theme:` block accepts colours only — no radius |
136
+ | Bold, tighter headings | hero ~3.6rem and section headings ~2.9rem, both at weight 700 with tracking about -0.02em (today 6rem and 2.25rem at weight 400) | No per-site type-role override |
137
+ | Generous section pacing | about 10rem between sections, not 4rem | No per-site section-spacing override; `spacious` (6rem) is not author-selectable |
138
+ | Section label in sentence case, bold, no tracking | "Core Features", not "CORE FEATURES" | The eyebrow role bakes in uppercase and tracking |
139
+ | Whitespace between sections, not rules | no rule between bands | Section dividers share the one `border` colour with card outlines, so black outlines make black dividers |
140
+ | Outlined steps in "how it works" | three plain outlined columns | The steps section renders dark filled cards; no outlined variant |
141
+
142
+ ## Do's and Don'ts
143
+
144
+ - **Do** keep every page built from registered sections. If a section you need does not exist, request it rather than writing one-off markup.
145
+ - **Do** change colours in `content/_site.mdx` `theme.colors`; they reach every section.
146
+ - **Don't** add a colour accent. The foundation's one idea is black on white; a brand pass adds colour deliberately, through the theme.
147
+ - **Don't** replace a black rule with a shadow or a grey fill.
148
+ - **Don't** hard-code the "heading toward" values above into a page. They arrive through the platform, or not at all.
@@ -1,8 +1,20 @@
1
1
  {
2
2
  "template": "marketing-site",
3
3
  "requires": ["marketing", "docs-blog", "scheduling", "signal-collectors"],
4
- "createAilkVersion": "0.5.0",
5
- "generatedHash": "0d7192a6f912c43e2ae3d51dae5878a72cf01f50dd206e341b0c59cf46dbd40c",
4
+ "categories": [
5
+ "accounting",
6
+ "legal",
7
+ "hvac",
8
+ "roofing",
9
+ "plumbing",
10
+ "electrical",
11
+ "landscaping",
12
+ "auto-repair",
13
+ "real-estate",
14
+ "technology",
15
+ "medical-specialty"
16
+ ],
17
+ "generatedHash": "7ac1901833c4607d7b1a5f7f8531d18618ecdc4a3e810480635d3d6b5eb3be83",
6
18
  "layout": {
7
19
  "nav": "full",
8
20
  "footer": "columns",
@@ -295,6 +307,14 @@
295
307
  "chrome": "on",
296
308
  "sections": []
297
309
  },
310
+ {
311
+ "route": "/appointments",
312
+ "pageType": null,
313
+ "schema": null,
314
+ "shell": "MarketingShell",
315
+ "chrome": "on",
316
+ "sections": []
317
+ },
298
318
  {
299
319
  "route": "/flows/[slug]",
300
320
  "pageType": null,
@@ -250,6 +250,13 @@ Target composition (deferred to **#5670**, same as `/meet` above):
250
250
  _Code route — no content, no sections._
251
251
  <!-- generated:end -->
252
252
 
253
+ `/appointments`:
254
+
255
+ <!-- generated:begin page=/appointments -->
256
+
257
+ _Code route — no content, no sections._
258
+ <!-- generated:end -->
259
+
253
260
  ### `/flows/<slug>` — InstrumentEntryPage · schema `WebPage` · signal-collectors
254
261
 
255
262
  The signal collector's landing (sample: a 5-question fit check). Sections: `hero` · `feature` · `step-flow` (preview) · `cta` · `faq`.
@@ -322,6 +329,7 @@ Everything in the Free manifest § 2a applies. Pro adds:
322
329
  ```
323
330
  marketing-site:
324
331
  requires: [marketing, docs-blog, scheduling, signal-collectors]
332
+ categories: [accounting, legal, hvac, roofing, plumbing, electrical, landscaping, auto-repair, real-estate, technology, medical-specialty]
325
333
  roster:
326
334
  - { route: "/", content: ["content/en/HomePage/home.mdx"] }
327
335
  - { route: "/how-it-works", content: ["content/en/LandingPage/how-it-works.mdx"] }
@@ -338,6 +346,7 @@ marketing-site:
338
346
  - { route: "/meet" }
339
347
  - { route: "/meet/[slug]" }
340
348
  - { route: "/meet/confirmed" }
349
+ - { route: "/appointments" }
341
350
  - { route: "/flows/[slug]" }
342
351
  - { route: "/flows/[slug]/start" }
343
352
  - { route: "/flows/[slug]/results/[payload]" }
@@ -382,8 +391,6 @@ Every component the roster rows' seed content composes today (generated):
382
391
 
383
392
  | Gap | Issue |
384
393
  | ------------------------------------------------------------------- | ---------- |
385
- | `/meet` rename | #5563 |
386
- | `ReportPage` + `/reports/<slug>` | #5562 |
387
394
  | Module bundles carry no LICENSE | #5552 |
388
395
  | Strip ignores `commercial_tier` (paid dirs still under `packages/`) | #5475 |
389
396
  | The Pro demo host `marketing-site.ailaunchkit.ai` — provisioning | #5464 body |
@@ -7,5 +7,5 @@
7
7
  "provenance.json": ".ailk-template.json",
8
8
  "content/en/blog/05-this-vc-morning-routine-will-make-you-super-annoying.mdx": "apps/web/content/en/blog/launching-ailk.mdx"
9
9
  },
10
- "postInstall": "Template marketing-site installed: its module samples - the Pro blog (5 posts) and docs (3 pages) from docs-blog, the projects (2 + listing), thank-you pages (contact, newsletter, apply), fit-check flow definition, waitlist experiment and sample report PDF under apps/web/public/reports/ from signal-collectors - arrived with those module bundles, and /pricing, /privacy and /terms with the base layer (its /reports/<slug> route is pending #5562; /meet, /meet/<slug> and /meet/confirmed shipped by #5563). This template adds one copy override (blog post 05) - every sample is placeholder copy to replace before you launch."
10
+ "postInstall": "Template marketing-site installed: its module samples - the Pro blog (5 posts) and docs (3 pages) from docs-blog, the booking pages at /meet, /meet/<slug> and /meet/confirmed from scheduling, the projects (2 + listing), thank-you pages (contact, newsletter, apply), fit-check flow definition, waitlist experiment, the report reader at /reports/<slug> and its sample report PDF under apps/web/public/reports/ from signal-collectors - arrived with those module bundles, and /pricing, /privacy and /terms with the base layer. This template adds one copy override (blog post 05) - every sample is placeholder copy to replace before you launch."
11
11
  }