create-ailk 0.1.0 → 0.2.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 (620) hide show
  1. package/README.md +124 -3
  2. package/component-catalog.md +456 -0
  3. package/dist/cli.js +92 -16
  4. package/dist/component-catalog.d.ts +11 -0
  5. package/dist/component-catalog.js +39 -0
  6. package/dist/copy.d.ts +7 -0
  7. package/dist/copy.js +24 -0
  8. package/dist/derive-architecture.d.ts +13 -0
  9. package/dist/derive-architecture.js +238 -0
  10. package/dist/index.d.ts +7 -2
  11. package/dist/index.js +19 -2
  12. package/dist/lib/extract-module-bundle.d.ts +16 -0
  13. package/dist/lib/extract-module-bundle.js +184 -0
  14. package/dist/lib/fetch-module.d.ts +55 -0
  15. package/dist/lib/fetch-module.js +125 -0
  16. package/dist/lib/module-license-gate.d.ts +48 -0
  17. package/dist/lib/module-license-gate.js +67 -0
  18. package/dist/lib/module-tier.d.ts +35 -0
  19. package/dist/lib/module-tier.js +37 -0
  20. package/dist/module-architecture.d.ts +175 -0
  21. package/dist/module-architecture.js +663 -0
  22. package/dist/parse-args.d.ts +47 -1
  23. package/dist/parse-args.js +143 -2
  24. package/dist/programmatic.d.ts +160 -3
  25. package/dist/programmatic.js +196 -7
  26. package/dist/surfaces.d.ts +211 -0
  27. package/dist/surfaces.js +532 -0
  28. package/dist/sync-routes.d.ts +92 -0
  29. package/dist/sync-routes.js +350 -0
  30. package/package.json +12 -5
  31. package/templates/.claude/rules/architecture.md +6 -2
  32. package/templates/.claude/skills/README.md +9 -9
  33. package/templates/.claude/skills/add-schema/SKILL.md +14 -7
  34. package/templates/.claude/skills/add-schema/references/schema-types.md +109 -6
  35. package/templates/.claude/skills/provision-config/SKILL.md +1 -1
  36. package/templates/.claude/skills/scaffold-commerce/SKILL.md +498 -1
  37. package/templates/.claude/skills/scaffold-commerce/templates/checkout-route.template.ts +370 -0
  38. package/templates/.claude/skills/scaffold-commerce/templates/invoice-route.template.ts +376 -0
  39. package/templates/.claude/skills/scaffold-commerce/templates/payment-link-route.template.ts +471 -0
  40. package/templates/.claude/skills/scaffold-commerce/templates/portal-route.template.ts +365 -0
  41. package/templates/.claude/skills/scaffold-commerce/templates/stripe-config.template.ts +60 -0
  42. package/templates/.claude/skills/scaffold-commerce/templates/subscription-route.template.ts +446 -0
  43. package/templates/.claude/skills/suggest-site-pages/references/categories.md +4 -4
  44. package/templates/.env.example +126 -2
  45. package/templates/CLAUDE.md +11 -5
  46. package/templates/README.md +1 -1
  47. package/templates/apps/api/.env.example +38 -0
  48. package/templates/apps/api/CLAUDE.md +78 -1
  49. package/templates/apps/api/LICENSE +201 -0
  50. package/templates/apps/api/api/index.ts +6 -141
  51. package/templates/apps/api/jest.config.cjs +16 -0
  52. package/templates/apps/api/package.json +22 -6
  53. package/templates/apps/api/src/__tests__/module-exclusion.test.ts +141 -0
  54. package/templates/apps/api/src/__tests__/server.test.ts +46 -0
  55. package/templates/apps/api/src/__tests__/vercel-handler.test.ts +211 -0
  56. package/templates/apps/api/src/bin/abandon-sweep.ts +42 -0
  57. package/templates/apps/api/src/bin/deliverable-resend.ts +144 -0
  58. package/templates/apps/api/src/bin/deliverable-upload.ts +114 -0
  59. package/templates/apps/api/src/bin/followup-sweep.ts +44 -0
  60. package/templates/apps/api/src/bin/listing-csv-sweep.ts +46 -0
  61. package/templates/apps/api/src/bin/seed-presets.ts +58 -0
  62. package/templates/apps/api/src/bin/seed-waitlist-experiments.ts +104 -0
  63. package/templates/apps/api/src/bin/session-retention-sweep.ts +46 -0
  64. package/templates/apps/api/src/cli.ts +5 -11
  65. package/templates/apps/api/src/config/index.ts +35 -0
  66. package/templates/apps/api/src/config/modules.ts +43 -0
  67. package/templates/apps/api/src/lib/__mocks__/prisma-client.js +11 -0
  68. package/templates/apps/api/src/lib/__mocks__/prisma.ts +241 -0
  69. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +2 -2
  70. package/templates/apps/api/src/lib/site.ts +16 -0
  71. package/templates/apps/api/src/lib/stripe.ts +22 -0
  72. package/templates/apps/api/src/lib/tenant-db.ts +225 -0
  73. package/templates/apps/api/src/lib/ws-token.ts +91 -0
  74. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +7 -1
  75. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +7 -1
  76. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +91 -4
  77. package/templates/apps/api/src/middleware/auth.ts +43 -8
  78. package/templates/apps/api/src/middleware/rate-limit.ts +78 -3
  79. package/templates/apps/api/src/middleware/tenant.ts +99 -0
  80. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +92 -0
  81. package/templates/apps/api/src/openapi/spec.ts +312 -3
  82. package/templates/apps/api/src/routes/aeo/__tests__/index.test.ts +175 -0
  83. package/templates/apps/api/src/routes/aeo/index.ts +107 -0
  84. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +5 -2
  85. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +22 -3
  86. package/templates/apps/api/src/routes/auth/tokens.ts +13 -1
  87. package/templates/apps/api/src/routes/billing/__tests__/portal.test.ts +450 -0
  88. package/templates/apps/api/src/routes/billing/__tests__/read.test.ts +262 -0
  89. package/templates/apps/api/src/routes/billing/__tests__/usage.test.ts +436 -0
  90. package/templates/apps/api/src/routes/billing/index.ts +36 -0
  91. package/templates/apps/api/src/routes/billing/portal.ts +182 -0
  92. package/templates/apps/api/src/routes/billing/read.ts +75 -0
  93. package/templates/apps/api/src/routes/billing/usage.ts +153 -0
  94. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +99 -0
  95. package/templates/apps/api/src/routes/checkout/sessions.ts +20 -8
  96. package/templates/apps/api/src/routes/content/create.ts +1 -0
  97. package/templates/apps/api/src/routes/content/delete.ts +1 -0
  98. package/templates/apps/api/src/routes/content/index.ts +42 -6
  99. package/templates/apps/api/src/routes/content/update.ts +1 -0
  100. package/templates/apps/api/src/routes/deliverables/__tests__/index.test.ts +393 -0
  101. package/templates/apps/api/src/routes/deliverables/index.ts +200 -0
  102. package/templates/apps/api/src/routes/flow-checkouts/__tests__/index.test.ts +443 -0
  103. package/templates/apps/api/src/routes/flow-checkouts/index.ts +82 -0
  104. package/templates/apps/api/src/routes/flows/README.md +147 -0
  105. package/templates/apps/api/src/routes/flows/__tests__/index.test.ts +752 -0
  106. package/templates/apps/api/src/routes/flows/__tests__/recommender.test.ts +671 -0
  107. package/templates/apps/api/src/routes/flows/index.ts +202 -0
  108. package/templates/apps/api/src/routes/flows/recommender.ts +443 -0
  109. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +438 -31
  110. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +10 -10
  111. package/templates/apps/api/src/routes/leads/index.ts +43 -9
  112. package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +558 -0
  113. package/templates/apps/api/src/routes/project-listings/__tests__/copy-edit.test.ts +815 -0
  114. package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +869 -0
  115. package/templates/apps/api/src/routes/project-listings/__tests__/me-route-precedence.test.ts +221 -0
  116. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +468 -0
  117. package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +424 -0
  118. package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +707 -0
  119. package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +375 -0
  120. package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +467 -0
  121. package/templates/apps/api/src/routes/project-listings/__tests__/tenant-isolation.test.ts +566 -0
  122. package/templates/apps/api/src/routes/project-listings/get.ts +70 -0
  123. package/templates/apps/api/src/routes/project-listings/index.ts +120 -0
  124. package/templates/apps/api/src/routes/project-listings/list.ts +47 -0
  125. package/templates/apps/api/src/routes/project-listings/me.ts +76 -0
  126. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +222 -0
  127. package/templates/apps/api/src/routes/project-listings/patch-draft.ts +97 -0
  128. package/templates/apps/api/src/routes/project-listings/patch.ts +136 -0
  129. package/templates/apps/api/src/routes/project-listings/public.ts +52 -0
  130. package/templates/apps/api/src/routes/project-listings/respond.ts +37 -0
  131. package/templates/apps/api/src/routes/project-listings/resume-token.ts +22 -0
  132. package/templates/apps/api/src/routes/project-listings/start.ts +106 -0
  133. package/templates/apps/api/src/routes/project-listings/submit.ts +122 -0
  134. package/templates/apps/api/src/routes/schedule/__tests__/index.test.ts +490 -0
  135. package/templates/apps/api/src/routes/schedule/index.ts +249 -0
  136. package/templates/apps/api/src/routes/slack/__tests__/actions.test.ts +385 -0
  137. package/templates/apps/api/src/routes/slack/actions.ts +177 -0
  138. package/templates/apps/api/src/routes/slack/index.ts +38 -0
  139. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +16 -6
  140. package/templates/apps/api/src/routes/test/auth/session.ts +8 -6
  141. package/templates/apps/api/src/routes/waitlist-experiments/__tests__/tenant-isolation.test.ts +577 -0
  142. package/templates/apps/api/src/routes/waitlist-experiments/comparison.ts +78 -0
  143. package/templates/apps/api/src/routes/waitlist-experiments/index.ts +41 -0
  144. package/templates/apps/api/src/routes/waitlist-experiments/list.ts +64 -0
  145. package/templates/apps/api/src/routes/waitlist-experiments/respond.ts +42 -0
  146. package/templates/apps/api/src/routes/waitlist-experiments/signup.ts +84 -0
  147. package/templates/apps/api/src/routes/waitlist-experiments/signups.ts +119 -0
  148. package/templates/apps/api/src/routes/waitlist-signups/__tests__/index.test.ts +238 -0
  149. package/templates/apps/api/src/routes/waitlist-signups/index.ts +101 -0
  150. package/templates/apps/api/src/routes/webhooks/README.md +35 -12
  151. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +315 -0
  152. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +270 -0
  153. package/templates/apps/api/src/routes/webhooks/stripe.ts +248 -20
  154. package/templates/apps/api/src/routes/workspaces/__tests__/config-tenant-isolation.test.ts +356 -0
  155. package/templates/apps/api/src/routes/workspaces/__tests__/tenant-isolation.test.ts +671 -0
  156. package/templates/apps/api/src/routes/workspaces/config.ts +125 -0
  157. package/templates/apps/api/src/routes/workspaces/index.ts +194 -0
  158. package/templates/apps/api/src/routes/workspaces/sessions.ts +218 -0
  159. package/templates/apps/api/src/server.ts +307 -7
  160. package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +489 -0
  161. package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +475 -0
  162. package/templates/apps/api/src/services/__tests__/answer-distributions.test.ts +132 -0
  163. package/templates/apps/api/src/services/__tests__/consent-migration.test.ts +65 -0
  164. package/templates/apps/api/src/services/__tests__/consent.test.ts +282 -0
  165. package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +523 -0
  166. package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +359 -0
  167. package/templates/apps/api/src/services/__tests__/entitlements.test.ts +142 -0
  168. package/templates/apps/api/src/services/__tests__/flow-aggregate.test.ts +425 -0
  169. package/templates/apps/api/src/services/__tests__/flow-engine.test.ts +2840 -0
  170. package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +393 -0
  171. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +8 -8
  172. package/templates/apps/api/src/services/__tests__/listing-csv-sweep.test.ts +560 -0
  173. package/templates/apps/api/src/services/__tests__/listing-promotion.test.ts +684 -0
  174. package/templates/apps/api/src/services/__tests__/playbook-compile.test.ts +406 -0
  175. package/templates/apps/api/src/services/__tests__/playbook-render.test.ts +290 -0
  176. package/templates/apps/api/src/services/__tests__/project-listing-decision.test.ts +736 -0
  177. package/templates/apps/api/src/services/__tests__/project-listing-flow.test.ts +475 -0
  178. package/templates/apps/api/src/services/__tests__/project-listing-issue.test.ts +340 -0
  179. package/templates/apps/api/src/services/__tests__/recommender-capture.test.ts +983 -0
  180. package/templates/apps/api/src/services/__tests__/slack-notify.test.ts +278 -0
  181. package/templates/apps/api/src/services/__tests__/tenant-context-cascade.test.ts +71 -0
  182. package/templates/apps/api/src/services/__tests__/tenant-context.test.ts +379 -0
  183. package/templates/apps/api/src/services/__tests__/usage-aggregation.test.ts +941 -0
  184. package/templates/apps/api/src/services/__tests__/usage-credits.test.ts +588 -0
  185. package/templates/apps/api/src/services/__tests__/usage-metering.test.ts +768 -0
  186. package/templates/apps/api/src/services/__tests__/waitlist-dashboard.test.ts +1314 -0
  187. package/templates/apps/api/src/services/__tests__/waitlist-experiments.test.ts +341 -0
  188. package/templates/apps/api/src/services/__tests__/waitlist-followup.test.ts +567 -0
  189. package/templates/apps/api/src/services/__tests__/waitlist-scoring.test.ts +474 -0
  190. package/templates/apps/api/src/services/__tests__/waitlist-signups.test.ts +354 -0
  191. package/templates/apps/api/src/services/abandon-email.ts +307 -0
  192. package/templates/apps/api/src/services/aeo-score.ts +288 -0
  193. package/templates/apps/api/src/services/answer-distributions.ts +138 -0
  194. package/templates/apps/api/src/services/consent.ts +236 -0
  195. package/templates/apps/api/src/services/deliverable-fulfillment.ts +523 -0
  196. package/templates/apps/api/src/services/entitlements.ts +102 -0
  197. package/templates/apps/api/src/services/flow-aggregate.ts +232 -0
  198. package/templates/apps/api/src/services/flow-checkouts.ts +123 -0
  199. package/templates/apps/api/src/services/flow-engine.ts +1296 -0
  200. package/templates/apps/api/src/services/lead-promotion.ts +176 -0
  201. package/templates/apps/api/src/services/lead-routing.ts +3 -3
  202. package/templates/apps/api/src/services/listing-config.ts +102 -0
  203. package/templates/apps/api/src/services/listing-csv-sweep.ts +455 -0
  204. package/templates/apps/api/src/services/listing-promotion.ts +342 -0
  205. package/templates/apps/api/src/services/playbook-compile.ts +398 -0
  206. package/templates/apps/api/src/services/playbook-render.ts +263 -0
  207. package/templates/apps/api/src/services/project-listing-decision.ts +510 -0
  208. package/templates/apps/api/src/services/project-listing-flow.ts +426 -0
  209. package/templates/apps/api/src/services/project-listing-issue.ts +251 -0
  210. package/templates/apps/api/src/services/project-listings.ts +1472 -0
  211. package/templates/apps/api/src/services/recommender-capture.ts +835 -0
  212. package/templates/apps/api/src/services/scheduling/cal-provider.ts +392 -0
  213. package/templates/apps/api/src/services/scheduling/index.ts +63 -0
  214. package/templates/apps/api/src/services/scheduling/types.ts +88 -0
  215. package/templates/apps/api/src/services/slack-notify.ts +240 -0
  216. package/templates/apps/api/src/services/tenant-context.ts +451 -0
  217. package/templates/apps/api/src/services/usage-aggregation.ts +516 -0
  218. package/templates/apps/api/src/services/usage-credits.ts +340 -0
  219. package/templates/apps/api/src/services/usage-metering.ts +699 -0
  220. package/templates/apps/api/src/services/waitlist-dashboard.ts +947 -0
  221. package/templates/apps/api/src/services/waitlist-experiments.ts +213 -0
  222. package/templates/apps/api/src/services/waitlist-followup.ts +486 -0
  223. package/templates/apps/api/src/services/waitlist-scoring.ts +166 -0
  224. package/templates/apps/api/src/services/waitlist-signups.ts +165 -0
  225. package/templates/apps/api/src/vercel-handler.ts +165 -0
  226. package/templates/apps/api/tsconfig.json +0 -12
  227. package/templates/apps/mcp/CLAUDE.md +19 -9
  228. package/templates/apps/mcp/LICENSE +201 -0
  229. package/templates/apps/mcp/__tests__/create_page.test.ts +1 -0
  230. package/templates/apps/mcp/__tests__/delete_page.test.ts +1 -0
  231. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +105 -0
  232. package/templates/apps/mcp/__tests__/parity.test.ts +70 -6
  233. package/templates/apps/mcp/__tests__/request_callback.test.ts +4 -4
  234. package/templates/apps/mcp/__tests__/schedule_tools.test.ts +242 -0
  235. package/templates/apps/mcp/__tests__/submit_lead.test.ts +4 -4
  236. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +4 -4
  237. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +47 -0
  238. package/templates/apps/mcp/__tests__/update_page.test.ts +1 -0
  239. package/templates/apps/mcp/package.json +6 -4
  240. package/templates/apps/mcp/src/config/modules.ts +37 -0
  241. package/templates/apps/mcp/src/server.ts +109 -18
  242. package/templates/apps/mcp/src/tools/capture_lead.ts +1 -1
  243. package/templates/apps/mcp/src/tools/create_booking.ts +58 -0
  244. package/templates/apps/mcp/src/tools/create_page.ts +1 -0
  245. package/templates/apps/mcp/src/tools/delete_page.ts +1 -0
  246. package/templates/apps/mcp/src/tools/get_event_meta.ts +55 -0
  247. package/templates/apps/mcp/src/tools/get_flow.ts +61 -0
  248. package/templates/apps/mcp/src/tools/index.ts +25 -0
  249. package/templates/apps/mcp/src/tools/list_availability.ts +67 -0
  250. package/templates/apps/mcp/src/tools/purchase.ts +3 -0
  251. package/templates/apps/mcp/src/tools/submit_flow_step.ts +83 -0
  252. package/templates/apps/mcp/src/tools/update_page.ts +1 -0
  253. package/templates/apps/mcp/tsconfig.json +1 -9
  254. package/templates/apps/web/.env.example +44 -0
  255. package/templates/apps/web/CLAUDE.md +28 -0
  256. package/templates/apps/web/LICENSE +201 -0
  257. package/templates/apps/web/__tests__/__mocks__/code-highlight.jest-stub.ts +24 -0
  258. package/templates/apps/web/__tests__/__mocks__/next-intl-server.ts +33 -0
  259. package/templates/apps/web/__tests__/__mocks__/next-intl.ts +18 -0
  260. package/templates/apps/web/__tests__/__mocks__/server-only.ts +13 -0
  261. package/templates/apps/web/__tests__/__mocks__/style-mock.js +4 -0
  262. package/templates/apps/web/__tests__/__mocks__/vercel-analytics-server.ts +9 -0
  263. package/templates/apps/web/__tests__/jest-support/import-meta-transformer.cjs +90 -0
  264. package/templates/apps/web/__tests__/setup.ts +22 -32
  265. package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +6 -3
  266. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +8 -2
  267. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +260 -0
  268. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +263 -0
  269. package/templates/apps/web/app/[locale]/(authed)/account/sign-out-button.tsx +39 -0
  270. package/templates/apps/web/app/[locale]/(authed)/layout.tsx +54 -0
  271. package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +96 -0
  272. package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/page.tsx +309 -0
  273. package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/signups/[leadId]/page.tsx +149 -0
  274. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/comparison.test.tsx +273 -0
  275. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/gate.test.tsx +172 -0
  276. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/list.test.tsx +171 -0
  277. package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/signup.test.tsx +179 -0
  278. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ExperimentsTable.tsx +116 -0
  279. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ForbiddenState.tsx +24 -0
  280. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/OfferFunnelTable.tsx +66 -0
  281. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/RollupTicker.tsx +61 -0
  282. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ScoreTrace.tsx +114 -0
  283. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx +139 -0
  284. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx +85 -0
  285. package/templates/apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx +67 -0
  286. package/templates/apps/web/app/[locale]/(authed)/waitlist/format.ts +111 -0
  287. package/templates/apps/web/app/[locale]/(authed)/waitlist/page.tsx +179 -0
  288. package/templates/apps/web/app/[locale]/about/page.tsx +10 -1
  289. package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +6 -1
  290. package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +9 -0
  291. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
  292. package/templates/apps/web/app/[locale]/careers/page.tsx +9 -1
  293. package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +9 -0
  294. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
  295. package/templates/apps/web/app/[locale]/case-studies/page.tsx +13 -1
  296. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +11 -1
  297. package/templates/apps/web/app/[locale]/clients/page.tsx +9 -1
  298. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +21 -1
  299. package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +188 -0
  300. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +242 -0
  301. package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +29 -0
  302. package/templates/apps/web/app/[locale]/contact/__tests__/intake-analytics.test.ts +51 -0
  303. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +39 -15
  304. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +21 -3
  305. package/templates/apps/web/app/[locale]/contact/intake-analytics.ts +49 -0
  306. package/templates/apps/web/app/[locale]/contact/intake-script.ts +66 -0
  307. package/templates/apps/web/app/[locale]/contact/page.tsx +14 -4
  308. package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +13 -1
  309. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
  310. package/templates/apps/web/app/[locale]/courses/page.tsx +9 -1
  311. package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +1 -0
  312. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +11 -1
  313. package/templates/apps/web/app/[locale]/downloads/page.tsx +13 -1
  314. package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +9 -0
  315. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +12 -2
  316. package/templates/apps/web/app/[locale]/events/page.tsx +9 -1
  317. package/templates/apps/web/app/[locale]/faq/page.tsx +10 -1
  318. package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +265 -0
  319. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +445 -0
  320. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +341 -0
  321. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/checkout.actions.test.ts +287 -0
  322. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +302 -0
  323. package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/two-route-tool.test.tsx +128 -0
  324. package/templates/apps/web/app/[locale]/flows/[slug]/checkout.actions.ts +254 -0
  325. package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +144 -0
  326. package/templates/apps/web/app/[locale]/flows/[slug]/page.tsx +108 -0
  327. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +532 -0
  328. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +121 -0
  329. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.checkout.test.tsx +457 -0
  330. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +396 -0
  331. package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +114 -0
  332. package/templates/apps/web/app/[locale]/flows/[slug]/start/page.tsx +52 -0
  333. package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +13 -1
  334. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
  335. package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +9 -0
  336. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
  337. package/templates/apps/web/app/[locale]/integrations/page.tsx +13 -1
  338. package/templates/apps/web/app/[locale]/launch-service/page.tsx +14 -1
  339. package/templates/apps/web/app/[locale]/layout.tsx +127 -16
  340. package/templates/apps/web/app/[locale]/page.tsx +10 -1
  341. package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +9 -0
  342. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
  343. package/templates/apps/web/app/[locale]/partners/page.tsx +9 -1
  344. package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +9 -0
  345. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
  346. package/templates/apps/web/app/[locale]/products/page.tsx +9 -1
  347. package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +13 -1
  348. package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +10 -0
  349. package/templates/apps/web/app/[locale]/projects/apply/ListingApplicationClient.tsx +110 -0
  350. package/templates/apps/web/app/[locale]/projects/apply/__tests__/ListingApplicationClient.test.tsx +96 -0
  351. package/templates/apps/web/app/[locale]/projects/page.tsx +13 -1
  352. package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +9 -0
  353. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +12 -2
  354. package/templates/apps/web/app/[locale]/resources/page.tsx +13 -1
  355. package/templates/apps/web/app/[locale]/schedule/__tests__/page.test.tsx +117 -0
  356. package/templates/apps/web/app/[locale]/schedule/confirmed/__tests__/page.test.tsx +96 -0
  357. package/templates/apps/web/app/[locale]/schedule/confirmed/page.tsx +92 -0
  358. package/templates/apps/web/app/[locale]/schedule/page.tsx +82 -0
  359. package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +9 -0
  360. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
  361. package/templates/apps/web/app/[locale]/services/page.tsx +9 -1
  362. package/templates/apps/web/app/[locale]/sign-in/__tests__/next-path.test.ts +31 -0
  363. package/templates/apps/web/app/[locale]/sign-in/__tests__/page.test.tsx +152 -0
  364. package/templates/apps/web/app/[locale]/sign-in/next-path.ts +0 -0
  365. package/templates/apps/web/app/[locale]/sign-in/page.tsx +83 -0
  366. package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +123 -0
  367. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +13 -1
  368. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
  369. package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +13 -1
  370. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
  371. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +11 -1
  372. package/templates/apps/web/app/[locale]/testimonials/page.tsx +13 -1
  373. package/templates/apps/web/app/[locale]/thanks/[slug]/__tests__/page.test.tsx +93 -0
  374. package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +48 -0
  375. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +11 -1
  376. package/templates/apps/web/app/[locale]/use-cases/page.tsx +13 -1
  377. package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +13 -1
  378. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
  379. package/templates/apps/web/app/globals.css +35 -0
  380. package/templates/apps/web/app/llms.txt/route.ts +2 -1
  381. package/templates/apps/web/app/og/route.tsx +10 -2
  382. package/templates/apps/web/auth.ts +8 -0
  383. package/templates/apps/web/components/sign-out-trigger.tsx +42 -0
  384. package/templates/apps/web/content/en/blog/README.txt +25 -0
  385. package/templates/apps/web/content/en/docs/index.mdx +28 -0
  386. package/templates/apps/web/jest.config.cjs +90 -27
  387. package/templates/apps/web/lib/__tests__/site-brand.test.ts +119 -0
  388. package/templates/apps/web/lib/__tests__/site-theme.test.ts +112 -0
  389. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +499 -0
  390. package/templates/apps/web/lib/account-config.ts +13 -0
  391. package/templates/apps/web/lib/server-api.ts +85 -0
  392. package/templates/apps/web/lib/site-brand.tsx +121 -0
  393. package/templates/apps/web/lib/site-theme.ts +74 -0
  394. package/templates/apps/web/messages/en.json +275 -7
  395. package/templates/apps/web/middleware.ts +11 -3
  396. package/templates/apps/web/next.config.mjs +8 -2
  397. package/templates/apps/web/package.json +17 -7
  398. package/templates/apps/web/postcss.config.mjs +23 -0
  399. package/templates/apps/web/public/.well-known/security.txt +3 -3
  400. package/templates/apps/web/src/lib/routes.ts +15 -2
  401. package/templates/apps/web/tsconfig.json +1 -16
  402. package/templates/content/_site.mdx +36 -25
  403. package/templates/content/en/AboutPage/about.mdx +24 -14
  404. package/templates/content/en/ContactPage/contact.mdx +23 -14
  405. package/templates/content/en/FAQPage/faq.mdx +10 -392
  406. package/templates/content/en/HomePage/home.mdx +14 -285
  407. package/templates/database/CHANGELOG.md +443 -0
  408. package/templates/database/LICENSE +201 -0
  409. package/templates/database/README.md +3 -1
  410. package/templates/database/__tests__/flows-listing-diagnostic.test.ts +392 -0
  411. package/templates/database/__tests__/flows-presets.test.ts +173 -0
  412. package/templates/database/__tests__/prefixed-ids.db.test.ts +146 -0
  413. package/templates/database/__tests__/seed.test.ts +88 -0
  414. package/templates/database/__tests__/user-cascade.test.ts +19 -4
  415. package/templates/database/auth/schema.prisma +521 -0
  416. package/templates/database/config/schema.prisma +234 -0
  417. package/templates/database/content/schema.prisma +263 -0
  418. package/templates/database/flows/listing-diagnostic.ts +182 -0
  419. package/templates/database/flows/presets.ts +315 -0
  420. package/templates/database/inbox/__tests__/schema.test.ts +4 -0
  421. package/templates/database/inbox/schema.prisma +574 -3
  422. package/templates/database/jest.config.cjs +8 -0
  423. package/templates/database/migrations/20260712215647_add_multi_tenant_tenancy/migration.sql +201 -0
  424. package/templates/database/migrations/20260713143320_reanchor_site_config_to_workspace/migration.sql +67 -0
  425. package/templates/database/migrations/20260713174000_add_audit_logs/migration.sql +46 -0
  426. package/templates/database/migrations/20260713190000_drop_telemetry_records/migration.sql +25 -0
  427. package/templates/database/migrations/20260713192000_add_uuidv7_function/migration.sql +49 -0
  428. package/templates/database/migrations/20260713192429_prefixed_uuid_entity_ids/migration.sql +197 -0
  429. package/templates/database/migrations/20260713200000_add_org_billing/migration.sql +32 -0
  430. package/templates/database/migrations/20260714000000_add_lead_promotion_fields/migration.sql +22 -0
  431. package/templates/database/migrations/20260714010000_add_usage_billing_content_models/migration.sql +151 -0
  432. package/templates/database/migrations/20260714020000_add_usage_billing_auth_config_models/migration.sql +223 -0
  433. package/templates/database/migrations/20260714030000_credit_balance_non_negative/migration.sql +22 -0
  434. package/templates/database/migrations/20260714030000_widen_usage_billing_report_aggregates/migration.sql +32 -0
  435. package/templates/database/migrations/20260810233516_add_flow_engine_models/migration.sql +40 -0
  436. package/templates/database/migrations/20260811020000_add_flow_session_abandon_email_columns/migration.sql +4 -0
  437. package/templates/database/migrations/20260811030000_add_flow_session_abandon_email_index/migration.sql +2 -0
  438. package/templates/database/migrations/20260811040000_add_flow_session_segment/migration.sql +2 -0
  439. package/templates/database/migrations/20260811050000_add_deliverable_models/migration.sql +29 -0
  440. package/templates/database/migrations/20260812000000_add_deliverable_grant_send_columns/migration.sql +6 -0
  441. package/templates/database/migrations/20260902222948_add_waitlist_experiment_models/migration.sql +39 -0
  442. package/templates/database/migrations/20260902224500_add_waitlist_id_format_checks/migration.sql +24 -0
  443. package/templates/database/migrations/20260903004112_add_flow_session_flags_aeo_score/migration.sql +3 -0
  444. package/templates/database/migrations/20260903010000_add_playbook_instance/migration.sql +33 -0
  445. package/templates/database/migrations/20260904000000_add_waitlist_followup_send/migration.sql +30 -0
  446. package/templates/database/migrations/20260905230000_add_flow_checkout/migration.sql +47 -0
  447. package/templates/database/migrations/20260906000000_add_flow_checkout_idempotency/migration.sql +16 -0
  448. package/templates/database/migrations/20260907120000_add_project_listing/migration.sql +47 -0
  449. package/templates/database/migrations/20260907130000_add_project_listing_slack_columns/migration.sql +10 -0
  450. package/templates/database/migrations/20260907180000_add_listing_csv_send/migration.sql +26 -0
  451. package/templates/database/migrations/20260909120000_project_listings_platform/migration.sql +90 -0
  452. package/templates/database/migrations/20260909180000_listing_draft_and_fields/migration.sql +174 -0
  453. package/templates/database/migrations/20260910120000_listing_public_site_key/migration.sql +14 -0
  454. package/templates/database/migrations/20260911120000_listing_copy_edit_audit/migration.sql +25 -0
  455. package/templates/database/migrations/20260911140000_listing_structured_address/migration.sql +32 -0
  456. package/templates/database/migrations/20260911180000_consent_grants/migration.sql +71 -0
  457. package/templates/database/migrations/20260911200000_listing_site_answers/migration.sql +30 -0
  458. package/templates/database/migrations/20260912120000_listing_owner_link/migration.sql +49 -0
  459. package/templates/database/ops/schema.prisma +27 -0
  460. package/templates/database/package.json +42 -4
  461. package/templates/database/prisma.config.ts +1 -1
  462. package/templates/database/schema.prisma +19 -435
  463. package/templates/database/seed-test.ts +14 -4
  464. package/templates/database/seed.ts +148 -0
  465. package/templates/database/tenancy.ts +45 -0
  466. package/templates/database/tsconfig.flows.json +15 -0
  467. package/templates/database/tsconfig.json +7 -1
  468. package/templates/database/tsconfig.tenancy.json +14 -0
  469. package/templates/package.json +30 -55
  470. package/templates/pnpm-workspace.yaml +0 -3
  471. package/templates/project.yaml +1 -1
  472. package/templates/tsconfig.json +1 -37
  473. package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +0 -94
  474. package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +0 -75
  475. package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +0 -82
  476. package/templates/apps/web/__tests__/auth/env-helpers.test.ts +0 -168
  477. package/templates/apps/web/__tests__/authority-list-routes.test.tsx +0 -208
  478. package/templates/apps/web/__tests__/better-stack.test.ts +0 -66
  479. package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +0 -87
  480. package/templates/apps/web/__tests__/blog-source-populated.test.ts +0 -130
  481. package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +0 -60
  482. package/templates/apps/web/__tests__/google-analytics.test.tsx +0 -104
  483. package/templates/apps/web/__tests__/i18n/middleware.test.ts +0 -119
  484. package/templates/apps/web/__tests__/i18n/routing.test.ts +0 -114
  485. package/templates/apps/web/__tests__/i18n/translations.test.ts +0 -191
  486. package/templates/apps/web/__tests__/json-ld.test.ts +0 -98
  487. package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +0 -580
  488. package/templates/apps/web/__tests__/layout-stealth.test.ts +0 -39
  489. package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +0 -103
  490. package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +0 -114
  491. package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +0 -94
  492. package/templates/apps/web/__tests__/page.test.tsx +0 -230
  493. package/templates/apps/web/__tests__/products-services-phase1.test.tsx +0 -321
  494. package/templates/apps/web/__tests__/projects-routes.test.tsx +0 -392
  495. package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +0 -475
  496. package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +0 -53
  497. package/templates/apps/web/__tests__/routes/blog-route.test.tsx +0 -191
  498. package/templates/apps/web/__tests__/routes/llms-txt.test.ts +0 -123
  499. package/templates/apps/web/__tests__/routes/robots-txt.test.ts +0 -52
  500. package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +0 -78
  501. package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +0 -203
  502. package/templates/apps/web/__tests__/section-routes.test.tsx +0 -693
  503. package/templates/apps/web/__tests__/security-headers.test.ts +0 -201
  504. package/templates/apps/web/__tests__/sentry-config.test.ts +0 -116
  505. package/templates/apps/web/__tests__/sitemap-locales.test.ts +0 -415
  506. package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +0 -844
  507. package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +0 -120
  508. package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +0 -202
  509. package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +0 -152
  510. package/templates/apps/web/content/en/blog/index.mdx +0 -15
  511. package/templates/apps/web/content/en/blog/launching-ailk.mdx +0 -20
  512. package/templates/apps/web/content/en/docs/getting-started.mdx +0 -30
  513. package/templates/content/.gitkeep +0 -0
  514. package/templates/content/CLAUDE.md +0 -85
  515. package/templates/content/ar/HomePage/home.mdx +0 -123
  516. package/templates/content/ar/_site.mdx +0 -35
  517. package/templates/content/de/_site.mdx +0 -29
  518. package/templates/content/en/.gitkeep +0 -0
  519. package/templates/content/en/AboutPage/about.schema.json +0 -82
  520. package/templates/content/en/BookCall/book-call.mdx +0 -19
  521. package/templates/content/en/BookCall/book-call.schema.json +0 -121
  522. package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +0 -20
  523. package/templates/content/en/CareersList/careers.mdx +0 -24
  524. package/templates/content/en/CaseStudiesList/case-studies.mdx +0 -22
  525. package/templates/content/en/CaseStudiesList/showcase.mdx +0 -8
  526. package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +0 -32
  527. package/templates/content/en/CaseStudy/schema-builder-migration.mdx +0 -41
  528. package/templates/content/en/ClientsList/clients.mdx +0 -38
  529. package/templates/content/en/ContactPage/contact.schema.json +0 -100
  530. package/templates/content/en/ContactPoint/primary.mdx +0 -14
  531. package/templates/content/en/Course/aeo-fundamentals.mdx +0 -37
  532. package/templates/content/en/Course/schema-builder-workshop.mdx +0 -62
  533. package/templates/content/en/CoursesList/courses.mdx +0 -22
  534. package/templates/content/en/DownloadsList/downloads.mdx +0 -22
  535. package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +0 -39
  536. package/templates/content/en/Event/ailk-launch-day-2026.mdx +0 -35
  537. package/templates/content/en/EventsList/events.mdx +0 -26
  538. package/templates/content/en/FAQPage/faq.schema.json +0 -231
  539. package/templates/content/en/GlossaryList/glossary.mdx +0 -19
  540. package/templates/content/en/GlossaryList/glossary.schema.json +0 -300
  541. package/templates/content/en/HomePage/home.schema.json +0 -88
  542. package/templates/content/en/HomePage/launch-service.mdx +0 -475
  543. package/templates/content/en/HomePage/launch-service.schema.json +0 -138
  544. package/templates/content/en/HowTo/add-mdx-content.mdx +0 -38
  545. package/templates/content/en/HowTo/configure-aeo-scoring.mdx +0 -35
  546. package/templates/content/en/HowTo/set-up-json-ld.mdx +0 -36
  547. package/templates/content/en/Integration/github-actions.mdx +0 -31
  548. package/templates/content/en/Integration/openai-api.mdx +0 -26
  549. package/templates/content/en/Integration/vercel.mdx +0 -32
  550. package/templates/content/en/IntegrationsList/integrations.mdx +0 -22
  551. package/templates/content/en/JobPosting/content-strategist.mdx +0 -46
  552. package/templates/content/en/JobPosting/developer-advocate.mdx +0 -47
  553. package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +0 -57
  554. package/templates/content/en/LandingPage/aeo-audit.mdx +0 -19
  555. package/templates/content/en/LandingPage/aeo-audit.schema.json +0 -92
  556. package/templates/content/en/LandingPage/agency-waitlist.mdx +0 -340
  557. package/templates/content/en/LandingPage/agency-waitlist.schema.json +0 -152
  558. package/templates/content/en/LandingPage/developers.mdx +0 -19
  559. package/templates/content/en/LandingPage/developers.schema.json +0 -109
  560. package/templates/content/en/LandingPage/for-agencies.mdx +0 -390
  561. package/templates/content/en/LandingPage/for-agencies.schema.json +0 -107
  562. package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +0 -417
  563. package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +0 -105
  564. package/templates/content/en/LandingPage/for-businesses.mdx +0 -19
  565. package/templates/content/en/LandingPage/for-businesses.schema.json +0 -96
  566. package/templates/content/en/LandingPage/platform.mdx +0 -369
  567. package/templates/content/en/LandingPage/platform.schema.json +0 -166
  568. package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +0 -19
  569. package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +0 -102
  570. package/templates/content/en/LandingPage/vs-wordpress.mdx +0 -19
  571. package/templates/content/en/LandingPage/vs-wordpress.schema.json +0 -53
  572. package/templates/content/en/NewsletterSignup/newsletter.mdx +0 -236
  573. package/templates/content/en/NewsletterSignup/newsletter.schema.json +0 -91
  574. package/templates/content/en/Organization/site-owner.mdx +0 -16
  575. package/templates/content/en/Partner/prisma.mdx +0 -31
  576. package/templates/content/en/Partner/supabase.mdx +0 -30
  577. package/templates/content/en/Partner/vercel.mdx +0 -28
  578. package/templates/content/en/PartnersList/partners.mdx +0 -22
  579. package/templates/content/en/Person/founder.mdx +0 -18
  580. package/templates/content/en/Pricing/pricing.mdx +0 -538
  581. package/templates/content/en/Pricing/pricing.schema.json +0 -209
  582. package/templates/content/en/PrivacyPage/privacy.mdx +0 -165
  583. package/templates/content/en/PrivacyPage/privacy.schema.json +0 -64
  584. package/templates/content/en/Product/ailk.mdx +0 -19
  585. package/templates/content/en/Product/ailk.schema.json +0 -94
  586. package/templates/content/en/Product/api-launch-kit.mdx +0 -26
  587. package/templates/content/en/Product/launch-kit.mdx +0 -28
  588. package/templates/content/en/ProductsList/products.mdx +0 -26
  589. package/templates/content/en/Project/ailk-phase-2.mdx +0 -54
  590. package/templates/content/en/ProjectsList/projects.mdx +0 -25
  591. package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +0 -27
  592. package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +0 -28
  593. package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +0 -39
  594. package/templates/content/en/ResourcesHub/resources.mdx +0 -22
  595. package/templates/content/en/Service/consulting.mdx +0 -22
  596. package/templates/content/en/Service/implementation.mdx +0 -30
  597. package/templates/content/en/Service/launch-service.mdx +0 -232
  598. package/templates/content/en/Service/launch.mdx +0 -228
  599. package/templates/content/en/ServicesList/services.mdx +0 -84
  600. package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +0 -44
  601. package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +0 -47
  602. package/templates/content/en/SoftwareProduct/ailk-schema.mdx +0 -49
  603. package/templates/content/en/TeamList/team.mdx +0 -63
  604. package/templates/content/en/TeamMember/founder.mdx +0 -72
  605. package/templates/content/en/TermsPage/terms.mdx +0 -19
  606. package/templates/content/en/TermsPage/terms.schema.json +0 -99
  607. package/templates/content/en/TestimonialsList/testimonials.mdx +0 -44
  608. package/templates/content/en/UseCasesList/use-cases.mdx +0 -30
  609. package/templates/content/en/Whitepaper/ax-first-product-development.mdx +0 -27
  610. package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +0 -27
  611. package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +0 -31
  612. package/templates/content/en-XA/AboutPage/about.mdx +0 -8
  613. package/templates/content/en-XA/FAQPage/faq.mdx +0 -8
  614. package/templates/content/en-XA/HomePage/home.mdx +0 -8
  615. package/templates/content/es/_site.mdx +0 -30
  616. package/templates/content/fr/_site.mdx +0 -30
  617. package/templates/content/ja/_site.mdx +0 -30
  618. package/templates/content/pt-BR/AboutPage/about.mdx +0 -8
  619. package/templates/content/pt-BR/FAQPage/faq.mdx +0 -8
  620. package/templates/content/pt-BR/HomePage/home.mdx +0 -23
@@ -1,3 +1,14 @@
1
+ /**
2
+ * The recognized module vocabulary for the `--modules` selector.
3
+ *
4
+ * A MODULE is a composable, potentially full-stack unit AILK's three-tier app
5
+ * is composed from (see architecture.yaml `composition_model`). At the MVP
6
+ * plumbing layer only the selection is threaded through; per-module template
7
+ * composition is downstream work, so the default (`marketing`) reproduces
8
+ * today's fixed-tree scaffold exactly.
9
+ */
10
+ export declare const RECOGNIZED_MODULES: readonly ["marketing", "docs", "multi-tenant", "scheduling"];
11
+ export type ModuleName = (typeof RECOGNIZED_MODULES)[number];
1
12
  export interface CliOptions {
2
13
  /** Positional target directory (the dir to scaffold into). Optional only
3
14
  * when `help` or `version` is set. */
@@ -5,9 +16,44 @@ export interface CliOptions {
5
16
  install: boolean;
6
17
  help: boolean;
7
18
  version: boolean;
19
+ /** Selected modules (recognized: marketing, docs, multi-tenant, scheduling).
20
+ * Defaults to ['marketing'] when the flag is absent. */
21
+ modules: string[];
22
+ /** Explicitly requested route surfaces (`--surfaces`). Empty when the flag is
23
+ * absent — the module set alone then decides (see surfaces.ts
24
+ * `resolveSurfaces`). Validated, lowercased, deduped and sorted. */
25
+ surfaces: string[];
26
+ /**
27
+ * When set, regenerate the target's COMPONENT-CATALOG.md in place from the
28
+ * catalog this create-ailk ships (catalog-sync mode) and exit. Mirrors
29
+ * `--sync-architecture`: data-only, one file, an already-scaffolded target.
30
+ */
31
+ syncCatalog: boolean;
32
+ /**
33
+ * When set, a fresh scaffold ALSO gets COMPONENT-CATALOG.md. Off by default
34
+ * so a scaffold that does not ask for the catalog is byte-identical to the
35
+ * pre-#4636 output.
36
+ */
37
+ withCatalog: boolean;
38
+ /** When set, the raw `--sync-architecture <csv>` value: regenerate the
39
+ * target's architecture.yaml in place from this module set (sync mode). The
40
+ * value is validated through `parseModules` at parse time; cli.ts re-parses
41
+ * it to the module list. Undefined when the flag is absent (scaffold mode). */
42
+ syncArchitecture: string | undefined;
8
43
  }
9
44
  export declare class ParseError extends Error {
10
45
  constructor(message: string);
11
46
  }
12
- export declare const helpText = "create-ailk \u2014 scaffold a new AI Launch Kit site.\n\nUsage:\n pnpm create ailk@latest <target-dir> [options]\n npx create-ailk <target-dir> [options]\n\nArguments:\n <target-dir> The directory to scaffold into. Must not exist OR\n must be empty. Path-traversal segments (..) are\n rejected.\n\nOptions:\n --install After scaffolding, run `pnpm install` in the\n target directory. Off by default.\n --help, -h Print this message.\n --version Print the scaffolder version.\n\nExamples:\n pnpm create ailk@latest my-site\n pnpm create ailk@latest /tmp/test-site --install\n\nNext steps after a successful scaffold:\n cd <target-dir>\n pnpm install\n pnpm dev\n\nReference: ADR 0007 \u2014 `pnpm create ailk@latest` is the canonical install path.\n";
47
+ export declare const helpText: string;
13
48
  export declare function parseCliArgs(argv: string[]): CliOptions;
49
+ /**
50
+ * Parse a module CSV (the `--modules` or `--sync-architecture` value) into a
51
+ * validated, normalized string[].
52
+ *
53
+ * Splits on `,`, trims and lowercases each entry, drops empties, and validates
54
+ * each against RECOGNIZED_MODULES. An absent flag (or an all-empty value)
55
+ * defaults to DEFAULT_MODULES (`['marketing']`) — reproducing today's scaffold.
56
+ *
57
+ * @throws ParseError on an unrecognized module value, naming the recognized set.
58
+ */
59
+ export declare function parseModules(raw: string | undefined): string[];
@@ -8,6 +8,24 @@
8
8
  * top-level catch turns this into a stderr write + non-zero exit.
9
9
  */
10
10
  import { parseArgs } from "node:util";
11
+ import { RECOGNIZED_SURFACES, parseSurfaces } from "./surfaces.js";
12
+ /**
13
+ * The recognized module vocabulary for the `--modules` selector.
14
+ *
15
+ * A MODULE is a composable, potentially full-stack unit AILK's three-tier app
16
+ * is composed from (see architecture.yaml `composition_model`). At the MVP
17
+ * plumbing layer only the selection is threaded through; per-module template
18
+ * composition is downstream work, so the default (`marketing`) reproduces
19
+ * today's fixed-tree scaffold exactly.
20
+ */
21
+ export const RECOGNIZED_MODULES = [
22
+ "marketing",
23
+ "docs",
24
+ "multi-tenant",
25
+ "scheduling",
26
+ ];
27
+ /** The default module selection when `--modules` is absent (reproduces today's scaffold). */
28
+ const DEFAULT_MODULES = ["marketing"];
11
29
  export class ParseError extends Error {
12
30
  constructor(message) {
13
31
  super(message);
@@ -26,6 +44,37 @@ Arguments:
26
44
  rejected.
27
45
 
28
46
  Options:
47
+ --modules <csv> Comma-separated list of modules to compose the site
48
+ from (recognized: ${RECOGNIZED_MODULES.join(", ")}).
49
+ Defaults to \`marketing\`, which reproduces today's
50
+ scaffold. A module is a composable unit across the
51
+ three tiers (data · API · presentation).
52
+ --surfaces <csv> Comma-separated route surfaces to scaffold IN
53
+ ADDITION to the core set (/, /about, /contact, /faq,
54
+ /thanks). Recognized: ${RECOGNIZED_SURFACES.join(", ")}.
55
+ Surfaces the declared architecture does not carry are
56
+ NOT scaffolded — their routes are absent, so a fresh
57
+ site never serves a stock page with placeholder
58
+ content. Add one later with the \`scaffold-page\`
59
+ skill, or re-run with the surface named here.
60
+ --sync-architecture <csv> Regenerate architecture.yaml in place in an
61
+ already-scaffolded repo from the given module set
62
+ (recognized: ${RECOGNIZED_MODULES.join(", ")}), then
63
+ exit. Data-only: rewrites only architecture.yaml, at
64
+ the target dir (positional arg, else cwd). Bypasses
65
+ the scaffold path — copies no template, runs no
66
+ install.
67
+ --with-catalog Also write COMPONENT-CATALOG.md — the capability-
68
+ indexed index of every @working-theory/ui component,
69
+ so a worker in the scaffolded repo can check what
70
+ already exists before building it. Off by default; a
71
+ scaffold without it is unchanged.
72
+ --sync-catalog Refresh COMPONENT-CATALOG.md in place in an already-
73
+ scaffolded repo from the catalog this create-ailk
74
+ ships, then exit. Data-only: rewrites only that one
75
+ file, at the target dir (positional arg, else cwd).
76
+ Bypasses the scaffold path — copies no template, runs
77
+ no install. Re-run after upgrading create-ailk.
29
78
  --install After scaffolding, run \`pnpm install\` in the
30
79
  target directory. Off by default.
31
80
  --help, -h Print this message.
@@ -50,6 +99,11 @@ export function parseCliArgs(argv) {
50
99
  strict: true,
51
100
  allowPositionals: true,
52
101
  options: {
102
+ modules: { type: "string" },
103
+ surfaces: { type: "string" },
104
+ "sync-architecture": { type: "string" },
105
+ "sync-catalog": { type: "boolean", default: false },
106
+ "with-catalog": { type: "boolean", default: false },
53
107
  install: { type: "boolean", default: false },
54
108
  help: { type: "boolean", default: false, short: "h" },
55
109
  version: { type: "boolean", default: false },
@@ -62,9 +116,52 @@ export function parseCliArgs(argv) {
62
116
  const help = parsed.values.help === true;
63
117
  const version = parsed.values.version === true;
64
118
  const install = parsed.values.install === true;
65
- // When help or version is set, target is optional.
119
+ const modules = parseModules(parsed.values.modules);
120
+ const surfaces = parseSurfaceList(parsed.values.surfaces);
121
+ const syncArchitecture = parsed.values["sync-architecture"];
122
+ const syncCatalog = parsed.values["sync-catalog"] === true;
123
+ const withCatalog = parsed.values["with-catalog"] === true;
124
+ // The two sync modes each exit after rewriting their one file, so asking for
125
+ // both in one invocation has no coherent meaning.
126
+ if (syncCatalog && syncArchitecture !== undefined) {
127
+ throw new ParseError("--sync-catalog and --sync-architecture cannot be combined; run them one at a time");
128
+ }
129
+ // Validate the sync-architecture value now, through the SAME parseModules
130
+ // path `--modules` uses, so an unknown module throws ParseError at parse time
131
+ // (cli.ts re-parses the raw value to the module list in sync mode).
132
+ if (syncArchitecture !== undefined) {
133
+ parseModules(syncArchitecture);
134
+ }
135
+ // When help or version is set, target is optional (help/version win).
66
136
  if (help || version) {
67
- return { target: undefined, install, help, version };
137
+ return {
138
+ target: undefined,
139
+ install,
140
+ help,
141
+ version,
142
+ modules,
143
+ surfaces,
144
+ syncCatalog: false,
145
+ withCatalog: false,
146
+ syncArchitecture: undefined,
147
+ };
148
+ }
149
+ // Sync modes: the target dir is optional (positional if given, else cwd).
150
+ if (syncArchitecture !== undefined || syncCatalog) {
151
+ if (parsed.positionals.length > 1) {
152
+ throw new ParseError(`expected at most one target directory, got ${parsed.positionals.length}`);
153
+ }
154
+ return {
155
+ target: parsed.positionals[0],
156
+ install,
157
+ help,
158
+ version,
159
+ modules,
160
+ surfaces,
161
+ syncCatalog,
162
+ withCatalog,
163
+ syncArchitecture,
164
+ };
68
165
  }
69
166
  if (parsed.positionals.length === 0) {
70
167
  throw new ParseError("missing target directory. Usage: pnpm create ailk@latest <target-dir>");
@@ -77,5 +174,49 @@ export function parseCliArgs(argv) {
77
174
  install,
78
175
  help,
79
176
  version,
177
+ modules,
178
+ surfaces,
179
+ syncCatalog,
180
+ withCatalog,
181
+ syncArchitecture: undefined,
80
182
  };
81
183
  }
184
+ /**
185
+ * Parse + validate the `--surfaces` CSV, re-throwing an unrecognized-surface
186
+ * failure as a ParseError so every CLI parse failure reaches the orchestrator's
187
+ * top-level catch through ONE error type.
188
+ */
189
+ function parseSurfaceList(raw) {
190
+ try {
191
+ return parseSurfaces(raw);
192
+ }
193
+ catch (err) {
194
+ throw new ParseError(err.message);
195
+ }
196
+ }
197
+ /**
198
+ * Parse a module CSV (the `--modules` or `--sync-architecture` value) into a
199
+ * validated, normalized string[].
200
+ *
201
+ * Splits on `,`, trims and lowercases each entry, drops empties, and validates
202
+ * each against RECOGNIZED_MODULES. An absent flag (or an all-empty value)
203
+ * defaults to DEFAULT_MODULES (`['marketing']`) — reproducing today's scaffold.
204
+ *
205
+ * @throws ParseError on an unrecognized module value, naming the recognized set.
206
+ */
207
+ export function parseModules(raw) {
208
+ if (raw === undefined)
209
+ return [...DEFAULT_MODULES];
210
+ const requested = raw
211
+ .split(",")
212
+ .map((m) => m.trim().toLowerCase())
213
+ .filter(Boolean);
214
+ if (requested.length === 0)
215
+ return [...DEFAULT_MODULES];
216
+ for (const m of requested) {
217
+ if (!RECOGNIZED_MODULES.includes(m)) {
218
+ throw new ParseError(`unknown module "${m}". Recognized: ${RECOGNIZED_MODULES.join(", ")}`);
219
+ }
220
+ }
221
+ return requested;
222
+ }
@@ -15,6 +15,9 @@
15
15
  * import { scaffoldSync } from './programmatic.js';
16
16
  * const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
17
17
  */
18
+ import { CATALOG_TARGET_PATH } from "./component-catalog.js";
19
+ import { type ModuleName } from "./parse-args.js";
20
+ import { type SyncRoutesResult } from "./sync-routes.js";
18
21
  export interface ScaffoldOptions {
19
22
  /** Absolute or relative path to the target directory. Must not exist or be empty. */
20
23
  targetDir: string;
@@ -25,12 +28,57 @@ export interface ScaffoldOptions {
25
28
  * Ignored at runtime until named presets are implemented.
26
29
  */
27
30
  preset?: string;
31
+ /**
32
+ * Selected modules (recognized: marketing, docs, multi-tenant). Defaults to
33
+ * ['marketing']. The scaffolder does NOT yet vary the copied template tree by
34
+ * module (per-module template composition is downstream work), so the copied
35
+ * files are today's fixed-tree scaffold — BUT the derived `architecture.yaml`
36
+ * (its code-boundary config) IS a function of this set (spec #3787), written
37
+ * at the target root after the template copy.
38
+ *
39
+ * As of #4154 the module set ALSO selects route surfaces (via
40
+ * `surfaces.ts` `MODULE_SURFACES`), so the copied tree is no longer
41
+ * module-invariant: a surface no module carries is not scaffolded at all.
42
+ */
43
+ modules?: string[];
44
+ /**
45
+ * Route surfaces to scaffold IN ADDITION to the core set (`--surfaces`).
46
+ * Omitted ⟹ the module set alone decides. Every gateable surface not in the
47
+ * resolved set has its route directories skipped by the copy, so its routes
48
+ * are ABSENT from the output rather than serving placeholder content (#4154).
49
+ */
50
+ surfaces?: string[];
51
+ /**
52
+ * Also write COMPONENT-CATALOG.md at the target root (`--with-catalog`).
53
+ * Defaults to false: a scaffold that does not ask for the catalog produces
54
+ * byte-identical output to the pre-#4636 scaffolder.
55
+ */
56
+ withCatalog?: boolean;
57
+ /**
58
+ * Licensed module delivery (K1, #5089 — Flavor 3). Consumed ONLY by the
59
+ * async `scaffold()` below — `scaffoldSync` remains oblivious to licensing
60
+ * entirely, so every existing synchronous caller (the vast majority of this
61
+ * package's own tests) is untouched by this card.
62
+ *
63
+ * `licenseKey` defaults to `process.env["AILK_LICENSE_KEY"]`; `fetchImpl`
64
+ * defaults to `globalThis.fetch` (injectable so tests — and this repo's own
65
+ * evidence runs — never make a live network call). Both are ignored
66
+ * entirely when `modules` names no paid module (the regression floor: a
67
+ * bare/all-Free scaffold reads neither).
68
+ */
69
+ licenseKey?: string;
70
+ /** Overrides `AILK_MODULE_REGISTRY_URL` / the built-in module-distribution default. */
71
+ moduleRegistryUrl?: string;
72
+ /** Injected fetch for tests. Never a live network call in CI or in this repo's evidence runs. */
73
+ fetchImpl?: typeof fetch;
28
74
  }
29
75
  export interface ScaffoldResult {
30
76
  /** Resolved absolute path to the scaffolded directory. */
31
77
  targetDir: string;
32
78
  /** Number of files written. */
33
79
  filesCreated: number;
80
+ /** The gateable route surfaces this scaffold declares (sorted). */
81
+ surfaces: string[];
34
82
  }
35
83
  /**
36
84
  * Scaffold an AI Launch Kit starter project into targetDir (synchronous).
@@ -42,8 +90,117 @@ export declare function scaffoldSync(opts: ScaffoldOptions): ScaffoldResult;
42
90
  /**
43
91
  * Scaffold an AI Launch Kit starter project into targetDir (async wrapper).
44
92
  *
45
- * Wraps scaffoldSync for callers that prefer Promise-based APIs. The
46
- * underlying I/O is synchronous; the async signature is provided for
47
- * compatibility with async callers (e.g. the MCP tool handler via subprocess).
93
+ * The ONLY entry point that resolves paid modules (K1, #5089 — Flavor 3):
94
+ *
95
+ * 1. Classify the requested module set into free / paid (`module-tier.ts`).
96
+ * 2. `resolvePaidModules` — zero-paid-modules returns instantly with no key
97
+ * read and no network call (the regression floor). A paid module with
98
+ * no key, or a licence the module distribution rejects, throws
99
+ * `LicenseRequiredError` HERE — before anything is written to disk.
100
+ * 3. `scaffoldSync` — unchanged, today's local `templates/` copy.
101
+ * 4. Merge each resolved paid module's fetched bundle into the freshly
102
+ * scaffolded tree (`extractModuleBundle`).
103
+ *
104
+ * `scaffoldSync` itself stays licensing-oblivious on purpose: every existing
105
+ * synchronous caller (this package's own test suite, overwhelmingly) is
106
+ * unaffected by this card — only a caller that goes through THIS function
107
+ * with a paid module in `opts.modules` exercises the gate at all.
48
108
  */
49
109
  export declare function scaffold(opts: ScaffoldOptions): Promise<ScaffoldResult>;
110
+ export { LicenseRequiredError, type ResolvePaidModulesOptions, } from "./lib/module-license-gate.js";
111
+ export { FREE_MODULES, PAID_MODULES, classifyModules } from "./lib/module-tier.js";
112
+ export type { ModuleName };
113
+ export interface SyncArchitectureOptions {
114
+ /**
115
+ * The already-scaffolded repo to sync (absolute or relative). It MUST exist
116
+ * and contain an `architecture.yaml` — the inverse of scaffold's empty-target
117
+ * rule (spec D3), so this path does NOT reuse `validateTarget`.
118
+ */
119
+ targetDir: string;
120
+ /** The module set to regenerate architecture.yaml from (validated upstream). */
121
+ modules: string[];
122
+ /** Route surfaces to declare in addition to the module-derived set (#4154). */
123
+ surfaces?: string[];
124
+ }
125
+ export interface SyncArchitectureResult {
126
+ /** Resolved absolute path to the synced directory. */
127
+ targetDir: string;
128
+ /** The gateable route surfaces the regenerated architecture.yaml declares. */
129
+ surfaces: string[];
130
+ /**
131
+ * Surface drift — route and content directories that EXIST in the target but
132
+ * belong to a surface the regenerated declaration does not carry. Reported,
133
+ * never removed: deleting files in an already-scaffolded repo is the
134
+ * operator's call, made as one reviewable commit (spec #4154 D5). Repo-
135
+ * relative, sorted.
136
+ */
137
+ undeclared: string[];
138
+ }
139
+ /**
140
+ * Regenerate an already-scaffolded repo's `architecture.yaml` in place from a
141
+ * module set (the "module added later" sync path — spec #3561).
142
+ *
143
+ * Mirrors scaffoldSync's architecture-write step MINUS the template copy: it
144
+ * overwrites exactly the one `architecture.yaml` file at the target root via
145
+ * the shipped, byte-deterministic `deriveArchitecture`, so a synced repo's
146
+ * config is identical to a fresh scaffold's for the same module set. Data-only
147
+ * and non-destructive: no template re-copy, no subprocess, no other file
148
+ * touched.
149
+ *
150
+ * Validates the target is an EXISTING scaffolded dir (an existing directory
151
+ * containing `architecture.yaml`) — the inverse of `validateTarget` (D3).
152
+ * Throws Error on a missing target, a non-directory target, or a directory with
153
+ * no `architecture.yaml`; the CLI's top-level catch turns that into a
154
+ * `[create-ailk] <message>` stderr write + exit 1.
155
+ */
156
+ export declare function syncArchitectureSync(opts: SyncArchitectureOptions): SyncArchitectureResult;
157
+ export interface SyncCatalogResult {
158
+ /** Resolved absolute path to the synced directory. */
159
+ targetDir: string;
160
+ /** Absolute path of the file written. */
161
+ catalogPath: string;
162
+ }
163
+ /**
164
+ * Refresh an already-scaffolded repo's `COMPONENT-CATALOG.md` in place from the
165
+ * catalog this create-ailk ships (#4636).
166
+ *
167
+ * The same shape as `syncArchitectureSync`, with a different artifact: validate
168
+ * the target is an existing scaffolded dir, overwrite exactly one file, touch
169
+ * nothing else, spawn nothing. The catalog is regenerated from `packages/ui` at
170
+ * publish time, so re-running this after upgrading create-ailk is how a site
171
+ * picks up components added since it was scaffolded.
172
+ */
173
+ export declare function syncCatalogSync(opts: {
174
+ targetDir: string;
175
+ }): SyncCatalogResult;
176
+ export interface SyncRoutesSyncOptions {
177
+ /** The already-scaffolded repo to sync (absolute or relative). */
178
+ targetDir: string;
179
+ /** Copy the missing route directories in. Default false = check only. */
180
+ apply?: boolean;
181
+ }
182
+ /**
183
+ * Compare an already-scaffolded repo's route tree with the template this
184
+ * create-ailk ships and, with `apply`, copy in the route dirs it is missing
185
+ * (`create-ailk sync-routes`, #4986).
186
+ *
187
+ * The same shape as `syncArchitectureSync` / `syncCatalogSync`: validate the
188
+ * target is an existing scaffolded dir, spawn nothing, touch nothing else. The
189
+ * one difference is what it writes — not a regenerated file but the ABSENT
190
+ * route directories, copied through the scaffold's own `copyTemplate` with the
191
+ * scaffold's own markers, so a synced route is byte-identical to a fresh
192
+ * scaffold's. No other template file is re-copied; a route the site changed is
193
+ * reported and left as-is; nothing is deleted. The logic lives in
194
+ * `sync-routes.ts` (a pure module jest imports directly); this wrapper only
195
+ * supplies the package's `templates/` dir and version map.
196
+ */
197
+ export declare function syncRoutesSync(opts: SyncRoutesSyncOptions): SyncRoutesResult;
198
+ /** Re-exported beside the other sync results so consumers see one surface. */
199
+ export type { RouteReport, SyncRoutesResult } from "./sync-routes.js";
200
+ /** Re-exported so the CLI can name the file it wrote without duplicating it. */
201
+ export { CATALOG_TARGET_PATH };
202
+ /**
203
+ * Render the surface-drift report the CLI prints after a sync run. Returns an
204
+ * empty string when there is no drift, so the caller can skip the write.
205
+ */
206
+ export declare function formatSurfaceDrift(undeclared: string[]): string;
@@ -15,10 +15,18 @@
15
15
  * import { scaffoldSync } from './programmatic.js';
16
16
  * const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
17
17
  */
18
- import { existsSync, readdirSync, readFileSync } from "node:fs";
19
- import { basename, dirname, resolve } from "node:path";
18
+ import { existsSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
19
+ import { basename, dirname, join, resolve } from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
+ import { CATALOG_TARGET_PATH, writeComponentCatalog, } from "./component-catalog.js";
21
22
  import { copyTemplate } from "./copy.js";
23
+ import { deriveArchitecture } from "./derive-architecture.js";
24
+ import { extractModuleBundle } from "./lib/extract-module-bundle.js";
25
+ import { resolvePaidModules } from "./lib/module-license-gate.js";
26
+ import { classifyModules } from "./lib/module-tier.js";
27
+ import { normalizeModules } from "./module-architecture.js";
28
+ import { NAV_CONFIG_PATH, excludedRoutePaths, renderNavConfig, resolveSurfaces, } from "./surfaces.js";
29
+ import { syncRoutes } from "./sync-routes.js";
22
30
  import { validateTarget } from "./validate.js";
23
31
  const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
24
32
  const TEMPLATES_DIR = resolve(PKG_ROOT, "templates");
@@ -63,27 +71,208 @@ export function scaffoldSync(opts) {
63
71
  // Validate target — throws ValidationError on rejection.
64
72
  const targetAbs = validateTarget(opts.targetDir);
65
73
  const projectName = opts.projectName ?? basename(targetAbs);
74
+ // The declared route surface (#4154). Resolved BEFORE the copy: it decides
75
+ // both which route directories are skipped and what architecture.yaml records.
76
+ const enabledSurfaces = resolveSurfaces(opts.modules ?? ["marketing"], opts.surfaces ?? []);
66
77
  const versions = readVersionMap();
67
78
  copyTemplate({
68
79
  templatesDir: TEMPLATES_DIR,
69
80
  targetDir: targetAbs,
70
81
  versions,
82
+ excludePaths: excludedRoutePaths(enabledSurfaces),
71
83
  markers: {
72
84
  PROJECT_NAME: projectName,
73
85
  COMPANY_NAME: "Your Company",
74
86
  COMPANY_DOMAIN: "example.com",
75
87
  },
76
88
  });
89
+ // Derive + write the module-set-driven architecture.yaml (spec #3787). This
90
+ // is the single source of the scaffolded site's code-boundary config and
91
+ // closes the dangling `architecture_rules: architecture.yaml` reference in
92
+ // the scaffolded project.yaml. Written AFTER the template copy, at the target
93
+ // root — a deterministic function of the selected module set.
94
+ writeFileSync(join(targetAbs, "architecture.yaml"), deriveArchitecture(opts.modules ?? ["marketing"], enabledSurfaces));
95
+ // Regenerate the site nav from the same surface set (#4154). The nav is a
96
+ // static list the layout renders into the header AND the footer, so leaving
97
+ // the template's copy in place would link /docs and /blog sitewide in a
98
+ // scaffold that carries neither route.
99
+ writeFileSync(join(targetAbs, NAV_CONFIG_PATH), renderNavConfig(enabledSurfaces));
100
+ // Opt-in only (#4636). Every write above this line is unconditional, so a
101
+ // scaffold with `withCatalog` unset touches exactly the files it did before.
102
+ if (opts.withCatalog === true)
103
+ writeComponentCatalog(targetAbs);
77
104
  const filesCreated = countFiles(targetAbs);
78
- return { targetDir: targetAbs, filesCreated };
105
+ return { targetDir: targetAbs, filesCreated, surfaces: enabledSurfaces };
79
106
  }
80
107
  /**
81
108
  * Scaffold an AI Launch Kit starter project into targetDir (async wrapper).
82
109
  *
83
- * Wraps scaffoldSync for callers that prefer Promise-based APIs. The
84
- * underlying I/O is synchronous; the async signature is provided for
85
- * compatibility with async callers (e.g. the MCP tool handler via subprocess).
110
+ * The ONLY entry point that resolves paid modules (K1, #5089 — Flavor 3):
111
+ *
112
+ * 1. Classify the requested module set into free / paid (`module-tier.ts`).
113
+ * 2. `resolvePaidModules` — zero-paid-modules returns instantly with no key
114
+ * read and no network call (the regression floor). A paid module with
115
+ * no key, or a licence the module distribution rejects, throws
116
+ * `LicenseRequiredError` HERE — before anything is written to disk.
117
+ * 3. `scaffoldSync` — unchanged, today's local `templates/` copy.
118
+ * 4. Merge each resolved paid module's fetched bundle into the freshly
119
+ * scaffolded tree (`extractModuleBundle`).
120
+ *
121
+ * `scaffoldSync` itself stays licensing-oblivious on purpose: every existing
122
+ * synchronous caller (this package's own test suite, overwhelmingly) is
123
+ * unaffected by this card — only a caller that goes through THIS function
124
+ * with a paid module in `opts.modules` exercises the gate at all.
86
125
  */
87
126
  export async function scaffold(opts) {
88
- return scaffoldSync(opts);
127
+ const { paid } = classifyModules(normalizeModules(opts.modules ?? ["marketing"]));
128
+ const bundles = await resolvePaidModules({
129
+ paidModules: paid,
130
+ licenseKey: opts.licenseKey,
131
+ ...(opts.moduleRegistryUrl !== undefined
132
+ ? { registryUrl: opts.moduleRegistryUrl }
133
+ : {}),
134
+ ...(opts.fetchImpl !== undefined ? { fetchImpl: opts.fetchImpl } : {}),
135
+ });
136
+ const result = scaffoldSync(opts);
137
+ for (const [moduleName, bytes] of bundles) {
138
+ await extractModuleBundle({
139
+ bytes,
140
+ targetDir: result.targetDir,
141
+ moduleName,
142
+ });
143
+ }
144
+ return result;
145
+ }
146
+ // Re-exported so a consumer of the async `scaffold()` above can type its own
147
+ // wrapper (e.g. the MCP scaffold-site tool) without reaching into `lib/`.
148
+ export { LicenseRequiredError, } from "./lib/module-license-gate.js";
149
+ export { FREE_MODULES, PAID_MODULES, classifyModules } from "./lib/module-tier.js";
150
+ /**
151
+ * Regenerate an already-scaffolded repo's `architecture.yaml` in place from a
152
+ * module set (the "module added later" sync path — spec #3561).
153
+ *
154
+ * Mirrors scaffoldSync's architecture-write step MINUS the template copy: it
155
+ * overwrites exactly the one `architecture.yaml` file at the target root via
156
+ * the shipped, byte-deterministic `deriveArchitecture`, so a synced repo's
157
+ * config is identical to a fresh scaffold's for the same module set. Data-only
158
+ * and non-destructive: no template re-copy, no subprocess, no other file
159
+ * touched.
160
+ *
161
+ * Validates the target is an EXISTING scaffolded dir (an existing directory
162
+ * containing `architecture.yaml`) — the inverse of `validateTarget` (D3).
163
+ * Throws Error on a missing target, a non-directory target, or a directory with
164
+ * no `architecture.yaml`; the CLI's top-level catch turns that into a
165
+ * `[create-ailk] <message>` stderr write + exit 1.
166
+ */
167
+ export function syncArchitectureSync(opts) {
168
+ const targetAbs = resolve(opts.targetDir);
169
+ if (!existsSync(targetAbs)) {
170
+ throw new Error(`sync target does not exist: ${targetAbs}. Point --sync-architecture at an already-scaffolded repo.`);
171
+ }
172
+ if (!statSync(targetAbs).isDirectory()) {
173
+ throw new Error(`sync target is not a directory: ${targetAbs}`);
174
+ }
175
+ const archPath = join(targetAbs, "architecture.yaml");
176
+ if (!existsSync(archPath)) {
177
+ throw new Error(`not a scaffolded repo: no architecture.yaml at ${targetAbs}. Run \`create-ailk <target-dir>\` to scaffold first.`);
178
+ }
179
+ const enabledSurfaces = resolveSurfaces(opts.modules, opts.surfaces ?? []);
180
+ writeFileSync(archPath, deriveArchitecture(opts.modules, enabledSurfaces));
181
+ return {
182
+ targetDir: targetAbs,
183
+ surfaces: enabledSurfaces,
184
+ undeclared: findUndeclaredSurfacePaths(targetAbs, enabledSurfaces),
185
+ };
186
+ }
187
+ /**
188
+ * List the ROUTE directories present in an already-scaffolded repo that belong
189
+ * to a gateable surface the given declaration does not carry.
190
+ *
191
+ * This is the adoption path for a site scaffolded before #4154 (spec D5): the
192
+ * sync run declares what the site actually has, then names what is left over so
193
+ * the operator can remove it in one reviewable commit. It is READ-ONLY — it
194
+ * stats paths and returns strings, and never writes or deletes.
195
+ *
196
+ * Routes only, deliberately. A surface's content directories are informational
197
+ * (`Surface.content`), not drift: `apps/web/content/<locale>/{blog,docs}` must
198
+ * exist in EVERY scaffold — `source.config.ts` resolves those paths at build
199
+ * time whether or not the route is mounted — so sweeping content here would
200
+ * tell every operator to delete directories the build requires.
201
+ */
202
+ function findUndeclaredSurfacePaths(targetAbs, enabled) {
203
+ return excludedRoutePaths(enabled)
204
+ .filter((rel) => existsSync(join(targetAbs, rel)))
205
+ .sort();
206
+ }
207
+ /**
208
+ * Refresh an already-scaffolded repo's `COMPONENT-CATALOG.md` in place from the
209
+ * catalog this create-ailk ships (#4636).
210
+ *
211
+ * The same shape as `syncArchitectureSync`, with a different artifact: validate
212
+ * the target is an existing scaffolded dir, overwrite exactly one file, touch
213
+ * nothing else, spawn nothing. The catalog is regenerated from `packages/ui` at
214
+ * publish time, so re-running this after upgrading create-ailk is how a site
215
+ * picks up components added since it was scaffolded.
216
+ */
217
+ export function syncCatalogSync(opts) {
218
+ const targetAbs = resolve(opts.targetDir);
219
+ if (!existsSync(targetAbs)) {
220
+ throw new Error(`sync target does not exist: ${targetAbs}. Point --sync-catalog at an already-scaffolded repo.`);
221
+ }
222
+ if (!statSync(targetAbs).isDirectory()) {
223
+ throw new Error(`sync target is not a directory: ${targetAbs}`);
224
+ }
225
+ if (!existsSync(join(targetAbs, "architecture.yaml"))) {
226
+ throw new Error(`not a scaffolded repo: no architecture.yaml at ${targetAbs}. Run \`create-ailk <target-dir>\` to scaffold first.`);
227
+ }
228
+ return {
229
+ targetDir: targetAbs,
230
+ catalogPath: writeComponentCatalog(targetAbs),
231
+ };
232
+ }
233
+ /**
234
+ * Compare an already-scaffolded repo's route tree with the template this
235
+ * create-ailk ships and, with `apply`, copy in the route dirs it is missing
236
+ * (`create-ailk sync-routes`, #4986).
237
+ *
238
+ * The same shape as `syncArchitectureSync` / `syncCatalogSync`: validate the
239
+ * target is an existing scaffolded dir, spawn nothing, touch nothing else. The
240
+ * one difference is what it writes — not a regenerated file but the ABSENT
241
+ * route directories, copied through the scaffold's own `copyTemplate` with the
242
+ * scaffold's own markers, so a synced route is byte-identical to a fresh
243
+ * scaffold's. No other template file is re-copied; a route the site changed is
244
+ * reported and left as-is; nothing is deleted. The logic lives in
245
+ * `sync-routes.ts` (a pure module jest imports directly); this wrapper only
246
+ * supplies the package's `templates/` dir and version map.
247
+ */
248
+ export function syncRoutesSync(opts) {
249
+ return syncRoutes({
250
+ ...opts,
251
+ templatesDir: TEMPLATES_DIR,
252
+ versions: readVersionMap(),
253
+ });
254
+ }
255
+ /** Re-exported so the CLI can name the file it wrote without duplicating it. */
256
+ export { CATALOG_TARGET_PATH };
257
+ /**
258
+ * Render the surface-drift report the CLI prints after a sync run. Returns an
259
+ * empty string when there is no drift, so the caller can skip the write.
260
+ */
261
+ export function formatSurfaceDrift(undeclared) {
262
+ if (undeclared.length === 0)
263
+ return "";
264
+ const lines = [
265
+ "",
266
+ `[create-ailk] ${undeclared.length} path(s) belong to route surfaces this architecture.yaml does not declare:`,
267
+ ...undeclared.map((p) => ` ${p}`),
268
+ "",
269
+ "These are NOT removed automatically. Either declare the surface",
270
+ "(re-run with --surfaces <id>) or delete the paths above — a scaffolded",
271
+ "site that keeps them serves routes its declared architecture does not carry.",
272
+ "",
273
+ "Content that fed those routes may be orphaned too: content whose route is",
274
+ "gone still appears in /sitemap.xml and /llms.txt, advertising URLs that 404.",
275
+ "",
276
+ ];
277
+ return lines.join("\n");
89
278
  }