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
package/dist/cli.js CHANGED
@@ -3,43 +3,114 @@
3
3
  * `create-ailk` — entry point.
4
4
  *
5
5
  * Orchestration:
6
+ * 0. on a `sync-routes` subcommand: parse its own argv, run syncRoutesSync(),
7
+ * print the report, exit (1 iff routes are missing in check mode)
6
8
  * 1. parse argv → CliOptions
7
9
  * 2. on --help: print helpText, exit 0
8
10
  * 3. on --version: print version, exit 0
9
- * 4. delegate to scaffoldSync() in programmatic.ts (validates + copies template)
11
+ * 4. delegate to scaffold() in programmatic.ts gates + fetches any
12
+ * requested paid module (K1, #5089 — Flavor 3), then validates + copies
13
+ * the local template, then merges each fetched bundle in
10
14
  * 5. when --install: spawn `pnpm install` (cwd = target, hard-coded argv)
11
15
  * 6. print next-steps message
12
16
  *
13
- * Any thrown error (parse failure, validation failure, copy failure) is
14
- * caught at the top level: stderr "[create-ailk] <message>", exit non-zero.
17
+ * Any thrown error (parse failure, validation failure, copy failure,
18
+ * `LicenseRequiredError`) is caught at the top level: stderr
19
+ * "[create-ailk] <message>", exit non-zero. `LicenseRequiredError` is not
20
+ * special-cased — its message already states which honest state fired (no
21
+ * key / licence does not cover this module), so the existing single
22
+ * error-handling path is the whole contract.
23
+ *
24
+ * `main()` is async ONLY because Deliverable 2 needs to `await` the paid-
25
+ * module network round trip; every other branch below is exactly as
26
+ * synchronous as before.
15
27
  */
16
28
  import { spawnSync } from "node:child_process";
17
29
  import { readFileSync } from "node:fs";
18
30
  import { dirname, resolve } from "node:path";
19
31
  import { fileURLToPath } from "node:url";
20
32
  import { proCallout } from "./lib/pro-callout.js";
21
- import { helpText, parseCliArgs } from "./parse-args.js";
22
- import { scaffoldSync } from "./programmatic.js";
33
+ import { helpText, parseCliArgs, parseModules } from "./parse-args.js";
34
+ import { formatSurfaceDrift, scaffold, syncArchitectureSync, syncCatalogSync, syncRoutesSync, } from "./programmatic.js";
35
+ import { CORE_SURFACE_PATHS } from "./surfaces.js";
36
+ import { SYNC_ROUTES_HELP, formatSyncRoutesReport, parseSyncRoutesArgs, } from "./sync-routes.js";
23
37
  const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
24
38
  const PKG_JSON = resolve(PKG_ROOT, "package.json");
25
39
  function readPackageVersion() {
26
40
  const raw = readFileSync(PKG_JSON, "utf8");
27
41
  return JSON.parse(raw).version;
28
42
  }
29
- function main() {
30
- const opts = parseCliArgs(process.argv.slice(2));
43
+ async function main() {
44
+ const argv = process.argv.slice(2);
45
+ // Subcommand dispatch, ahead of the flag parser: `sync-routes` has its own
46
+ // argv shape (#4986). Check mode exits 1 iff a template route is missing;
47
+ // locally modified routes are reported but do not fail; --apply exits 0.
48
+ if (argv[0] === "sync-routes") {
49
+ const args = parseSyncRoutesArgs(argv.slice(1));
50
+ if (args.help) {
51
+ process.stdout.write(SYNC_ROUTES_HELP);
52
+ process.exit(0);
53
+ }
54
+ const result = syncRoutesSync({
55
+ targetDir: args.target ?? process.cwd(),
56
+ apply: args.apply,
57
+ });
58
+ process.stdout.write(formatSyncRoutesReport(result, args.apply));
59
+ process.exit(!args.apply && result.missing.length > 0 ? 1 : 0);
60
+ }
61
+ const opts = parseCliArgs(argv);
31
62
  if (opts.help) {
32
- process.stdout.write(helpText);
63
+ process.stdout.write(helpText + "\n" + SYNC_ROUTES_HELP);
33
64
  process.exit(0);
34
65
  }
35
66
  if (opts.version) {
36
67
  process.stdout.write(readPackageVersion() + "\n");
37
68
  process.exit(0);
38
69
  }
39
- // scaffoldSync() validates and copies the template — throws ValidationError
40
- // on rejection (caught at top level below).
41
- const { targetDir: targetAbs } = scaffoldSync({
70
+ // Catalog-sync mode: refresh COMPONENT-CATALOG.md in an already-scaffolded
71
+ // repo, then exit the `--sync-architecture` shape with a different artifact
72
+ // (#4636). Data-only: one file rewritten, no template copy, no install.
73
+ if (opts.syncCatalog) {
74
+ const { catalogPath } = syncCatalogSync({
75
+ targetDir: opts.target ?? process.cwd(),
76
+ });
77
+ process.stdout.write(`[create-ailk] Wrote ${catalogPath}\n` +
78
+ `[create-ailk] Search it by CAPABILITY before building a component — it indexes every @working-theory/ui section, block and chrome component by what it does.\n`);
79
+ process.exit(0);
80
+ }
81
+ // Sync mode: regenerate architecture.yaml in an already-scaffolded repo from
82
+ // the module set, then exit — bypassing the scaffold / --install / next-steps
83
+ // path entirely (spec #3561 D2). Data-only and non-destructive: only
84
+ // architecture.yaml is rewritten. The value was already validated at parse
85
+ // time; re-parse it through the SAME parseModules to the module list.
86
+ if (opts.syncArchitecture !== undefined) {
87
+ const modules = parseModules(opts.syncArchitecture);
88
+ const targetDir = opts.target ?? process.cwd();
89
+ const { targetDir: targetAbs, surfaces, undeclared, } = syncArchitectureSync({
90
+ targetDir,
91
+ modules,
92
+ surfaces: opts.surfaces,
93
+ });
94
+ process.stdout.write(`[create-ailk] Regenerated architecture.yaml in ${targetAbs} from modules: ${modules.join(", ")}\n`);
95
+ process.stdout.write(`[create-ailk] Declared route surfaces: ${surfaces.length > 0 ? surfaces.join(", ") : "core only"}\n`);
96
+ // Surface drift is advisory, never fatal and never auto-removed (#4154 D5):
97
+ // the operator deletes the named paths in their own reviewable commit.
98
+ const drift = formatSurfaceDrift(undeclared);
99
+ if (drift)
100
+ process.stdout.write(drift);
101
+ process.exit(0);
102
+ }
103
+ // scaffold() gates + fetches any requested paid module (K1, #5089), then
104
+ // validates and copies the local template — throws ValidationError or
105
+ // LicenseRequiredError on rejection (caught at top level below). Neither
106
+ // AILK_LICENSE_KEY nor AILK_MODULE_REGISTRY_URL is read, and no network
107
+ // call is made, when `opts.modules` names no paid module — the regression
108
+ // floor (see `resolvePaidModules` in `lib/module-license-gate.ts`).
109
+ const { targetDir: targetAbs, surfaces } = await scaffold({
42
110
  targetDir: opts.target,
111
+ modules: opts.modules,
112
+ surfaces: opts.surfaces,
113
+ withCatalog: opts.withCatalog,
43
114
  });
44
115
  if (opts.install) {
45
116
  // Hard-coded argv. User input only flows through `cwd`, never the command.
@@ -65,16 +136,21 @@ function main() {
65
136
  lines.push(" pnpm dev");
66
137
  lines.push("");
67
138
  lines.push("Open http://localhost:3000 to see the home page.");
139
+ lines.push("");
140
+ lines.push(`Route surfaces: ${CORE_SURFACE_PATHS.join(", ")}` +
141
+ (surfaces.length > 0 ? ` + ${surfaces.join(", ")}` : ""));
142
+ lines.push("Add another with the `scaffold-page` skill, or re-run with --surfaces <id>.");
143
+ // Only when asked for. The default scaffold's output is unchanged.
144
+ if (opts.withCatalog) {
145
+ lines.push("Component catalog: COMPONENT-CATALOG.md — search it by capability before building a component.");
146
+ }
68
147
  lines.push("Reference: ADR 0007 — pnpm create ailk@latest is the canonical install path.");
69
148
  lines.push("");
70
149
  lines.push(proCallout());
71
150
  lines.push("");
72
151
  process.stdout.write(lines.join("\n"));
73
152
  }
74
- try {
75
- main();
76
- }
77
- catch (err) {
153
+ main().catch((err) => {
78
154
  process.stderr.write(`[create-ailk] ${err.message}\n`);
79
155
  process.exit(1);
80
- }
156
+ });
@@ -0,0 +1,11 @@
1
+ /** Where the catalog lands in a consuming repo. The address is the contract. */
2
+ export declare const CATALOG_TARGET_PATH = "COMPONENT-CATALOG.md";
3
+ /**
4
+ * Copy the shipped catalog to `<targetAbs>/COMPONENT-CATALOG.md`, overwriting
5
+ * any previous copy. Returns the absolute path written.
6
+ *
7
+ * Throws when the package carries no catalog — that means `build-catalog` never
8
+ * ran, and writing nothing silently would leave the consuming repo believing it
9
+ * has an inventory it does not have.
10
+ */
11
+ export declare function writeComponentCatalog(targetAbs: string): string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Distribution of the generated component catalog into a consuming repo.
3
+ *
4
+ * The catalog (`component-catalog.md`, generated by
5
+ * `scripts/build-component-catalog.mjs` and shipped in this package's tarball)
6
+ * answers "what component gives me a modal form on a dimmed backdrop?" with
7
+ * `FormLightbox`. It is only useful where the person asking that question is,
8
+ * which is a scaffolded site's own repo — a cloud session there is single-repo
9
+ * by construction and cannot reach AILK (#4636 cause 1: no address).
10
+ *
11
+ * The file lands at the TARGET ROOT, beside `CLAUDE.md`, `CONVENTIONS.md` and
12
+ * `project.yaml`. Root rather than `docs/`: a scaffold has no `docs/` today,
13
+ * and the whole failure being fixed is that the inventory had no address a
14
+ * worker could resolve — the root is the one place every reader already looks.
15
+ */
16
+ import { copyFileSync, existsSync } from "node:fs";
17
+ import { dirname, join, resolve } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+ const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
20
+ /** The catalog as shipped in this package (generated at `prepublishOnly`). */
21
+ const CATALOG_SOURCE = join(PKG_ROOT, "component-catalog.md");
22
+ /** Where the catalog lands in a consuming repo. The address is the contract. */
23
+ export const CATALOG_TARGET_PATH = "COMPONENT-CATALOG.md";
24
+ /**
25
+ * Copy the shipped catalog to `<targetAbs>/COMPONENT-CATALOG.md`, overwriting
26
+ * any previous copy. Returns the absolute path written.
27
+ *
28
+ * Throws when the package carries no catalog — that means `build-catalog` never
29
+ * ran, and writing nothing silently would leave the consuming repo believing it
30
+ * has an inventory it does not have.
31
+ */
32
+ export function writeComponentCatalog(targetAbs) {
33
+ if (!existsSync(CATALOG_SOURCE)) {
34
+ throw new Error(`no component catalog in this create-ailk install (${CATALOG_SOURCE}). Run \`pnpm --filter create-ailk run build-catalog\` first.`);
35
+ }
36
+ const dest = join(targetAbs, CATALOG_TARGET_PATH);
37
+ copyFileSync(CATALOG_SOURCE, dest);
38
+ return dest;
39
+ }
package/dist/copy.d.ts CHANGED
@@ -4,5 +4,12 @@ export interface CopyTemplateOptions {
4
4
  targetDir: string;
5
5
  versions: WorkspaceVersionMap;
6
6
  markers: MarkerMap;
7
+ /**
8
+ * Template-relative directory paths to SKIP entirely — the route directories
9
+ * of gateable surfaces the declared architecture does not carry (spec #4154).
10
+ * Forward-slash separated. Matching is anchored at a directory boundary, so
11
+ * `.../services` never excludes a sibling `.../services-extra`.
12
+ */
13
+ excludePaths?: string[];
7
14
  }
8
15
  export declare function copyTemplate(opts: CopyTemplateOptions): void;
package/dist/copy.js CHANGED
@@ -21,6 +21,24 @@
21
21
  import { copyFileSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "node:fs";
22
22
  import { extname, join, relative, resolve, sep } from "node:path";
23
23
  import { substituteMarkers, substituteWorkspaceVersions, } from "./substitute.js";
24
+ /**
25
+ * Whether a walked template-relative path is inside (or equal to) an excluded
26
+ * directory. Compares `/`-normalized paths so the check holds on Windows, and
27
+ * only at a directory boundary — a prefix that stops mid-segment is no match.
28
+ */
29
+ function isExcluded(relativePath, excluded) {
30
+ if (excluded.length === 0)
31
+ return false;
32
+ const rel = relativePath.split(sep).join("/");
33
+ for (const raw of excluded) {
34
+ const ex = raw.replace(/\/+$/, "");
35
+ if (ex.length === 0)
36
+ continue;
37
+ if (rel === ex || rel.startsWith(ex + "/"))
38
+ return true;
39
+ }
40
+ return false;
41
+ }
24
42
  /** File extensions whose content we treat as text (and run markers over). */
25
43
  const TEXT_EXTS = new Set([
26
44
  ".md",
@@ -61,6 +79,7 @@ function isPackageJson(relativePath) {
61
79
  export function copyTemplate(opts) {
62
80
  const templatesAbs = resolve(opts.templatesDir);
63
81
  const targetAbs = resolve(opts.targetDir);
82
+ const excluded = opts.excludePaths ?? [];
64
83
  mkdirSync(targetAbs, { recursive: true });
65
84
  const stack = [templatesAbs];
66
85
  while (stack.length > 0) {
@@ -75,6 +94,11 @@ export function copyTemplate(opts) {
75
94
  continue;
76
95
  const srcPath = join(dir, entry.name);
77
96
  const rel = relative(templatesAbs, srcPath);
97
+ // Surface gating (#4154): a route directory belonging to a surface the
98
+ // declared architecture does not carry is skipped outright — the route is
99
+ // ABSENT from the scaffold, not present-and-serving-a-placeholder.
100
+ if (isExcluded(rel, excluded))
101
+ continue;
78
102
  const dstPath = join(targetAbs, rel);
79
103
  // Path-safety guard: dstPath MUST be within targetAbs. Use `path.sep`
80
104
  // so the check holds on Windows (`\\`) as well as POSIX (`/`).
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Derive the `architecture.yaml` document for a module set.
3
+ *
4
+ * @param modules the selected module names (any order; deduped). Defaults to
5
+ * the same set `parse-args` defaults to when omitted (`['marketing']`).
6
+ * @param surfaces the enabled gateable route surfaces. Omitted ⟹ derived from
7
+ * the module set alone (`resolveSurfaces`), so a caller that passes only
8
+ * modules gets exactly what the modules imply.
9
+ * @returns the complete `architecture.yaml` file content (a deterministic
10
+ * function of the module SET and the surface SET).
11
+ * @throws Error on an unrecognized module (defensive; parse-args rejects first).
12
+ */
13
+ export declare function deriveArchitecture(modules?: string[], surfaces?: string[]): string;
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Derive a scaffolded site's `architecture.yaml` from its selected module set.
3
+ *
4
+ * `deriveArchitecture(modules)` composes the module-independent BASE
5
+ * (module-architecture.ts `ARCHITECTURE_BASE`) with the selected module slices
6
+ * into ONE deterministic `architecture.yaml` document string. The module set is
7
+ * the single source of truth for the result — same set → byte-identical output
8
+ * (no timestamps, stable key/array ordering), so the derivation doubles as the
9
+ * re-runnable sync path (add a module, re-derive, the file updates; re-deriving
10
+ * an unchanged set is a no-op).
11
+ *
12
+ * Zero runtime dependencies (create-ailk is a published, standalone CLI): the
13
+ * YAML is emitted by a small, purpose-built deterministic serializer over the
14
+ * fixed document shape this module produces — no `yaml`/`js-yaml` dependency.
15
+ */
16
+ import { ARCHITECTURE_BASE, MODULE_SLICES, normalizeModules, } from "./module-architecture.js";
17
+ import { CORE_SURFACE_PATHS, RECOGNIZED_SURFACES, resolveSurfaces, } from "./surfaces.js";
18
+ function isScalar(v) {
19
+ return typeof v === "string" || typeof v === "number";
20
+ }
21
+ /** A bare (unquoted-safe) scalar: identifier chars only, not a YAML keyword/number. */
22
+ function isBareSafe(s) {
23
+ if (s === "")
24
+ return false;
25
+ if (!/^[A-Za-z0-9._-]+$/.test(s))
26
+ return false;
27
+ if (/^[0-9]/.test(s))
28
+ return false; // avoid numeric-looking bare scalars
29
+ if (/^(true|false|null|yes|no|on|off|~)$/i.test(s))
30
+ return false;
31
+ return true;
32
+ }
33
+ function scalar(v) {
34
+ if (typeof v === "number")
35
+ return String(v);
36
+ return isBareSafe(v) ? v : JSON.stringify(v); // double-quoted, correctly escaped
37
+ }
38
+ function emitSeq(arr, indent) {
39
+ const pad = " ".repeat(indent);
40
+ const lines = [];
41
+ for (const item of arr) {
42
+ if (isScalar(item)) {
43
+ lines.push(`${pad}- ${scalar(item)}`);
44
+ }
45
+ else if (Array.isArray(item)) {
46
+ // Nested sequence — not produced by our shapes, but handled for safety.
47
+ lines.push(`${pad}-`);
48
+ lines.push(...emitSeq(item, indent + 2));
49
+ }
50
+ else {
51
+ const inner = emitMap(item, indent + 2);
52
+ // Splice the "- " marker onto the first line of the mapping block.
53
+ const first = inner[0] ?? "";
54
+ inner[0] = `${pad}- ${first.slice(indent + 2)}`;
55
+ lines.push(...inner);
56
+ }
57
+ }
58
+ return lines;
59
+ }
60
+ function emitMap(obj, indent) {
61
+ const pad = " ".repeat(indent);
62
+ const lines = [];
63
+ for (const [k, v] of Object.entries(obj)) {
64
+ if (isScalar(v)) {
65
+ lines.push(`${pad}${k}: ${scalar(v)}`);
66
+ }
67
+ else if (Array.isArray(v)) {
68
+ if (v.length === 0) {
69
+ lines.push(`${pad}${k}: []`);
70
+ }
71
+ else {
72
+ lines.push(`${pad}${k}:`);
73
+ lines.push(...emitSeq(v, indent + 2));
74
+ }
75
+ }
76
+ else {
77
+ lines.push(`${pad}${k}:`);
78
+ lines.push(...emitMap(v, indent + 2));
79
+ }
80
+ }
81
+ return lines;
82
+ }
83
+ function emitDocument(doc) {
84
+ return emitMap(doc, 0).join("\n") + "\n";
85
+ }
86
+ // ── Deterministic set helpers ──────────────────────────────────────────────
87
+ /** Sorted unique union of string arrays (a set → a stable, ordered list). */
88
+ function sortedUnion(...lists) {
89
+ const set = new Set();
90
+ for (const list of lists)
91
+ for (const s of list ?? [])
92
+ set.add(s);
93
+ return [...set].sort();
94
+ }
95
+ /** Union of forbidden patterns, deduped by `pattern`, base-first then sorted. */
96
+ function mergeForbidden(base, extra) {
97
+ const seen = new Set();
98
+ const out = [];
99
+ for (const p of base) {
100
+ if (!seen.has(p.pattern)) {
101
+ seen.add(p.pattern);
102
+ out.push(p);
103
+ }
104
+ }
105
+ const sortedExtra = [...extra].sort((a, b) => a.pattern < b.pattern ? -1 : a.pattern > b.pattern ? 1 : 0);
106
+ for (const p of sortedExtra) {
107
+ if (!seen.has(p.pattern)) {
108
+ seen.add(p.pattern);
109
+ out.push(p);
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+ function forbiddenToYaml(p) {
115
+ const m = { pattern: p.pattern, reason: p.reason };
116
+ if (p.paths_excluded && p.paths_excluded.length > 0) {
117
+ m.paths_excluded = [...p.paths_excluded].sort();
118
+ }
119
+ return m;
120
+ }
121
+ function appToYaml(app) {
122
+ const m = {
123
+ path: app.path,
124
+ description: app.description,
125
+ may_import_from: [...app.may_import_from].sort(),
126
+ may_not_import_from: [...app.may_not_import_from].sort(),
127
+ };
128
+ if (app.forbidden_patterns && app.forbidden_patterns.length > 0) {
129
+ m.forbidden_patterns = app.forbidden_patterns.map(forbiddenToYaml);
130
+ }
131
+ return m;
132
+ }
133
+ function packageToYaml(pkg) {
134
+ return {
135
+ description: pkg.description,
136
+ may_import_from: [...pkg.may_import_from].sort(),
137
+ };
138
+ }
139
+ function namespacesToYaml(ns) {
140
+ const members = {};
141
+ const sortedMembers = Object.entries(ns.members).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
142
+ for (const [key, mem] of sortedMembers) {
143
+ members[key] = { path: mem.path, description: mem.description };
144
+ }
145
+ return {
146
+ description: ns.description,
147
+ members,
148
+ rules: [...ns.rules],
149
+ };
150
+ }
151
+ /**
152
+ * Derive the `architecture.yaml` document for a module set.
153
+ *
154
+ * @param modules the selected module names (any order; deduped). Defaults to
155
+ * the same set `parse-args` defaults to when omitted (`['marketing']`).
156
+ * @param surfaces the enabled gateable route surfaces. Omitted ⟹ derived from
157
+ * the module set alone (`resolveSurfaces`), so a caller that passes only
158
+ * modules gets exactly what the modules imply.
159
+ * @returns the complete `architecture.yaml` file content (a deterministic
160
+ * function of the module SET and the surface SET).
161
+ * @throws Error on an unrecognized module (defensive; parse-args rejects first).
162
+ */
163
+ export function deriveArchitecture(modules = ["marketing"], surfaces) {
164
+ const selected = normalizeModules(modules);
165
+ const slices = selected.map((m) => MODULE_SLICES[m]);
166
+ // The declared route surface (#4154). A scaffold's live-route set is a
167
+ // function of this list; the `surfaces:` block below is its machine-readable
168
+ // record, so "which routes does this site declare" is answerable without
169
+ // walking the app directory.
170
+ const enabledSurfaces = surfaces === undefined
171
+ ? resolveSurfaces(selected)
172
+ : [...new Set(surfaces)].sort();
173
+ // apps/web (BASE) — may_import_from filled from the selected modules' webImports.
174
+ const webImports = sortedUnion(...slices.map((s) => s.webImports));
175
+ const apps = {
176
+ web: {
177
+ path: ARCHITECTURE_BASE.web.path,
178
+ description: ARCHITECTURE_BASE.web.description,
179
+ may_import_from: webImports,
180
+ may_not_import_from: [...ARCHITECTURE_BASE.web.may_not_import_from].sort(),
181
+ forbidden_patterns: ARCHITECTURE_BASE.web.forbidden_patterns.map(forbiddenToYaml),
182
+ },
183
+ };
184
+ // Additional apps (api, mcp, workspace) in canonical order.
185
+ const extraApps = {};
186
+ for (const s of slices)
187
+ Object.assign(extraApps, s.apps ?? {});
188
+ for (const key of ["api", "mcp", "workspace"]) {
189
+ const a = extraApps[key];
190
+ if (a)
191
+ apps[key] = appToYaml(a);
192
+ }
193
+ // packages — sorted union across the selected slices.
194
+ const packagesRaw = {};
195
+ for (const s of slices)
196
+ Object.assign(packagesRaw, s.packages ?? {});
197
+ const packages = {};
198
+ const sortedPackages = Object.entries(packagesRaw).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
199
+ for (const [key, pkg] of sortedPackages) {
200
+ packages[key] = packageToYaml(pkg);
201
+ }
202
+ // namespaces — present only if a data-tier module contributes one.
203
+ const nsSlice = slices.find((s) => s.namespaces)?.namespaces;
204
+ // forbidden_patterns — base floor first, then the selected modules' patterns.
205
+ const extraForbidden = [];
206
+ for (const s of slices)
207
+ extraForbidden.push(...(s.forbiddenPatterns ?? []));
208
+ const forbidden = mergeForbidden([...ARCHITECTURE_BASE.forbiddenPatterns], extraForbidden);
209
+ const doc = {
210
+ version: ARCHITECTURE_BASE.version,
211
+ composition_model: {
212
+ reference: ARCHITECTURE_BASE.composition_model.reference,
213
+ tiers: { ...ARCHITECTURE_BASE.composition_model.tiers },
214
+ },
215
+ surfaces: {
216
+ core: [...CORE_SURFACE_PATHS],
217
+ enabled: enabledSurfaces,
218
+ available: [...RECOGNIZED_SURFACES],
219
+ },
220
+ apps,
221
+ packages,
222
+ ...(nsSlice ? { namespaces: namespacesToYaml(nsSlice) } : {}),
223
+ forbidden_patterns: forbidden.map(forbiddenToYaml),
224
+ };
225
+ const header = [
226
+ "# Architecture Boundaries — AI Launch Kit site",
227
+ "#",
228
+ "# GENERATED by create-ailk from the selected module set (--modules).",
229
+ "# The module set is the single source of truth for these boundaries.",
230
+ "# To change them, re-run create-ailk (or re-derive) with the new module",
231
+ "# set — do NOT hand-edit. Enforced by tools/lint-architecture.ts.",
232
+ "#",
233
+ `# Modules: ${selected.join(", ")}`,
234
+ `# Surfaces: ${enabledSurfaces.length > 0 ? enabledSurfaces.join(", ") : "core only"}`,
235
+ "",
236
+ ].join("\n");
237
+ return header + emitDocument(doc);
238
+ }
package/dist/index.d.ts CHANGED
@@ -4,7 +4,12 @@
4
4
  * `dist/cli.js` (per `bin` in package.json).
5
5
  */
6
6
  export { copyTemplate, type CopyTemplateOptions } from "./copy.js";
7
- export { parseCliArgs, ParseError, helpText, type CliOptions, } from "./parse-args.js";
8
- export { scaffold, scaffoldSync, type ScaffoldOptions, type ScaffoldResult, } from "./programmatic.js";
7
+ export { parseCliArgs, parseModules, ParseError, helpText, RECOGNIZED_MODULES, type ModuleName, type CliOptions, } from "./parse-args.js";
8
+ export { CATALOG_TARGET_PATH, FREE_MODULES, LicenseRequiredError, PAID_MODULES, classifyModules, formatSurfaceDrift, scaffold, scaffoldSync, syncArchitectureSync, syncCatalogSync, syncRoutesSync, type ResolvePaidModulesOptions, type ScaffoldOptions, type ScaffoldResult, type SyncArchitectureOptions, type SyncArchitectureResult, type SyncCatalogResult, type SyncRoutesSyncOptions, } from "./programmatic.js";
9
+ export { DEFAULT_AILK_MODULE_REGISTRY_URL, FetchModuleError, fetchModule, type FetchModuleOptions, } from "./lib/fetch-module.js";
10
+ export { extractModuleBundle, type ExtractModuleBundleOptions, } from "./lib/extract-module-bundle.js";
11
+ export { SYNC_ROUTES_HELP, formatSyncRoutesReport, listTemplateRouteDirs, parseSyncRoutesArgs, syncRoutes, type RouteReport, type SyncRoutesOptions, type SyncRoutesResult, } from "./sync-routes.js";
12
+ export { deriveArchitecture } from "./derive-architecture.js";
13
+ export { CORE_ROUTE_DIRS, CORE_SURFACE_PATHS, NAV_CONFIG_PATH, GATEABLE_SURFACES, MODULE_SURFACES, RECOGNIZED_SURFACES, ROUTE_SINCE, SurfaceError, excludedContentPaths, excludedRoutePaths, parseSurfaces, renderNavConfig, resolveSurfaces, surfaceForRouteDir, type Surface, } from "./surfaces.js";
9
14
  export { substituteMarkers, substituteWorkspaceVersions, type MarkerMap, type WorkspaceVersionMap, } from "./substitute.js";
10
15
  export { validateTarget, ValidationError } from "./validate.js";
package/dist/index.js CHANGED
@@ -4,7 +4,24 @@
4
4
  * `dist/cli.js` (per `bin` in package.json).
5
5
  */
6
6
  export { copyTemplate } from "./copy.js";
7
- export { parseCliArgs, ParseError, helpText, } from "./parse-args.js";
8
- export { scaffold, scaffoldSync, } from "./programmatic.js";
7
+ export { parseCliArgs, parseModules, ParseError, helpText, RECOGNIZED_MODULES, } from "./parse-args.js";
8
+ export { CATALOG_TARGET_PATH, FREE_MODULES, LicenseRequiredError, PAID_MODULES, classifyModules, formatSurfaceDrift, scaffold, scaffoldSync, syncArchitectureSync, syncCatalogSync, syncRoutesSync, } from "./programmatic.js";
9
+ // The paid-module fetch/extract primitives (K1, #5089 — Flavor 3). Exported
10
+ // so tooling (and this repo's own evidence-run scripts) can drive the fetch
11
+ // path directly without re-implementing its shape.
12
+ export { DEFAULT_AILK_MODULE_REGISTRY_URL, FetchModuleError, fetchModule, } from "./lib/fetch-module.js";
13
+ export { extractModuleBundle, } from "./lib/extract-module-bundle.js";
14
+ // `create-ailk sync-routes` (#4986) — the template-route drift check + copy.
15
+ // The pure module is exported so tooling can run it against any template dir.
16
+ export { SYNC_ROUTES_HELP, formatSyncRoutesReport, listTemplateRouteDirs, parseSyncRoutesArgs, syncRoutes, } from "./sync-routes.js";
17
+ // The module-set → architecture.yaml derivation. Exported so the sync path
18
+ // (re-derive after a module is added) can re-run it (spec #3787 §2.1). The
19
+ // module→slice registry it composes is an internal detail, deliberately not
20
+ // re-exported.
21
+ export { deriveArchitecture } from "./derive-architecture.js";
22
+ // The route-surface registry (#4154) — which public routes a scaffold carries.
23
+ // Exported so tooling can answer "what surfaces does this site declare" without
24
+ // re-parsing architecture.yaml.
25
+ export { CORE_ROUTE_DIRS, CORE_SURFACE_PATHS, NAV_CONFIG_PATH, GATEABLE_SURFACES, MODULE_SURFACES, RECOGNIZED_SURFACES, ROUTE_SINCE, SurfaceError, excludedContentPaths, excludedRoutePaths, parseSurfaces, renderNavConfig, resolveSurfaces, surfaceForRouteDir, } from "./surfaces.js";
9
26
  export { substituteMarkers, substituteWorkspaceVersions, } from "./substitute.js";
10
27
  export { validateTarget, ValidationError } from "./validate.js";
@@ -0,0 +1,16 @@
1
+ export interface ExtractModuleBundleOptions {
2
+ /** The fetched bundle bytes (a gzipped tar archive). */
3
+ bytes: Uint8Array;
4
+ /** The already-scaffolded target directory the module's files land in. */
5
+ targetDir: string;
6
+ /** The module name — used only for error messages and staging dir naming. */
7
+ moduleName: string;
8
+ }
9
+ /**
10
+ * Extract a fetched module bundle into `targetDir`, merging its files onto
11
+ * the tree `copyTemplate` already wrote. Throws on any unsafe entry,
12
+ * decompress error, or limit overrun — `targetDir` is left untouched on
13
+ * failure (validation completes in a throwaway staging dir before any file
14
+ * is copied into place).
15
+ */
16
+ export declare function extractModuleBundle(options: ExtractModuleBundleOptions): Promise<void>;