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,56 @@
1
+ ---
2
+ type: "FAQPage"
3
+ slug: "faq"
4
+ title: "FAQ"
5
+ description: "The questions people ask before they book. Placeholder copy — replace every answer before you launch."
6
+ sections:
7
+ [
8
+ {
9
+ "id": "faq",
10
+ "type": "faq",
11
+ "data":
12
+ {
13
+ "headline": "Questions",
14
+ "variant": "centered",
15
+ "initialOpen": "first",
16
+ "items":
17
+ [
18
+ {
19
+ "question": "{Which areas do you cover?}",
20
+ "answer": "{Name the towns, the radius or the postcodes. A reader outside them should know it here.}",
21
+ },
22
+ {
23
+ "question": "{How often do you visit?}",
24
+ "answer": "{Give the real cadence for the recurring job, and say what happens in winter.}",
25
+ },
26
+ {
27
+ "question": "{What does it cost?}",
28
+ "answer": "{The three service pages carry the prices. Say here what moves them — yard size, access, waste removal.}",
29
+ },
30
+ {
31
+ "question": "{How do I pay?}",
32
+ "answer": "{Say when payment is taken and how. Checkout runs on your own Stripe account; the card details never touch this site.}",
33
+ },
34
+ {
35
+ "question": "{What if I need to cancel?}",
36
+ "answer": "{Point at the cancellation policy and give the notice period in one line.}",
37
+ },
38
+ ],
39
+ "supportLink":
40
+ { "label": "Still stuck? Get in touch", "href": "/contact" },
41
+ },
42
+ },
43
+ {
44
+ "id": "closing",
45
+ "type": "cta",
46
+ "data":
47
+ {
48
+ "variant": "minimal",
49
+ "headline": "Still have a question?",
50
+ "primaryCta": { "label": "Contact us →", "href": "/contact" },
51
+ },
52
+ },
53
+ ]
54
+ ---
55
+
56
+ Placeholder copy. Replace every answer before you launch.
@@ -0,0 +1,85 @@
1
+ ---
2
+ type: "HomePage"
3
+ slug: "home"
4
+ title: "Your Company"
5
+ description: "Placeholder home for the simple-service template — a lawn-care site that books a visit and takes the payment. Replace every line before you launch."
6
+ sections:
7
+ [
8
+ {
9
+ "id": "hero",
10
+ "type": "hero",
11
+ "data":
12
+ {
13
+ "variant": "centered",
14
+ "eyebrow": "{Your service area}",
15
+ "headline": "{Lawn care that turns up when it says it will}",
16
+ "subheadline": "{One line on who you serve and what they get. Name the street, the town or the county — a local reader is looking for their own.}",
17
+ "primaryCta": { "label": "Book a visit →", "href": "/meet" },
18
+ "secondaryCta":
19
+ {
20
+ "label": "See services",
21
+ "href": "/services",
22
+ "variant": "outline",
23
+ },
24
+ },
25
+ },
26
+ {
27
+ "id": "services",
28
+ "type": "items",
29
+ "data":
30
+ {
31
+ "headline": "What we do",
32
+ "columns": 3,
33
+ "items":
34
+ [
35
+ {
36
+ "title": "{Lawn maintenance}",
37
+ "description": "{One line on the recurring visit — what it includes and how often it runs.}",
38
+ "link":
39
+ {
40
+ "label": "Read more",
41
+ "href": "/services/lawn-maintenance",
42
+ },
43
+ },
44
+ {
45
+ "title": "{Seasonal cleanup}",
46
+ "description": "{One line on the spring and autumn clear-down.}",
47
+ "link":
48
+ {
49
+ "label": "Read more",
50
+ "href": "/services/seasonal-cleanup",
51
+ },
52
+ },
53
+ {
54
+ "title": "{Landscape design}",
55
+ "description": "{One line on the design-and-plant job, and what a customer ends up with.}",
56
+ "link":
57
+ {
58
+ "label": "Read more",
59
+ "href": "/services/landscape-design",
60
+ },
61
+ },
62
+ ],
63
+ },
64
+ },
65
+ {
66
+ "id": "closing",
67
+ "type": "cta",
68
+ "data":
69
+ {
70
+ "variant": "minimal",
71
+ "headline": "Ready for a tidier yard?",
72
+ "description": "{One line inviting the reader to pick a time rather than fill in a form.}",
73
+ "primaryCta": { "label": "Book a visit →", "href": "/meet" },
74
+ "secondaryCta":
75
+ {
76
+ "label": "Ask a question",
77
+ "href": "/contact",
78
+ "variant": "outline",
79
+ },
80
+ },
81
+ },
82
+ ]
83
+ ---
84
+
85
+ Placeholder copy. Every headline, every line of body copy and every price on this site is a placeholder — replace them before you launch.
@@ -0,0 +1,40 @@
1
+ ---
2
+ type: "Service"
3
+ slug: "landscape-design"
4
+ title: "{Landscape design}"
5
+ description: "{One line on what this job is and who it suits. Replace before you launch.}"
6
+ price: 1250
7
+ priceCurrency: "USD"
8
+ provider:
9
+ name: "{Your Company}"
10
+ schema:
11
+ serviceType: "{Landscape design}"
12
+ areaServed: "{Your service area}"
13
+ ---
14
+
15
+ # \{Landscape design\}
16
+
17
+ \{Open with the situation a reader is in when they come looking for this. Two or
18
+ three sentences, no more — the detail belongs under the headings below.\}
19
+
20
+ ## What it covers
21
+
22
+ - \{The first thing you actually do\}
23
+ - \{The second thing you actually do\}
24
+ - \{The third thing you actually do\}
25
+
26
+ ## How it runs
27
+
28
+ \{One paragraph on the shape of the visit: how it is scheduled, how long it
29
+ takes, who turns up, and what you need from the customer beforehand.\}
30
+
31
+ ## What you end up with
32
+
33
+ \{One paragraph on the result. Be concrete — describe the yard when the crew
34
+ drives away.\}
35
+
36
+ ## What it costs
37
+
38
+ \{The price in this page's frontmatter is a PLACEHOLDER. It is what the site
39
+ publishes as a schema.org `Offer`, so an agent reading this page quotes it —
40
+ replace it with your real number before you launch.\}
@@ -0,0 +1,40 @@
1
+ ---
2
+ type: "Service"
3
+ slug: "lawn-maintenance"
4
+ title: "{Lawn maintenance}"
5
+ description: "{One line on what this job is and who it suits. Replace before you launch.}"
6
+ price: 149
7
+ priceCurrency: "USD"
8
+ provider:
9
+ name: "{Your Company}"
10
+ schema:
11
+ serviceType: "{Lawn maintenance}"
12
+ areaServed: "{Your service area}"
13
+ ---
14
+
15
+ # \{Lawn maintenance\}
16
+
17
+ \{Open with the situation a reader is in when they come looking for this. Two or
18
+ three sentences, no more — the detail belongs under the headings below.\}
19
+
20
+ ## What it covers
21
+
22
+ - \{The first thing you actually do\}
23
+ - \{The second thing you actually do\}
24
+ - \{The third thing you actually do\}
25
+
26
+ ## How it runs
27
+
28
+ \{One paragraph on the shape of the visit: how it is scheduled, how long it
29
+ takes, who turns up, and what you need from the customer beforehand.\}
30
+
31
+ ## What you end up with
32
+
33
+ \{One paragraph on the result. Be concrete — describe the yard when the crew
34
+ drives away.\}
35
+
36
+ ## What it costs
37
+
38
+ \{The price in this page's frontmatter is a PLACEHOLDER. It is what the site
39
+ publishes as a schema.org `Offer`, so an agent reading this page quotes it —
40
+ replace it with your real number before you launch.\}
@@ -0,0 +1,40 @@
1
+ ---
2
+ type: "Service"
3
+ slug: "seasonal-cleanup"
4
+ title: "{Seasonal cleanup}"
5
+ description: "{One line on what this job is and who it suits. Replace before you launch.}"
6
+ price: 289
7
+ priceCurrency: "USD"
8
+ provider:
9
+ name: "{Your Company}"
10
+ schema:
11
+ serviceType: "{Seasonal cleanup}"
12
+ areaServed: "{Your service area}"
13
+ ---
14
+
15
+ # \{Seasonal cleanup\}
16
+
17
+ \{Open with the situation a reader is in when they come looking for this. Two or
18
+ three sentences, no more — the detail belongs under the headings below.\}
19
+
20
+ ## What it covers
21
+
22
+ - \{The first thing you actually do\}
23
+ - \{The second thing you actually do\}
24
+ - \{The third thing you actually do\}
25
+
26
+ ## How it runs
27
+
28
+ \{One paragraph on the shape of the visit: how it is scheduled, how long it
29
+ takes, who turns up, and what you need from the customer beforehand.\}
30
+
31
+ ## What you end up with
32
+
33
+ \{One paragraph on the result. Be concrete — describe the yard when the crew
34
+ drives away.\}
35
+
36
+ ## What it costs
37
+
38
+ \{The price in this page's frontmatter is a PLACEHOLDER. It is what the site
39
+ publishes as a schema.org `Offer`, so an agent reading this page quotes it —
40
+ replace it with your real number before you launch.\}
@@ -0,0 +1,72 @@
1
+ ---
2
+ type: "ServicesList"
3
+ slug: "services"
4
+ title: "Services"
5
+ description: "The three jobs {your company} does, each with its own price. Placeholder copy — replace before you launch."
6
+ sections:
7
+ [
8
+ {
9
+ "id": "hero",
10
+ "type": "hero",
11
+ "data":
12
+ {
13
+ "variant": "centered",
14
+ "eyebrow": "Services",
15
+ "headline": "Three jobs, three prices",
16
+ "subheadline": "{One line on how to choose between them. Name the question a reader is actually asking.}",
17
+ },
18
+ },
19
+ {
20
+ "id": "jobs",
21
+ "type": "items",
22
+ "data":
23
+ {
24
+ "headline": "What we do",
25
+ "columns": 3,
26
+ "items":
27
+ [
28
+ {
29
+ "title": "{Lawn maintenance}",
30
+ "description": "{One line on the recurring visit — what it includes and how often it runs.}",
31
+ "link":
32
+ {
33
+ "label": "Read more",
34
+ "href": "/services/lawn-maintenance",
35
+ },
36
+ },
37
+ {
38
+ "title": "{Seasonal cleanup}",
39
+ "description": "{One line on the spring and autumn clear-down.}",
40
+ "link":
41
+ {
42
+ "label": "Read more",
43
+ "href": "/services/seasonal-cleanup",
44
+ },
45
+ },
46
+ {
47
+ "title": "{Landscape design}",
48
+ "description": "{One line on the design-and-plant job, and what a customer ends up with.}",
49
+ "link":
50
+ {
51
+ "label": "Read more",
52
+ "href": "/services/landscape-design",
53
+ },
54
+ },
55
+ ],
56
+ },
57
+ },
58
+ {
59
+ "id": "closing",
60
+ "type": "cta",
61
+ "data":
62
+ {
63
+ "variant": "minimal",
64
+ "headline": "Not sure which one?",
65
+ "description": "{One line inviting the reader to book the visit instead of guessing.}",
66
+ "primaryCta": { "label": "Book a visit →", "href": "/meet" },
67
+ },
68
+ },
69
+ ]
70
+ ---
71
+
72
+ Placeholder copy. The three detail pages under `content/en/Service/` carry the long form and the price; this page is the chooser.
@@ -0,0 +1,4 @@
1
+ {
2
+ "template": "simple-service",
3
+ "requires": ["marketing", "scheduling", "commerce"]
4
+ }
@@ -4,41 +4,32 @@ Skills are reusable Claude Code workflows scoped to this project. Each
4
4
  lives in its own subdirectory with a `SKILL.md` describing when to use
5
5
  it and how it works.
6
6
 
7
- The seven OSS skills below are the canonical AI Launch Kit workflows.
8
- Their status reflects what's available at the upstream
9
- <https://github.com/working-theory-labs/ai-launch-kit> repository today. Issue
10
- numbers in the table refer to that upstream repo (the
11
- `working-theory-labs/ai-launch-kit#N` form makes the link explicit), not your
12
- local project's issues.
13
-
14
- ## Status
15
-
16
- | Skill | Purpose | Status |
17
- | -------------------- | ------------------------------------------------------ | ---------------------------------------------------- |
18
- | `suggest-site-pages` | Generic page-type suggestions by category | coming soon — issue #361 (working-theory-labs/ai-launch-kit) |
19
- | `scaffold-page` | Generate a page with the appropriate schema.org type | coming soon — issue #362 (working-theory-labs/ai-launch-kit) |
20
- | `scaffold-auth` | Wire up an auth flow against `@working-theory/auth-client` | coming soon — issue #364 (working-theory-labs/ai-launch-kit) |
21
- | `audit-site` | Run `ailk audit` and explain the results | coming soon — issue #365 (working-theory-labs/ai-launch-kit) |
22
- | `add-schema` | Add Product / Service / FAQ schema to an existing page | coming soon — issue #366 (working-theory-labs/ai-launch-kit) |
23
- | `provision-config` | Generate `vercel.json` and environment templates | coming soon — issue #367 (working-theory-labs/ai-launch-kit) |
7
+ The six skills below ship with this project. Claude Code discovers
8
+ them automatically at session start — nothing to install or enable.
9
+
10
+ ## Available skills
11
+
12
+ | Skill | Purpose |
13
+ | ---------------------- | -------------------------------------------------------------------------------------------------------- |
14
+ | `suggest-site-pages` | Recommend a starter set of pages — each tagged with a schema.org type — from a free-text business description. |
15
+ | `scaffold-page` | Generate a new page: App Router route + MDX content stub + typed JSON-LD, in one confirm-before-write pass. |
16
+ | `add-schema` | Add or replace schema.org JSON-LD on a page that already exists. |
17
+ | `scaffold-auth` | Activate auth providers — magic-link via Resend, Google OAuth, GitHub OAuth. |
18
+ | `provision-config` | Emit deploy configuration — `vercel.json`, `.env.example`, and `RUNBOOK.md` — for a Vercel deploy. |
19
+ | `audit-site` | Run `ailk-audit --json` and explain the score and findings in plain language. |
24
20
 
25
21
  `scaffold-commerce` is delivered with the commerce module (`--modules commerce`, licensed).
26
22
 
27
- ## How a skill ships
23
+ ## How a skill works
28
24
 
29
- When a skill is built upstream, this directory will contain a
30
- subdirectory of the same name, each holding:
25
+ Each subdirectory holds:
31
26
 
32
27
  - `SKILL.md` — when to invoke, what it produces, what it requires.
33
28
  - Any supporting prompt fragments, code templates, or reference
34
29
  files the skill loads at runtime.
35
30
 
36
- Until then, the workflows the skills will perform can still be done
37
- by hand or by asking Claude Code directly.
38
-
39
31
  ## Adding your own
40
32
 
41
33
  To add a project-specific skill, create a folder here with a
42
34
  `SKILL.md` describing it. Claude Code will discover it automatically
43
- on session start. See the upstream `@working-theory/*` repository for examples
44
- of the format.
35
+ on session start. See the skills above for examples of the format.
@@ -23,13 +23,20 @@ STEALTH=true
23
23
  # hide the Blog link. Set BLOG_ENABLED=true and redeploy to launch the blog.
24
24
  # BLOG_ENABLED=true
25
25
 
26
- # ── Content backend ──────────────────────────────────────────────────────────
27
- # Default: mdx — reads from /content/*.mdx at the repo root.
28
- # Set to "pro-cms" to use the paid Pro CMS adapter (separate package, not
29
- # bundled with the OSS template).
30
- CONTENT_BACKEND=mdx
26
+ # ── Content adapter ──────────────────────────────────────────────────────────
27
+ # Which content adapter every consumer resolves: mdx (default, reads
28
+ # /content/*.mdx at the repo root) | projection (compiled manifest) | database
29
+ # (the Artifact store — needs a workspaceId).
30
+ CONTENT_ADAPTER=mdx
31
+ # CONTENT_BACKEND is deprecated — read for one release, then removed.
31
32
  # Override the content directory (default: <repo-root>/content). Useful for tests.
32
33
  # AILK_CONTENT_ROOT=
34
+ # Publish revalidation (#5851) — where apps/api POSTs on publish/unpublish so
35
+ # the site purges the affected tag, and the HMAC-SHA256 key it signs the body
36
+ # with. Required only under CONTENT_ADAPTER=database; with the URL unset the
37
+ # webhook is a logged no-op.
38
+ # CONTENT_REVALIDATE_URL=https://example.com/api/revalidate
39
+ # CONTENT_REVALIDATE_SECRET=
33
40
 
34
41
  # ── Database (optional in standalone mode) ───────────────────────────────────
35
42
  # DATABASE_URL=postgres://user:pass@host:5432/db
@@ -50,16 +57,51 @@ CONTENT_BACKEND=mdx
50
57
  # BETTER_AUTH_URL=http://localhost:3000
51
58
  # BETTER_AUTH_SECRET=
52
59
 
53
- # ── Single-tenant operator pin (multi-tenant module, apps/api) ───────────────
60
+ # ── Single-tenant operator pin (apps/api) ────────────────────────────────────
61
+ # REQUIRED on a build WITHOUT the multi-tenant module — for the submissions
62
+ # review dashboard AND for the `workspace` module's settings surface.
63
+ # OPTIONAL with the multi-tenant module.
64
+ #
54
65
  # On a single-tenant deployment (the default Workspace exists and is the ONLY
55
66
  # Workspace) the FIRST authenticated user to resolve a tenant context is
56
67
  # bound as the sole owner (TOFU — trust on first use); every subsequent
57
- # caller is denied. AILK_OPERATOR_EMAIL is OPTIONAL and pins that binding to
58
- # one email address instead of "whoever logs in first" — set it when you
59
- # want to guarantee only a specific operator account can ever become owner.
60
- # Case-insensitive, trimmed. Leave unset for pure TOFU.
68
+ # caller is denied. AILK_OPERATOR_EMAIL pins that binding to one email
69
+ # address instead of "whoever logs in first". Case-insensitive, trimmed.
70
+ #
71
+ # WITHOUT the multi-tenant module it is MANDATORY and unset fails CLOSED:
72
+ # the review routes (/v1/waitlist-experiments/*, the tenant-scoped
73
+ # /v1/project-listings/*) answer 403 to everyone, including you. That is
74
+ # deliberate. Those routes can widen to an unfiltered, every-site read for an
75
+ # owner of the default Organization, so an unpinned deployment must not seat
76
+ # whoever authenticates first — on a site with public sign-ups that is not
77
+ # necessarily you. The pinned account's email must also be VERIFIED.
78
+ #
79
+ # The same MANDATORY-and-fail-closed rule covers a `--modules workspace`
80
+ # deployment (#5371, #5515 item 1). The Pro workspace module registers
81
+ # /v1/workspaces/:workspaceId/{theme,identity,seo,general,members} behind the
82
+ # same guard, so on a workspace-only build the module's Admin pages (/admin)
83
+ # answer 403 to everyone until this is set — and, because the guard refuses
84
+ # BEFORE resolving, the first account to load the settings page cannot bind
85
+ # ITSELF as the sole owner off a plain GET. Set this before you hand the site
86
+ # to its owner.
87
+ #
88
+ # If your own dashboard returns 403, this variable is the first thing to
89
+ # check. With the multi-tenant module present, resolution comes from the
90
+ # session's active workspace and this stays optional, exactly as before.
61
91
  # AILK_OPERATOR_EMAIL=
62
92
  #
93
+ # ── Site id (apps/api, apps/web) ─────────────────────────────────────────────
94
+ # The scope captured rows are stamped with. Lead, WaitlistExperiment and
95
+ # ProjectListing carry `siteId`, which defaults to the literal "default"
96
+ # (apps/api/src/lib/site.ts), while tenancy scopes reads by WORKSPACE id.
97
+ # A single-tenant deployment should set this to the default workspace
98
+ # sentinel so the two agree:
99
+ # AILK_SITE_ID=wksp_00000000-0000-7000-8000-000000000001
100
+ #
101
+ # Leaving them disagreeing is why a correctly pinned owner can still open the
102
+ # review dashboard and see nothing: the rows exist, but under a different
103
+ # scope key than the one their session resolves.
104
+ #
63
105
  # Belt-and-suspenders: the owner-pin denies any non-operator account at
64
106
  # tenant resolution regardless, but for a single-tenant deployment you should
65
107
  # also disable open sign-up / configure an OAuth allowlist on your identity
@@ -98,6 +140,45 @@ CONTENT_BACKEND=mdx
98
140
  # default.
99
141
  # RESEND_AUDIENCE_ID=
100
142
  #
143
+ # Request-and-confirm (#5970) — the callback request a site owner confirms by
144
+ # an emailed link, which mints a Stripe Payment Link for the customer to pay
145
+ # on. Off by default: with the flag unset the callback route behaves exactly as
146
+ # it always has.
147
+ #
148
+ # Set to "true" to turn it on. Anything else (including absent) is off, and TO,
149
+ # FROM and AILK_PUBLIC_API_URL must ALSO resolve or the path stays off — a flag
150
+ # with no recipient would write a credential nobody is sent.
151
+ #
152
+ # SINGLE-TENANT ONLY. On a build carrying the multi-tenant module this flag is
153
+ # ignored and the callback route behaves exactly as it does with the feature
154
+ # off. Every value here is process-wide, as is STRIPE_SECRET_KEY, so on a
155
+ # multi-tenant deployment one tenant's customer would pay into the
156
+ # deployment's own Stripe account. Lighting it up there means resolving these
157
+ # per site, which is a separate piece of work.
158
+ # AILK_REQUEST_CONFIRM_ENABLED=
159
+ #
160
+ # Where the confirm link is sent — the site owner's own address. Optional:
161
+ # falls back to AILK_LEAD_NOTIFICATION_TO when unset. This message SUPERSEDES
162
+ # the generic lead notification for a callback, so the owner still receives
163
+ # exactly one email; it just carries more (the request's details, plus the
164
+ # link).
165
+ # AILK_REQUEST_CONFIRM_TO=
166
+ #
167
+ # The verified sender for both the owner's confirm email and the customer's
168
+ # payment-link email. Optional — falls back to AILK_LEAD_NOTIFICATION_FROM.
169
+ # AILK_REQUEST_CONFIRM_FROM=
170
+ #
171
+ # The confirm form's default currency, lowercase ISO-4217. Optional; defaults
172
+ # to usd.
173
+ # AILK_REQUEST_CONFIRM_CURRENCY=
174
+ #
175
+ # The most the confirm form will price a job at, in MINOR units (cents).
176
+ # Optional; defaults to 1000000 — ten thousand dollars at two decimal places.
177
+ # High enough not to obstruct a real job, low enough that a typo with three
178
+ # extra zeroes is refused rather than charged. A value that does not parse as a
179
+ # positive integer falls back to the default rather than becoming unbounded.
180
+ # AILK_REQUEST_CONFIRM_MAX_MINOR=
181
+ #
101
182
  # The public base URL this API is reachable at, e.g. https://api.example.com
102
183
  # (no trailing slash). This is the API's OWN origin — distinct from
103
184
  # FRONTEND_URL (the site the browser loads) and from `_site.mdx`'s `baseUrl`
@@ -112,6 +193,11 @@ CONTENT_BACKEND=mdx
112
193
  # 2. The OpenAPI `servers` block (#5306). Unset degrades to a single
113
194
  # document-relative server (`/`), which an agent resolves against the
114
195
  # origin it fetched the spec from — correct, just less explicit.
196
+ # 3. The request-and-confirm link (#5970):
197
+ # `${AILK_PUBLIC_API_URL}/v1/requests/:id/confirm?token=…`. The confirm
198
+ # route is on this API, so this is the right base and no second
199
+ # base-URL variable exists. Unset means the confirm email is skipped
200
+ # (logged, with the row still written and the 201 unchanged).
115
201
  # AILK_PUBLIC_API_URL=
116
202
  #
117
203
  # The apps/api origin @working-theory/api-client calls from
@@ -288,12 +374,16 @@ CONTENT_BACKEND=mdx
288
374
  # booking page. Full notes in apps/api/.env.example.
289
375
  # CAL_API_KEY=cal_live_xxx
290
376
  # CAL_API_BASE_URL=https://api.cal.com
377
+ # HMAC-SHA256 key POST /v1/webhooks/calcom verifies the x-cal-signature-256
378
+ # header against (#6085). Unset makes the receiver answer 503 and accept
379
+ # nothing — the same fail-closed posture an unset STRIPE_WEBHOOK_SECRET has.
380
+ # CAL_WEBHOOK_SECRET=
291
381
  # SCHEDULING_PUBLIC_BASE_URL=https://cal.com
292
382
  # SCHEDULING_PROVIDER=cal
293
383
  #
294
- # Which event the /schedule page books, as "<owner>/<event-slug>" (the path of
384
+ # Which event the /meet page books, as "<owner>/<event-slug>" (the path of
295
385
  # the provider's own public booking page). Read server-side by apps/web; unset
296
- # means the /schedule route 404s, exactly as if the scheduling module were not
386
+ # means the /meet route 404s, exactly as if the scheduling module were not
297
387
  # installed. Deliberately NOT a NEXT_PUBLIC_ variable — the whole scheduling
298
388
  # config surface is server-read.
299
389
  # SCHEDULING_CAL_LINK=owner/event-slug
@@ -0,0 +1,48 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ jobs:
7
+ ci:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+
12
+ - uses: pnpm/action-setup@v4
13
+
14
+ # A fresh scaffold ships no pnpm-lock.yaml — it is generated by the
15
+ # customer's own first `pnpm install`. actions/setup-node's built-in
16
+ # pnpm cache globs for cache-dependency-path and errors the step
17
+ # outright when nothing matches, so a PR opened before that first
18
+ # install would fail here before `pnpm install` below even runs. This
19
+ # placeholder only stands in for the glob; `pnpm install` still
20
+ # generates (or refreshes) the real lockfile every run.
21
+ - run: test -f pnpm-lock.yaml || touch pnpm-lock.yaml
22
+
23
+ - uses: actions/setup-node@v4
24
+ with:
25
+ node-version: 20
26
+ cache: pnpm
27
+ cache-dependency-path: pnpm-lock.yaml
28
+
29
+ # Not --frozen-lockfile: the scaffold ships no pnpm-lock.yaml (it is
30
+ # generated fresh by the customer's own first `pnpm install`, and the
31
+ # placeholder step above is a cache-key stand-in, not a real lockfile),
32
+ # so a --frozen install would fail outright on any PR opened before a
33
+ # real lockfile has been committed.
34
+ - run: pnpm install
35
+
36
+ # Prisma's generated client (database/generated/) is a build artifact,
37
+ # not part of the scaffold — type-check/build/test all resolve
38
+ # `@working-theory/database`'s generated types, and `prisma generate` needs
39
+ # no DATABASE_URL (it reads only the schema file, no live DB).
40
+ - run: pnpm db:generate
41
+
42
+ - run: pnpm type-check
43
+
44
+ - run: pnpm lint
45
+
46
+ - run: pnpm test
47
+
48
+ - run: pnpm build
@@ -103,7 +103,9 @@ If you need to override a section component, swap its registration in the sectio
103
103
 
104
104
  ## License & contributing
105
105
 
106
- Your project — `{{PROJECT_NAME}}`, owned by {{COMPANY_NAME}} ({{COMPANY_DOMAIN}}) — is yours. Pick whatever license suits you.
106
+ This is your code — `{{PROJECT_NAME}}`, owned by {{COMPANY_NAME}} ({{COMPANY_DOMAIN}}). The root `package.json`'s `license` field ships set to `UNLICENSED` as a neutral placeholder; it's yours to change to whatever license suits your project (or to remove entirely if the repo is private).
107
+
108
+ The `LICENSE` files under `apps/*/` and `database/` are the exception — they stay **Apache 2.0** because those directories are snapshots of `@working-theory/*` packages' own source, not code you authored.
107
109
 
108
110
  The AI Launch Kit framework upstream is **Apache 2.0** — see <https://github.com/working-theory-labs/ai-launch-kit/blob/main/LICENSE>. Contributions are welcome at the upstream repo; start with the [contributing guide](https://github.com/working-theory-labs/ai-launch-kit/blob/main/CONTRIBUTING.md).
109
111
 
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "fallback-1789916251590-037e9005",
3
+ "siteId": "site_1",
4
+ "source": "callback",
5
+ "email": "",
6
+ "payload": {},
7
+ "createdAt": "2026-09-20T14:57:31.552Z"
8
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "fallback-1789916253842-b52659e9",
3
+ "siteId": "wksp_00000000-0000-7000-8000-000000000001",
4
+ "source": "flow:get-a-quote",
5
+ "email": "abandoner@example.com",
6
+ "payload": {
7
+ "email": "abandoner@example.com",
8
+ "flowSlug": "get-a-quote",
9
+ "locale": "en"
10
+ },
11
+ "createdAt": "2026-09-20T14:57:33.840Z"
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "fallback-1789916253845-6b266f8c",
3
+ "siteId": "default",
4
+ "source": "flow:get-a-quote",
5
+ "email": "abandoner@example.com",
6
+ "payload": {
7
+ "email": "abandoner@example.com",
8
+ "flowSlug": "get-a-quote",
9
+ "locale": "en"
10
+ },
11
+ "createdAt": "2026-09-20T14:57:33.844Z"
12
+ }