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,240 @@
1
+ {
2
+ "template": "simple-service",
3
+ "requires": ["marketing", "scheduling", "commerce"],
4
+ "categories": ["landscaping"],
5
+ "generatedHash": "f0dce515363186cee7ec9d1b1fd91d0ca11e039db31e843d1235d451dd49e736",
6
+ "layout": {
7
+ "nav": "full",
8
+ "footer": "columns",
9
+ "announcementBanner": true,
10
+ "home": "default"
11
+ },
12
+ "rows": [
13
+ {
14
+ "route": "/",
15
+ "pageType": "HomePage",
16
+ "schema": "HomePage",
17
+ "shell": "MarketingShell",
18
+ "chrome": "on",
19
+ "sections": [
20
+ {
21
+ "type": "hero",
22
+ "component": "Hero"
23
+ },
24
+ {
25
+ "type": "items",
26
+ "component": "Items"
27
+ },
28
+ {
29
+ "type": "cta",
30
+ "component": "CTA"
31
+ }
32
+ ]
33
+ },
34
+ {
35
+ "route": "/services",
36
+ "pageType": "ServicesList",
37
+ "schema": "ServicesList",
38
+ "shell": "MarketingShell",
39
+ "chrome": "on",
40
+ "sections": [
41
+ {
42
+ "type": "hero",
43
+ "component": "Hero"
44
+ },
45
+ {
46
+ "type": "items",
47
+ "component": "Items"
48
+ },
49
+ {
50
+ "type": "cta",
51
+ "component": "CTA"
52
+ }
53
+ ]
54
+ },
55
+ {
56
+ "route": "/services/[slug]",
57
+ "pageType": null,
58
+ "schema": null,
59
+ "shell": "MarketingShell",
60
+ "chrome": "on",
61
+ "sections": []
62
+ },
63
+ {
64
+ "route": "/about",
65
+ "pageType": "AboutPage",
66
+ "schema": "AboutPage",
67
+ "shell": "MarketingShell",
68
+ "chrome": "on",
69
+ "sections": [
70
+ {
71
+ "type": "content-block",
72
+ "component": "ContentBlock"
73
+ },
74
+ {
75
+ "type": "cta",
76
+ "component": "CTA"
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "route": "/contact",
82
+ "pageType": "ContactPage",
83
+ "schema": "ContactPage",
84
+ "shell": "MarketingShell",
85
+ "chrome": "on",
86
+ "sections": [
87
+ {
88
+ "type": "hero",
89
+ "component": "Hero"
90
+ },
91
+ {
92
+ "type": "contact-form",
93
+ "component": "ContactForm"
94
+ },
95
+ {
96
+ "type": "cta",
97
+ "component": "CTA"
98
+ }
99
+ ]
100
+ },
101
+ {
102
+ "route": "/faq",
103
+ "pageType": "FAQPage",
104
+ "schema": "FAQPage",
105
+ "shell": "MarketingShell",
106
+ "chrome": "on",
107
+ "sections": [
108
+ {
109
+ "type": "faq",
110
+ "component": "FAQ"
111
+ },
112
+ {
113
+ "type": "cta",
114
+ "component": "CTA"
115
+ }
116
+ ]
117
+ },
118
+ {
119
+ "route": "/returns",
120
+ "pageType": "ReturnsPolicyPage",
121
+ "schema": "ReturnsPolicyPage",
122
+ "shell": "MarketingShell",
123
+ "chrome": "on",
124
+ "sections": [
125
+ {
126
+ "type": "document-chassis",
127
+ "component": "DocumentChassis"
128
+ }
129
+ ]
130
+ },
131
+ {
132
+ "route": "/cancellation",
133
+ "pageType": "CancellationPolicyPage",
134
+ "schema": "CancellationPolicyPage",
135
+ "shell": "MarketingShell",
136
+ "chrome": "on",
137
+ "sections": [
138
+ {
139
+ "type": "document-chassis",
140
+ "component": "DocumentChassis"
141
+ }
142
+ ]
143
+ },
144
+ {
145
+ "route": "/shipping",
146
+ "pageType": "ShippingPolicyPage",
147
+ "schema": "ShippingPolicyPage",
148
+ "shell": "MarketingShell",
149
+ "chrome": "on",
150
+ "sections": [
151
+ {
152
+ "type": "document-chassis",
153
+ "component": "DocumentChassis"
154
+ }
155
+ ]
156
+ },
157
+ {
158
+ "route": "/privacy",
159
+ "pageType": "PrivacyPage",
160
+ "schema": "PrivacyPage",
161
+ "shell": "MarketingShell",
162
+ "chrome": "on",
163
+ "sections": [
164
+ {
165
+ "type": "document-chassis",
166
+ "component": "DocumentChassis"
167
+ }
168
+ ]
169
+ },
170
+ {
171
+ "route": "/terms",
172
+ "pageType": "TermsPage",
173
+ "schema": "TermsPage",
174
+ "shell": "MarketingShell",
175
+ "chrome": "on",
176
+ "sections": [
177
+ {
178
+ "type": "document-chassis",
179
+ "component": "DocumentChassis"
180
+ }
181
+ ]
182
+ },
183
+ {
184
+ "route": "/account",
185
+ "pageType": null,
186
+ "schema": null,
187
+ "shell": "MarketingShell",
188
+ "chrome": "on",
189
+ "sections": []
190
+ },
191
+ {
192
+ "route": "/purchase/success",
193
+ "pageType": null,
194
+ "schema": null,
195
+ "shell": "MarketingShell",
196
+ "chrome": "on",
197
+ "sections": []
198
+ },
199
+ {
200
+ "route": "/purchase/cancel",
201
+ "pageType": null,
202
+ "schema": null,
203
+ "shell": "MarketingShell",
204
+ "chrome": "on",
205
+ "sections": []
206
+ },
207
+ {
208
+ "route": "/meet",
209
+ "pageType": null,
210
+ "schema": null,
211
+ "shell": "MarketingShell",
212
+ "chrome": "on",
213
+ "sections": []
214
+ },
215
+ {
216
+ "route": "/meet/[slug]",
217
+ "pageType": null,
218
+ "schema": null,
219
+ "shell": "MarketingShell",
220
+ "chrome": "on",
221
+ "sections": []
222
+ },
223
+ {
224
+ "route": "/meet/confirmed",
225
+ "pageType": null,
226
+ "schema": null,
227
+ "shell": "MarketingShell",
228
+ "chrome": "on",
229
+ "sections": []
230
+ },
231
+ {
232
+ "route": "/appointments",
233
+ "pageType": null,
234
+ "schema": null,
235
+ "shell": "MarketingShell",
236
+ "chrome": "on",
237
+ "sections": []
238
+ }
239
+ ]
240
+ }
@@ -0,0 +1,278 @@
1
+ # Template manifest — `simple-service`
2
+
3
+ > The T1 lawn-care template (#6087, Epic #5778) — the first site shape that composes `scheduling` and `commerce`: three priced services, a booker, a checkout return pair and the three #5947 policy pages. Generated file: the regions between `<!-- generated:begin <id> -->` and `<!-- generated:end -->` are produced by `scripts/build-template-manifest.mjs --template simple-service` from the composed layer stack (this tree → its required modules → `_base` → the always-copied overlay), each roster row's MDX `sections[]`, and `component-catalog.json`. Everything outside the markers is written by hand.
4
+
5
+ | Field | Value |
6
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------- |
7
+ | Template | `simple-service` |
8
+ | Level | Pro (derived from `requires` — `scheduling` and `commerce` are paid; never declared) |
9
+ | `requires` | `[marketing, scheduling, commerce]` — the first template to take `commerce` |
10
+ | `extends` | `_base` — lineage only, never level |
11
+ | Delivery | licence-checked module bundle (#5441); never in the Free tarball |
12
+ | Sample content posture | every line of copy, and all three service prices, are **placeholders** — and the prices are PUBLISHED as JSON-LD `Offer`s |
13
+
14
+ ## 1. Chrome
15
+
16
+ This template declares **no `layout` block**. The default marketing-site chrome is what a lawn-care site wants — a nav row a reader can reach `/services` from, the four-column footer, and the document-scroll home — and the issue's STOP boundary excludes layout knobs the spec does not name.
17
+
18
+ ### Layout knobs (#5612)
19
+
20
+ The template's `layout` block — resolved with `resolveSiteChrome`, defaults filled.
21
+
22
+ <!-- generated:begin layout -->
23
+
24
+ | Knob | Value |
25
+ | -------------------- | --------- |
26
+ | `nav` | `full` |
27
+ | `footer` | `columns` |
28
+ | `announcementBanner` | `true` |
29
+ | `home` | `default` |
30
+
31
+ <!-- generated:end -->
32
+
33
+ ## 2. The money path
34
+
35
+ The whole point of this template is the first roster that takes a booking **and** the payment for it:
36
+
37
+ | Step | Where it lives |
38
+ | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | Discovery | `/services` and the three `/services/<slug>` pages. Each detail page's top-level `price` + `priceCurrency` + `provider` become one schema.org `Offer` in its JSON-LD (#5838) — the free discovery floor. |
40
+ | Booking | `/meet`, `/meet/<slug>`, `/meet/confirmed` — the `scheduling` module's own contributed rows; `/appointments` is the site owner's own list (#6086). |
41
+ | Payment | a provider-hosted page on the seller's own Stripe account. Nothing on this site renders a card form. |
42
+ | Return | `/purchase/success` and `/purchase/cancel` — base tree under #6084 D12's shape-2 disposition, gated at request time on the `commerce` licence claim. |
43
+ | Policies | `/returns`, `/cancellation`, `/shipping` (#5947) — their seed rides the always-copied overlay. |
44
+
45
+ ## 3. Pages
46
+
47
+ One `page=<route>` region per roster row, generated from the seed file the composed layer stack lands for that route.
48
+
49
+ `/`:
50
+
51
+ <!-- generated:begin page=/ -->
52
+
53
+ | # | Section | Component | Copy (first line) |
54
+ | --- | ---------------------------------------------------------- | --------- | ---------------------------------------------- |
55
+ | 1 | `hero` (centered · eyebrow "{Your service area}" · 2 CTAs) | `Hero` | {Lawn care that turns up when it says it will} |
56
+ | 2 | `items` (items ×3) | `Items` | What we do |
57
+ | 3 | `cta` (minimal · 2 CTAs) | `CTA` | Ready for a tidier yard? |
58
+
59
+ <!-- generated:end -->
60
+
61
+ `/services`:
62
+
63
+ <!-- generated:begin page=/services -->
64
+
65
+ | # | Section | Component | Copy (first line) |
66
+ | --- | -------------------------------------- | --------- | ------------------------ |
67
+ | 1 | `hero` (centered · eyebrow "Services") | `Hero` | Three jobs, three prices |
68
+ | 2 | `items` (items ×3) | `Items` | What we do |
69
+ | 3 | `cta` (minimal · 1 CTA) | `CTA` | Not sure which one? |
70
+
71
+ <!-- generated:end -->
72
+
73
+ `/services/[slug]`:
74
+
75
+ <!-- generated:begin page=/services/[slug] -->
76
+
77
+ _Code route — no content, no sections._
78
+ <!-- generated:end -->
79
+
80
+ `/about`:
81
+
82
+ <!-- generated:begin page=/about -->
83
+
84
+ | # | Section | Component | Copy (first line) |
85
+ | --- | ------------------------------------------ | -------------- | ------------------------------------------ |
86
+ | 1 | `content-block` (narrow · eyebrow "About") | `ContentBlock` | {A small crew, the same yards, every week} |
87
+ | 2 | `cta` (minimal · 2 CTAs) | `CTA` | Want us to take a look? |
88
+
89
+ <!-- generated:end -->
90
+
91
+ `/contact`:
92
+
93
+ <!-- generated:begin page=/contact -->
94
+
95
+ | # | Section | Component | Copy (first line) |
96
+ | --- | ------------------------------------- | ------------- | -------------------------------- |
97
+ | 1 | `hero` (centered · eyebrow "Contact") | `Hero` | Tell us about the yard |
98
+ | 2 | `contact-form` (card · fields ×3) | `ContactForm` | Name · Email · What needs doing? |
99
+ | 3 | `cta` (minimal · 1 CTA) | `CTA` | Would a visit be faster? |
100
+
101
+ <!-- generated:end -->
102
+
103
+ `/faq`:
104
+
105
+ <!-- generated:begin page=/faq -->
106
+
107
+ | # | Section | Component | Copy (first line) |
108
+ | --- | ------------------------------------------------------------- | --------- | ---------------------- |
109
+ | 1 | `faq` (centered · items ×5 · supportLink · initialOpen first) | `FAQ` | Questions |
110
+ | 2 | `cta` (minimal · 1 CTA) | `CTA` | Still have a question? |
111
+
112
+ <!-- generated:end -->
113
+
114
+ `/returns`:
115
+
116
+ <!-- generated:begin page=/returns -->
117
+
118
+ | # | Section | Component | Copy (first line) |
119
+ | --- | ------------------ | ----------------- | ----------------- |
120
+ | 1 | `document-chassis` | `DocumentChassis` | Returns & Refunds |
121
+
122
+ <!-- generated:end -->
123
+
124
+ `/cancellation`:
125
+
126
+ <!-- generated:begin page=/cancellation -->
127
+
128
+ | # | Section | Component | Copy (first line) |
129
+ | --- | ------------------ | ----------------- | ------------------- |
130
+ | 1 | `document-chassis` | `DocumentChassis` | Cancellation Policy |
131
+
132
+ <!-- generated:end -->
133
+
134
+ `/shipping`:
135
+
136
+ <!-- generated:begin page=/shipping -->
137
+
138
+ | # | Section | Component | Copy (first line) |
139
+ | --- | ------------------ | ----------------- | ----------------- |
140
+ | 1 | `document-chassis` | `DocumentChassis` | Shipping Policy |
141
+
142
+ <!-- generated:end -->
143
+
144
+ `/privacy`:
145
+
146
+ <!-- generated:begin page=/privacy -->
147
+
148
+ | # | Section | Component | Copy (first line) |
149
+ | --- | ------------------------------------------------------------------ | ----------------- | ----------------- |
150
+ | 1 | `document-chassis` (eyebrow "PLACEHOLDER — REPLACE BEFORE LAUNCH") | `DocumentChassis` | Privacy Policy |
151
+
152
+ <!-- generated:end -->
153
+
154
+ `/terms`:
155
+
156
+ <!-- generated:begin page=/terms -->
157
+
158
+ | # | Section | Component | Copy (first line) |
159
+ | --- | ------------------------------------------------------------------ | ----------------- | ----------------- |
160
+ | 1 | `document-chassis` (eyebrow "PLACEHOLDER — REPLACE BEFORE LAUNCH") | `DocumentChassis` | Terms of Service |
161
+
162
+ <!-- generated:end -->
163
+
164
+ `/account`:
165
+
166
+ <!-- generated:begin page=/account -->
167
+
168
+ _Code route — no content, no sections._
169
+ <!-- generated:end -->
170
+
171
+ `/purchase/success`:
172
+
173
+ <!-- generated:begin page=/purchase/success -->
174
+
175
+ _Code route — no content, no sections._
176
+ <!-- generated:end -->
177
+
178
+ `/purchase/cancel`:
179
+
180
+ <!-- generated:begin page=/purchase/cancel -->
181
+
182
+ _Code route — no content, no sections._
183
+ <!-- generated:end -->
184
+
185
+ `/meet`:
186
+
187
+ <!-- generated:begin page=/meet -->
188
+
189
+ _Code route — no content, no sections._
190
+ <!-- generated:end -->
191
+
192
+ `/meet/[slug]`:
193
+
194
+ <!-- generated:begin page=/meet/[slug] -->
195
+
196
+ _Code route — no content, no sections._
197
+ <!-- generated:end -->
198
+
199
+ `/meet/confirmed`:
200
+
201
+ <!-- generated:begin page=/meet/confirmed -->
202
+
203
+ _Code route — no content, no sections._
204
+ <!-- generated:end -->
205
+
206
+ `/appointments`:
207
+
208
+ <!-- generated:begin page=/appointments -->
209
+
210
+ _Code route — no content, no sections._
211
+ <!-- generated:end -->
212
+
213
+ ## 4. Roster, as the registry declares it
214
+
215
+ `simple-service` is the second declared template that does not reuse `TEMPLATE_BASE_ROSTER`: a lawn-care site sells three named services from `/services`, not from a pricing table, so `/how-it-works`, `/features` and `/pricing` are not pages this site has. `/pricing`'s absence is not a missing file — the `_base` layer still lands `content/en/Pricing/pricing.mdx`; the roster is what the template IS, so an unrostered page simply has no route directory copied. The merged roster, as the registry composes it:
216
+
217
+ <!-- generated:begin roster -->
218
+
219
+ ```
220
+ simple-service:
221
+ requires: [marketing, scheduling, commerce]
222
+ categories: [landscaping]
223
+ roster:
224
+ - { route: "/", content: ["content/en/HomePage/home.mdx"] }
225
+ - { route: "/services", content: ["content/en/ServicesList/services.mdx"] }
226
+ - { route: "/services/[slug]" }
227
+ - { route: "/about", content: ["content/en/AboutPage/about.mdx"] }
228
+ - { route: "/contact", content: ["content/en/ContactPage/contact.mdx"] }
229
+ - { route: "/faq", content: ["content/en/FAQPage/faq.mdx"] }
230
+ - { route: "/returns", content: ["content/en/ReturnsPolicyPage/returns.mdx"] }
231
+ - { route: "/cancellation", content: ["content/en/CancellationPolicyPage/cancellation.mdx"] }
232
+ - { route: "/shipping", content: ["content/en/ShippingPolicyPage/shipping.mdx"] }
233
+ - { route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] }
234
+ - { route: "/terms", content: ["content/en/TermsPage/terms.mdx"] }
235
+ - { route: "/account" }
236
+ - { route: "/purchase/success" }
237
+ - { route: "/purchase/cancel" }
238
+ - { route: "/meet" }
239
+ - { route: "/meet/[slug]" }
240
+ - { route: "/meet/confirmed" }
241
+ - { route: "/appointments" }
242
+ ```
243
+
244
+ <!-- generated:end -->
245
+
246
+ By source:
247
+
248
+ ```
249
+ template: / · /services · /services/<slug> · /about · /contact · /faq
250
+ /returns · /cancellation · /shipping · /privacy · /terms · /account
251
+ /purchase/success · /purchase/cancel
252
+ scheduling: /meet · /meet/<slug> · /meet/confirmed · /appointments
253
+ ```
254
+
255
+ **Why the two `/purchase/*` rows are the TEMPLATE's and not the `commerce` module's.** #6084 landed the checkout return pair under the operator's shape-2 disposition (#6084 D12): `CORE_ROUTE_DIRS` carries `[locale]/purchase`, and neither `GATEABLE_SURFACES` nor `MODULE_SURFACES.commerce` gained an entry, so `MODULE_SLICES.commerce` contributes **no** `pageContributions` at all. Nothing else claims the two routes, so declaring them here trips no both-claimants refusal — and the issue's AC-1 requires the merged roster to carry them. The four scheduling rows, by contrast, **are** the module's, and declaring one here would make `mergeRoster` refuse this template outright.
256
+
257
+ `/account` and the three policy routes carry no `GATEABLE_SURFACES` entry and need none: `(authed)` ships unconditionally, and `/returns`, `/cancellation` and `/shipping` have no gateable surface at all, so they are always copied. The three module-less surfaces this roster enables are `privacy`, `services` and `terms`.
258
+
259
+ ## 5. Component inventory
260
+
261
+ Every component the roster rows' seed content composes today (generated):
262
+
263
+ <!-- generated:begin inventory -->
264
+
265
+ | Tier | Used by this template |
266
+ | -------- | ------------------------------------------------------------------------------- |
267
+ | Shell | `MarketingShell` |
268
+ | Chrome | `Nav`, `Footer`, `Banner` (+ `BannerConsentIsland`, `BannerDismissIsland`) |
269
+ | Sections | `ContactForm`, `ContentBlock`, `CTA`, `DocumentChassis`, `FAQ`, `Hero`, `Items` |
270
+
271
+ <!-- generated:end -->
272
+
273
+ ## 6. Known gaps this manifest depends on
274
+
275
+ | Gap | Issue |
276
+ | -------------------------------------------------------------------------------------------- | ----- |
277
+ | No routes-map row for `/account`, `/appointments` or `/purchase/*`, so those rows show blank | #5572 |
278
+ | The Pro demo host `simple-service.ailaunchkit.ai` — provisioning is the runbook's act | #5778 |
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "simple-service",
3
+ "requires": ["marketing", "scheduling", "commerce"],
4
+ "extends": "_base",
5
+ "$comment": "The T1 lawn-care template (#6087, Epic #5778) — the first site shape that composes scheduling and commerce. Composed base -> modules -> template: /pricing (unrostered), /privacy and /terms arrive with the _base layer this extends; /meet, /meet/<slug>, /meet/confirmed and /appointments with the scheduling bundle; /purchase/success and /purchase/cancel are BASE TREE (#6084 D12 shape 2 — CORE_ROUTE_DIRS carries [locale]/purchase and the commerce licence claim, not the scaffold, decides whether they serve); /returns, /cancellation, /shipping, /how-it-works, /features, /sign-in and the Free about/contact/faq compositions with the always-copied overlay, which this template's own /about, /contact and /faq files then override. This tree holds ONLY its own compositions and its placeholder copy. It declares no layout block — the default marketing-site chrome is what this template renders with, and the code registry (TEMPLATE_MANIFESTS) is authoritative for a template create-ailk ships, so a duplicate block here would be a second authority for one fact. installMap: bundle-relative source -> scaffold-relative destination; the stager reads only installMap/postInstall/patches. Unmapped content/en/** lands at the scaffold root's content/, exactly as marketing-site-free's does.",
6
+ "installMap": {
7
+ "provenance.json": ".ailk-template.json"
8
+ },
9
+ "postInstall": "Template simple-service installed. This is the lawn-care shape: three priced services at /services (content/en/Service/), a booker at /meet from the scheduling module, the site owner's own list at /appointments, and the checkout return pair at /purchase/success and /purchase/cancel. /privacy and /terms came with the base layer; /returns, /cancellation and /shipping came with the overlay. This template adds the home page, /services and its three detail pages, /about, /contact and /faq. THE THREE PRICES ARE PLACEHOLDERS AND THEY ARE PUBLISHED: each service page's top-level price and priceCurrency become a schema.org Offer in that page's JSON-LD, which is what an agent reading your site quotes back to a buyer — replace all three, and the provider name with them, before you launch. Taking money needs the commerce licence claim and your own Stripe account: without the claim the return pages 404 by design. EVERY line of copy on this site is a placeholder too — replace it before you launch."
10
+ }
@@ -0,0 +1,38 @@
1
+ ---
2
+ type: "AboutPage"
3
+ slug: "about"
4
+ title: "About"
5
+ description: "The crew behind {your company}. Placeholder copy — replace before you launch."
6
+ sections:
7
+ [
8
+ {
9
+ "id": "intro",
10
+ "type": "content-block",
11
+ "data":
12
+ {
13
+ "variant": "narrow",
14
+ "eyebrow": "About",
15
+ "headline": "{A small crew, the same yards, every week}",
16
+ "body": "{Two or three sentences on how the business started, how far you travel, and what you will not take on. Keep it short — this page is read on a phone in a driveway.}",
17
+ },
18
+ },
19
+ {
20
+ "id": "closing",
21
+ "type": "cta",
22
+ "data":
23
+ {
24
+ "variant": "minimal",
25
+ "headline": "Want us to take a look?",
26
+ "primaryCta": { "label": "Book a visit →", "href": "/meet" },
27
+ "secondaryCta":
28
+ {
29
+ "label": "Ask a question",
30
+ "href": "/contact",
31
+ "variant": "outline",
32
+ },
33
+ },
34
+ },
35
+ ]
36
+ ---
37
+
38
+ Placeholder copy. This page overrides the always-copied overlay's `AboutPage/about.mdx`.
@@ -0,0 +1,67 @@
1
+ ---
2
+ type: "ContactPage"
3
+ slug: "contact"
4
+ title: "Contact"
5
+ description: "One form, three fields, an inline confirmation. Placeholder copy — replace before you launch."
6
+ sections:
7
+ [
8
+ {
9
+ "id": "hero",
10
+ "type": "hero",
11
+ "data":
12
+ {
13
+ "variant": "centered",
14
+ "eyebrow": "Contact",
15
+ "headline": "Tell us about the yard",
16
+ "subheadline": "{One line on what happens after you send this, and how long it takes. If a call is faster, say so.}",
17
+ },
18
+ },
19
+ {
20
+ "id": "contact-form",
21
+ "type": "contact-form",
22
+ "data":
23
+ {
24
+ "variant": "card",
25
+ "source": "contact",
26
+ "fields":
27
+ [
28
+ {
29
+ "name": "name",
30
+ "label": "Name",
31
+ "type": "text",
32
+ "required": true,
33
+ },
34
+ {
35
+ "name": "email",
36
+ "label": "Email",
37
+ "type": "email",
38
+ "required": true,
39
+ },
40
+ {
41
+ "name": "message",
42
+ "label": "What needs doing?",
43
+ "type": "textarea",
44
+ "required": true,
45
+ },
46
+ ],
47
+ "submitLabel": "Send →",
48
+ "consentText": "I accept the Terms",
49
+ "consentLink": { "label": "Terms", "href": "/terms" },
50
+ "successMessage": "Thank you — your message is in. You will hear back within {time amount}.",
51
+ "action": "/v1/leads/submit",
52
+ },
53
+ },
54
+ {
55
+ "id": "closing",
56
+ "type": "cta",
57
+ "data":
58
+ {
59
+ "variant": "minimal",
60
+ "headline": "Would a visit be faster?",
61
+ "primaryCta": { "label": "Book a visit →", "href": "/meet" },
62
+ },
63
+ },
64
+ ]
65
+ ---
66
+
67
+ The form posts to the site's own API (`/v1/leads/submit`) and confirms inline — no redirect, no thank-you page. Placeholder copy.