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
@@ -38,3 +38,41 @@ STRIPE_WEBHOOK_SECRET=whsec_xxx
38
38
  # Must match OSS_API_INTERNAL_SECRET in apps-paid/marketing-api/.env.local.
39
39
  # Generate with: openssl rand -hex 32
40
40
  # OSS_API_INTERNAL_SECRET=your-shared-secret-here
41
+
42
+ # =============================================================================
43
+ # Scheduling — the `booker` section's provider (#4416)
44
+ # =============================================================================
45
+ # SERVER-SIDE ONLY. The browser never receives these: the booker section calls
46
+ # this app's /v1/schedule/availability + /v1/schedule/book, and those handlers
47
+ # hold the credential. Never expose any of these as NEXT_PUBLIC_*.
48
+ #
49
+ # Unset CAL_API_KEY is a supported state, not a broken one — the routes answer
50
+ # 503 not_configured with the provider's public booking page, and the section
51
+ # renders a link out to it rather than an error.
52
+ # CAL_API_KEY=cal_live_xxx
53
+ # Self-hosted Cal instances only; defaults to https://api.cal.com.
54
+ # CAL_API_BASE_URL=https://api.cal.com
55
+ # Host used to build the degraded state's link out; defaults to https://cal.com.
56
+ # SCHEDULING_PUBLIC_BASE_URL=https://cal.com
57
+ # Provider selector. Only "cal" is implemented today; the self-hosted engine
58
+ # (#4288) lands as a second value here with no change to the section.
59
+ # SCHEDULING_PROVIDER=cal
60
+
61
+ # ── Project listings — site addressing (#5048 D2) ───────────────────────────
62
+ # AILK_SITE_ID is this deployment's own site identifier. Unset means "default".
63
+ # It is read SERVER-SIDE only; no request body carries a site identifier.
64
+ # AILK_SITE_ID=default
65
+ #
66
+ # AILK_LISTING_PUBLIC_KEY is the PUBLIC site key an anonymous founder
67
+ # application and the public listings read name this site by. It is not a
68
+ # credential: it ships in browser JavaScript and in an agent's request, and
69
+ # holding it grants only what a public application form grants. The server maps
70
+ # it to AILK_SITE_ID.
71
+ #
72
+ # This is the SINGLE-TENANT path — the default create-ailk scaffold, one
73
+ # customer per deployment, no database row required. A multi-tenant deployment
74
+ # instead writes SiteListingConfig.public_key per site, which is consulted
75
+ # first. With neither set, every application and every public read answers 400
76
+ # unknown_site_key, which is the correct closed default but gives no clue at
77
+ # boot — so set this if the deployment accepts listings.
78
+ # AILK_LISTING_PUBLIC_KEY=
@@ -17,11 +17,24 @@ Every endpoint here has a 1:1 MCP tool in `apps/mcp`. When you add, change, or r
17
17
  Routes are versioned under `/v1/*`:
18
18
 
19
19
  - `/v1/leads/{submit,subscribe,callback}` — lead capture, newsletter subscription, callback request
20
+ - `/v1/flows/:slug` (GET), `/v1/flows/:slug/steps` (POST) — serve a flow config + submit a step's answers; server-side per-step partial-state persistence (#3956)
21
+ - `/v1/flows/:slug/aggregate` (GET) — anonymous, site-scoped per-question response counts across all completed respondents for the results reveal (#4771): respondents are completed `FlowSession` rows (not `Lead` rows — a recommending-mode respondent has no Lead until the email moment), question metadata + the chart flag come from the `WaitlistExperiment` register, and only `resultsReveal`-flagged `single`/`multi` questions are returned (`src/services/flow-aggregate.ts`). No individual answer, email, name, session id, or score in the response; no auth. No MCP twin — recorded exception (an agent walking a flow already gets everything it needs from `submit_flow_step`'s own response; "how everyone else answered" changes none of it).
22
+ - `/v1/flows/:slug/save` (POST), `/v1/flows/:slug/checkout` (POST) — the recommender's email moment (#4841): `save` creates the FlowSession + Lead (+ the T+0 DeliverableGrant) for the permalink's answers; `checkout` does the same, records the `FlowCheckout` buyer row at a SERVER-recomputed `price()` (the body carries no amount — `flowCheckoutInputSchema` is strict), and opens a Stripe TEST-mode Checkout Session whose metadata carries the permalink + offer key (`src/routes/flows/recommender.ts`, `src/services/recommender-capture.ts`, `packages/stripe-client`'s `createQuotedCheckoutSession`). Anonymous, rate-limited; a non-`sk_test_` key is refused before any side effect. No MCP twin — recorded exception: an agent walking a flow has no email to give and no card to pay with; the anonymous MCP surface is identity-blind.
20
23
  - `/v1/content/{types,:type,:type/:slug}` — public content reads
21
24
  - `/v1/auth/tokens`, `/v1/user/{profile,data/:key}` — local auth + user data
22
25
  - `/v1/checkout/sessions` — start a Stripe checkout
26
+ - `/v1/workspaces/:workspaceId/{theme,identity,seo}` (GET/PUT) — per-workspace site config (multi-tenant module)
27
+ - `/v1/billing` (GET), `/v1/billing/portal-session` (POST) — org-scoped billing read + Stripe customer-portal session creation
28
+ - `/v1/schedule/availability` (GET), `/v1/schedule/event-meta` (GET), `/v1/schedule/book` (POST) — anonymous scheduling proxy behind the provider seam (`src/services/scheduling/`); Cal.com v2 today, a self-hosted engine later, same three calls. `event-meta` is the meta-only read (title · duration · description · price) so rendering an event's facts never fetches an availability window (#4633). `CAL_API_KEY` is read server-side only. MCP twins: `list_availability` / `get_event_meta` / `create_booking` (#4416, #4633)
29
+ - `/v1/aeo/score` (POST), `/v1/aeo/score/example` (GET) — anonymous instant AEO score for a respondent-supplied URL, and the bundled pre-launch example, both fed by the SSRF-guarded crawler at `@working-theory/aeo/fetch` and the pure scorer at `@working-theory/aeo` (`src/services/aeo-score.ts`, #4666). No MCP twin — recorded exception, brief D7 (exposing an arbitrary-URL crawler to anonymous agents is a security-posture decision; `apps/mcp/src/tools/audit.ts` deliberately stays same-origin-locked instead).
30
+ - `/v1/waitlist-experiments` (GET), `/v1/waitlist-experiments/:experimentId` (GET), `/v1/waitlist-experiments/:experimentId/signups` (GET), `/v1/waitlist-experiments/:experimentId/signups/:leadId` (GET) — the operator-dashboard read API for Parallel Waitlist Validation (#4665 D7, B0): tenant-scoped list + rollup, per-waitlist comparison, paginated signups, and a signup drill-down over A1's `WaitlistExperiment` / `WaitlistScore` / `Lead` rows (`src/services/waitlist-dashboard.ts`, #4671). Role floor `owner|admin` (signup PII); the platform-operator scope (`isSentinel(organizationId) && role === "owner"`, ALSO requiring `AILK_OPERATOR_EMAIL` to be set — fail-closed, PR #4687) sees every site, an ordinary owner/admin sees only its own `siteId`. No MCP twin — identity-bound tenant routes (#3591 exception, same shape as `/v1/billing/*`).
31
+ - `/v1/waitlist-signups/me` (GET, `?experimentKey=<slug>`) — the respondent read (#4731): a signed-in, **email-verified** user's OWN newest signup for one experiment (`experimentKey`, `waitlistKey`, `completedAt`, `tier`, `score`, `aeoScore`, `answers.q3` — seven fields, nothing more; `src/services/waitlist-signups.ts` is the only read path). Registered in `authScope` only (auth, no tenant guard — a respondent has no workspace). Identity is `request.userId`; the email is the `User`'s, never a parameter; `emailVerified !== true` → 403 `email_unverified` before any `Lead` read; no match → 404 `signup_not_found`; every read scoped to `currentSiteId()`. No MCP twin — identity-bound (#3591 exception).
32
+ - `/v1/flow-checkouts/me` (GET) — the respondent purchases read (#4984, FEAT-022 M2): a signed-in, **email-verified** user's OWN `FlowCheckout` rows, newest first, `[]` when none (`id`, `flowSlug`, `experimentKey`, `offerKey`, `status`, `amountMinor`, `currency`, `period`, `completedAt`, `createdAt` — ten fields, nothing more; `src/services/flow-checkouts.ts` is the only read path). Registered in `authScope` only, beside `/v1/waitlist-signups/me`. Identity is `request.userId`; rows are joined through the promotion link (`Lead.promotedUserId = userId`, `src/services/lead-promotion.ts`) — never by an email, and no query parameter is read; `emailVerified !== true` → 403 `email_unverified` before any `Lead` read; every read scoped to `currentSiteId()`. No MCP twin — identity-bound (#3591 exception).
33
+ - `/v1/project-listings/me` (GET) — the FOUNDER'S OWN listings read (#5295): a signed-in user's own `ProjectListing` rows, newest first, `[]` when none. Registered in `authScope` only, beside `/v1/flow-checkouts/me` — a founder is not a workspace member, so the tenant guard's default-deny would answer 403 for their own submission. Identity is `request.userId`; rows are joined through the owner link (`ProjectListing.ownerUserId = userId`, stamped by `src/services/listing-promotion.ts`) — **never** by `founderEmail`, at any stage, and no query parameter is read. `founderEmail` is an unverified string typed into an anonymous form, so a read-time email match would hand one of two people sharing an address the other's submission. The row shape is `projectListingDraftSchema` (the founder-facing shape the anonymous draft read already uses — no `siteId`, `leadId`, `decidedBy`, `issueUrl`, or `experimentKey`). The route is ADDITIVE: `PROJECT_LISTING_ROLES` stays `owner|admin` and the tenant-scoped list/get/patch routes are unchanged. No MCP twin — identity-bound (#3591 exception).
23
34
 
24
- AEO Layer 1 scoring runs locally as a CLI command (`ailk audit`), not an HTTP endpoint.
35
+ The workspace site-config routes are **identity-bound tenant routes** (guarded by the tenant preHandler; the write scope is the caller's active workspace, never a body-supplied id). Like the sibling `/v1/workspaces/*` routes they have **no anonymous MCP twin** — the OSS MCP surface is identity-blind (`apps/mcp/CLAUDE.md`), so the "1:1 MCP tool" rule above does not apply to them; the tenant-scoped authed MCP surface is tracked in #3591. The `/v1/billing/*` and `/v1/waitlist-experiments/*` routes are the same shape — identity-bound tenant routes, admin/settings-facing rather than agent-facing, no MCP twin.
36
+
37
+ AEO Layer 1 scoring runs both ways: locally as a CLI command (`ailk audit`, filesystem content-root input) AND behind the anonymous `/v1/aeo/score` HTTP endpoint above (external-URL input, #4666) — the CLI's content-root audit and the route's crawler-fed score are two different input paths over the same underlying scorer, not a contradiction.
25
38
 
26
39
  JSON in, JSON out. Validate inputs with `@working-theory/validation`. Response envelope:
27
40
 
@@ -36,12 +49,56 @@ Capture → persist (DB or file) → notify operator → return success. That's
36
49
 
37
50
  Routing rules, enrichment, dedupe, webhook fan-out, CRM integration live in `@working-theory/lead-routing`, loaded via JWT entitlement check. Never hardcode routing logic here — the boundary is what makes paid additive.
38
51
 
52
+ ## Services (billing-ledger)
53
+
54
+ - `src/services/usage-metering.ts` — the write path for a completed AI call: cost → markup → write, in one `$transaction` (`UsageEvent` insert + `UsagePeriod` upsert).
55
+ - `src/services/usage-aggregation.ts` — sums an org/period's `UsageEvent` rows into the `UsageBillingReport` row (meter → aggregate → report).
56
+ - `src/services/usage-credits.ts` — the credit waterfall; the sanctioned tenant-scope exception that reads/writes `Organization`'s on-demand credit balance.
57
+
58
+ These own every billing-ledger mutation — don't write `UsageEvent`/`UsagePeriod`/`UsageBillingReport`/`Organization` balance fields from a route handler directly.
59
+
39
60
  ## Persistence
40
61
 
41
62
  - DB adapter is the default. File fallback exists for zero-config OSS use.
42
63
  - Don't assume a DB is configured. Read `AILK_DB_URL` and degrade gracefully.
43
64
  - Migrations in `database/migrations`. Never edit a shipped migration — add a new one.
44
65
 
66
+ ## Scheduled sweeps (external cron)
67
+
68
+ Stateless, idempotent bins an external scheduler runs (Vercel Cron / GitHub
69
+ Actions cron / plain crontab) — this repo has no queue or in-process timer
70
+ (D1). Dev: `pnpm --filter @working-theory/api <script>`. Production:
71
+ `node dist/bin/<name>.js`, on whatever cadence the deployment chooses;
72
+ a SEQUENTIAL re-run is always a no-op for already-processed rows, via each
73
+ sweep's own DB constraint (never a caller-side lock).
74
+
75
+ - `abandon:sweep` (`src/bin/abandon-sweep.ts`, #3962) — sends (or audits, in
76
+ `dark` mode) the configured `abandonEmail` follow-up for an incomplete flow
77
+ session past its `delayMinutes` window. Idempotent via `FlowSession.abandonEmailStatus`.
78
+ - `followup:sweep` (`src/bin/followup-sweep.ts`, #4732) — sends each due
79
+ `(lead, followUpKey)` pair from a completed flow session's `followUps`
80
+ register, tier-gated and suppressed on a booked call or a Resend
81
+ unsubscribe. Idempotent via `waitlist_followup_sends`'
82
+ `@@unique([leadId, followUpKey])`; a CONCURRENT overlapping run racing the
83
+ same pair is caught (the unique-constraint violation is swallowed and
84
+ logged, not surfaced as a sweep failure) rather than aborting the whole
85
+ run — the narrow race window between the idempotency check and the send
86
+ itself is not closed (a genuinely overlapping invocation could still
87
+ double-send that one email), so avoid overlapping invocations of the same
88
+ bin; a missed tick is still harmless either way.
89
+ - `listing-csv:sweep` (`src/bin/listing-csv-sweep.ts`, #5001) — the WEEKLY
90
+ founder CSV: for each `live` `ProjectListing`, the `WaitlistScore` rows for
91
+ its experiment newer than the last `ListingCsvSend` become one CSV, stored
92
+ as a `DeliverableAsset` (`listing-{slug}-{yyyy-mm-dd}`, `text/csv`), granted
93
+ to the founder's own `Lead`, and emailed as a
94
+ `GET /v1/deliverables/:grantId` capability link — the founder's list with no
95
+ login. Idempotent via the `ListingCsvSend` watermark: no signup newer than
96
+ the last send means no asset, no grant, no email. The stamp is written only
97
+ after a SUCCESSFUL send, so a failed send leaves those rows for the next
98
+ run rather than losing them. Per-listing failures are logged (PII-safe) and
99
+ never stop the listings after them. The CONSUMER schedules this weekly;
100
+ this repo adds no cron of its own.
101
+
45
102
  ## Error handling
46
103
 
47
104
  - Never leak stack traces in responses. Log them, return a code.
@@ -61,3 +118,23 @@ Routing rules, enrichment, dedupe, webhook fan-out, CRM integration live in `@wo
61
118
  - Don't return 200 with `{ ok: false }`.
62
119
  - Don't read MDX directly — use `@working-theory/content-adapters`.
63
120
  - Don't put session state in `apps/api`. It's stateless.
121
+
122
+ Last updated: 2026-09-12 — doc-sync: added `GET /v1/project-listings/me` (#5295), the auth-scoped founder read joined on the owner link, to Endpoint conventions — verified against `apps/api/src/routes/project-listings/me.ts` and `apps/api/src/server.ts`.
123
+
124
+ Prior: 2026-09-07 — doc-sync: added `listing-csv:sweep` (#5001), the weekly founder-CSV sweep, to `## Scheduled sweeps (external cron)` — verified against `apps/api/src/bin/listing-csv-sweep.ts` and `apps/api/package.json`.
125
+
126
+ Prior: 2026-09-04 — doc-sync: added the `## Scheduled sweeps (external cron)` section documenting `abandon:sweep` and `followup:sweep` (#4732 AC-6) — verified against `apps/api/package.json` and `apps/api/src/bin/`.
127
+
128
+ Prior: 2026-09-04 — doc-sync: added `GET /v1/waitlist-signups/me` (#4731), the auth-scoped respondent read, to Endpoint conventions — verified against `apps/api/src/routes/waitlist-signups/index.ts` and `apps/api/src/server.ts`.
129
+
130
+ Prior: 2026-09-02 — doc-sync: noted the `AILK_OPERATOR_EMAIL` fail-closed precondition on the platform-operator scope in the `/v1/waitlist-experiments/*` row (PR #4687 security review, High finding) — verified against `apps/api/src/services/waitlist-dashboard.ts`.
131
+
132
+ Prior: 2026-09-02 — doc-sync: added `/v1/waitlist-experiments/*` routes (#4665 D7, #4671) to Endpoint conventions — verified against `apps/api/src/routes/waitlist-experiments/index.ts`.
133
+
134
+ Prior: 2026-08-31 — doc-sync: added `GET /v1/schedule/event-meta` (#4633), the meta-only scheduling read, to the `/v1/schedule/*` row — verified against `apps/api/src/routes/schedule/index.ts`.
135
+
136
+ Prior: 2026-08-26 — doc-sync: added `/v1/schedule/*` routes (#4416) to Endpoint conventions — verified against `apps/api/src/routes/schedule/index.ts`.
137
+
138
+ Prior: 2026-08-10 — doc-sync: added `/v1/flows/*` routes (#3956) to Endpoint conventions — verified against `apps/api/src/routes/flows/index.ts`.
139
+
140
+ Prior: 2026-07-15 — doc-sync: added `/v1/billing/*` routes (#3701) to Endpoint conventions; added the `## Services (billing-ledger)` section documenting `usage-metering.ts` / `usage-aggregation.ts` / `usage-credits.ts` — verified against `apps/api/src/routes/billing/index.ts` and `apps/api/src/services/`.
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for describing the origin of the Work and
141
+ reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Support. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or support.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 Tailwind AI
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -1,144 +1,9 @@
1
1
  /**
2
2
  * Vercel Serverless Function Handler for Customer Template Backend
3
- * This file wraps the Fastify server for Vercel's serverless functions
3
+ *
4
+ * Thin re-export — the adapter logic lives in ../src/vercel-handler.ts so it
5
+ * sits under apps/api/src, which is what both tsconfig.json's `include` and
6
+ * jest.config.cjs's `roots` reach (this apps/api/api/ directory is outside
7
+ * both, so nothing here is type-checked or tested directly).
4
8
  */
5
-
6
- import { logger } from '@working-theory/observability';
7
- import type { VercelRequest, VercelResponse } from '@vercel/node';
8
-
9
- import type { build as buildServer } from '../src/server.js';
10
-
11
- type FastifyServer = Awaited<ReturnType<typeof buildServer>>;
12
-
13
- // Import the build function from server
14
- async function getBuildFunction(): Promise<typeof buildServer> {
15
- try {
16
- const srcModule = await import('../src/server.js');
17
- logger.info('[Vercel Handler] Using server from src/server.js');
18
- return srcModule.build;
19
- } catch (srcError) {
20
- logger.error(
21
- {
22
- err: srcError instanceof Error ? srcError.message : String(srcError),
23
- stack: srcError instanceof Error ? srcError.stack : undefined,
24
- },
25
- '[Vercel Handler] Failed to import server',
26
- );
27
- throw new Error(`Cannot find server module: ${srcError instanceof Error ? srcError.message : String(srcError)}`, { cause: srcError });
28
- }
29
- }
30
-
31
- // Initialize build function
32
- const buildPromise = getBuildFunction();
33
- let serverInstance: FastifyServer | null = null;
34
-
35
- /**
36
- * Get or create the Fastify server instance
37
- */
38
- async function getServer() {
39
- if (!serverInstance) {
40
- logger.info('[Vercel Handler] Building server instance...');
41
- const startTime = Date.now();
42
-
43
- try {
44
- const buildTimeout = new Promise<never>((_, reject) => {
45
- setTimeout(() => reject(new Error('Server build timeout after 10s')), 10000);
46
- });
47
-
48
- const build = await Promise.race([buildPromise, buildTimeout]);
49
- logger.info('[Vercel Handler] Build function obtained, creating server...');
50
-
51
- const initTimeout = new Promise<never>((_, reject) => {
52
- setTimeout(() => reject(new Error('Server initialization timeout after 10s')), 10000);
53
- });
54
-
55
- serverInstance = await Promise.race([build(), initTimeout]);
56
-
57
- const buildTime = Date.now() - startTime;
58
- logger.info({ buildTime }, '[Vercel Handler] Server built successfully');
59
- } catch (error) {
60
- const buildTime = Date.now() - startTime;
61
- logger.error({ err: error, buildTime }, '[Vercel Handler] Failed to build server');
62
- throw new Error(`Server build failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
63
- }
64
- }
65
- return serverInstance;
66
- }
67
-
68
- /**
69
- * Vercel serverless function handler
70
- */
71
- export default async function handler(
72
- req: VercelRequest,
73
- res: VercelResponse
74
- ): Promise<void> {
75
- const timeout = setTimeout(() => {
76
- if (!res.headersSent) {
77
- logger.error('[Vercel Handler] Request timeout');
78
- res.status(504).json({
79
- error: 'Gateway Timeout',
80
- message: 'Request took too long to process',
81
- });
82
- }
83
- }, 25000);
84
-
85
- try {
86
- logger.info({ method: req.method, url: req.url }, '[Vercel Handler] Starting request');
87
-
88
- const server = await getServer();
89
-
90
- const url = new URL(req.url || '/', 'http://localhost');
91
- const pathname = url.pathname;
92
-
93
- logger.info({ method: req.method, pathname }, '[Vercel Handler] Processing request');
94
-
95
- const fastifyRequest = {
96
- method: req.method || 'GET',
97
- url: pathname,
98
- headers: req.headers as Record<string, string>,
99
- body: req.body,
100
- query: req.query as Record<string, string>,
101
- };
102
-
103
- const response = await server.inject(fastifyRequest);
104
-
105
- logger.info({ status: response.statusCode }, '[Vercel Handler] Response status');
106
-
107
- clearTimeout(timeout);
108
-
109
- res.status(response.statusCode);
110
-
111
- Object.entries(response.headers).forEach(([key, value]) => {
112
- if (value !== undefined && !res.headersSent) {
113
- const headerValue = Array.isArray(value)
114
- ? value.map((v) => String(v)).join(', ')
115
- : String(value);
116
- res.setHeader(key, headerValue);
117
- }
118
- });
119
-
120
- if (!res.getHeader('Content-Type') && !res.headersSent) {
121
- res.setHeader('Content-Type', 'application/json');
122
- }
123
-
124
- if (!res.headersSent) {
125
- const body = typeof response.body === 'string'
126
- ? response.body
127
- : JSON.stringify(response.body);
128
-
129
- res.send(body);
130
- logger.info('[Vercel Handler] Response sent successfully');
131
- }
132
- } catch (error) {
133
- clearTimeout(timeout);
134
-
135
- logger.error({ err: error }, '[Vercel Handler] Error handling request');
136
-
137
- if (!res.headersSent) {
138
- res.status(500).json({
139
- error: 'Internal Server Error',
140
- message: error instanceof Error ? error.message : String(error),
141
- });
142
- }
143
- }
144
- }
9
+ export { default } from '../src/vercel-handler.js';
@@ -30,8 +30,21 @@ module.exports = {
30
30
  // forms to the same shared mock.
31
31
  '^@working-theory/database$': '<rootDir>/src/lib/__mocks__/prisma-client.js',
32
32
  '^.*database/generated/client/(index|client)\\.(js|ts)$': '<rootDir>/src/lib/__mocks__/prisma-client.js',
33
+ // The tenancy constants subpath (#3627) — real TS source, not a mock: the
34
+ // `database/tenancy.ts` module has no external boundary to fake, so map
35
+ // straight to source, matching the workspace-package-to-src pattern below.
36
+ '^@working-theory/database/tenancy$': '<rootDir>/../../database/tenancy.ts',
37
+ // The flow-presets data subpath (#3958) — same real-TS-source rationale
38
+ // as tenancy above: FLOW_PRESETS is plain data with no external boundary
39
+ // to fake, so map straight to source rather than requiring a package build.
40
+ '^@working-theory/database/flows/presets$': '<rootDir>/../../database/flows/presets.ts',
41
+ // The shared listing-diagnostic scoring register (#5001) — same
42
+ // real-TS-source rationale as flows/presets above.
43
+ '^@working-theory/database/flows/listing-diagnostic$': '<rootDir>/../../database/flows/listing-diagnostic.ts',
33
44
  // Map workspace packages to their TypeScript source so ts-jest compiles them
34
45
  // directly (the published dist is ESM, which Jest's CJS preset can't load).
46
+ '^@working-theory/aeo/fetch$': '<rootDir>/../../packages/aeo/src/fetch/index.ts',
47
+ '^@working-theory/aeo$': '<rootDir>/../../packages/aeo/src/index.ts',
35
48
  '^@working-theory/analytics/server$': '<rootDir>/../../packages/analytics/src/server/index.ts',
36
49
  '^@vercel/analytics/server$': '<rootDir>/../../packages/analytics/__mocks__/vercel-analytics-server.ts',
37
50
  '^@working-theory/common$': '<rootDir>/../../packages/common/src/index.ts',
@@ -39,11 +52,14 @@ module.exports = {
39
52
  '^@working-theory/content-projection$': '<rootDir>/../../packages/content-projection/src/index.ts',
40
53
  '^@working-theory/content-projection/node$': '<rootDir>/../../packages/content-projection/src/node.ts',
41
54
  '^@working-theory/email$': '<rootDir>/../../packages/email/src/index.ts',
55
+ '^@working-theory/ids$': '<rootDir>/../../packages/ids/src/index.ts',
42
56
  '^@working-theory/license$': '<rootDir>/../../packages/license/src/index.ts',
43
57
  '^@working-theory/observability$': '<rootDir>/../../packages/observability/src/index.ts',
44
58
  '^@working-theory/schema/faq$': '<rootDir>/../../packages/schema/src/faq.ts',
45
59
  '^@working-theory/schema$': '<rootDir>/../../packages/schema/src/index.ts',
60
+ '^@working-theory/site-config/schema$': '<rootDir>/../../packages/site-config/src/schema/index.ts',
46
61
  '^@working-theory/schema-pack-registry$': '<rootDir>/../../packages/schema-pack-registry/src/index.ts',
62
+ '^@working-theory/schema-validator$': '<rootDir>/../../packages/schema-validator/src/index.ts',
47
63
  '^@working-theory/stripe-client$': '<rootDir>/../../packages/stripe-client/src/index.ts',
48
64
  '^@working-theory/validation$': '<rootDir>/../../packages/validation/src/index.ts',
49
65
  '^(\\.{1,2}/.*)\\.js$': '$1',
@@ -7,10 +7,20 @@
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "dev": "tsx watch src/cli.ts",
10
+ "abandon:sweep": "tsx src/bin/abandon-sweep.ts",
11
+ "followup:sweep": "tsx src/bin/followup-sweep.ts",
12
+ "listing-csv:sweep": "tsx src/bin/listing-csv-sweep.ts",
13
+ "retention:sweep": "tsx src/bin/session-retention-sweep.ts",
14
+ "deliverable:upload": "tsx src/bin/deliverable-upload.ts",
15
+ "deliverable:resend": "tsx src/bin/deliverable-resend.ts",
16
+ "seed:presets": "tsx src/bin/seed-presets.ts",
10
17
  "build": "tsc",
11
18
  "build:vercel": "cd ../../database && pnpm exec prisma generate && cd ../.. && pnpm --filter @working-theory/validation build && pnpm --filter @working-theory/api build && mkdir -p apps/api/public && echo '{}' > apps/api/public/.vercel",
12
19
  "start": "node dist/cli.js",
13
- "lint": "eslint src --ext .ts",
20
+ "smoke:dev": "node -e \"const{spawn}=require('child_process');const http=require('http');const PORT=process.env.PORT||'3002';const SLUG=process.env.SMOKE_FLOW_SLUG||'smoke-check';const child=spawn('pnpm',['exec','tsx','watch','src/cli.ts'],{env:process.env,stdio:'ignore'});let done=false;function finish(code){if(done)return;done=true;try{child.kill();}catch(e){}process.exit(code);}function poll(attempt){if(attempt>40){console.error('smoke:dev - timeout waiting for server');finish(1);return;}const req=http.get({host:'127.0.0.1',port:PORT,path:'/v1/flows/'+SLUG},(res)=>{console.log('smoke:dev - GET /v1/flows/'+SLUG+' -> HTTP '+res.statusCode);res.resume();finish(0);});req.on('error',()=>{setTimeout(()=>poll(attempt+1),500);});}child.on('exit',(code)=>{if(!done){console.error('smoke:dev - child exited early with code '+code);finish(1);}});setTimeout(()=>poll(0),500);\"",
21
+ "smoke:build": "node -e \"const{spawn}=require('child_process');const http=require('http');const PORT=process.env.PORT||'3002';const SLUG=process.env.SMOKE_FLOW_SLUG||'smoke-check';const child=spawn('node',['dist/cli.js'],{env:process.env,stdio:'ignore'});let done=false;function finish(code){if(done)return;done=true;try{child.kill();}catch(e){}process.exit(code);}function poll(attempt){if(attempt>40){console.error('smoke:build - timeout waiting for server');finish(1);return;}const req=http.get({host:'127.0.0.1',port:PORT,path:'/v1/flows/'+SLUG},(res)=>{console.log('smoke:build - GET /v1/flows/'+SLUG+' -> HTTP '+res.statusCode);res.resume();finish(0);});req.on('error',()=>{setTimeout(()=>poll(attempt+1),500);});}child.on('exit',(code)=>{if(!done){console.error('smoke:build - child exited early with code '+code);finish(1);}});setTimeout(()=>poll(0),500);\"",
22
+ "smoke": "pnpm run smoke:dev && pnpm run smoke:build",
23
+ "lint": "tsx ../../scripts/lint-package.ts",
14
24
  "test": "jest",
15
25
  "test:watch": "jest --watch",
16
26
  "test:coverage": "jest --coverage",
@@ -20,24 +30,29 @@
20
30
  "db:studio": "cd ../../database && prisma studio"
21
31
  },
22
32
  "dependencies": {
33
+ "@fastify/cors": "^11.2.0",
34
+ "@fastify/rate-limit": "^10.3.0",
35
+ "@prisma/adapter-pg": "^7.8.0",
36
+ "@prisma/client": "^7.8.0",
37
+ "@working-theory/aeo": "workspace:*",
23
38
  "@working-theory/analytics": "workspace:*",
24
39
  "@working-theory/common": "workspace:*",
25
40
  "@working-theory/content-adapters": "workspace:*",
26
41
  "@working-theory/content-projection": "workspace:*",
27
42
  "@working-theory/database": "workspace:*",
28
43
  "@working-theory/email": "workspace:*",
44
+ "@working-theory/ids": "workspace:*",
29
45
  "@working-theory/license": "workspace:*",
30
46
  "@working-theory/observability": "workspace:*",
31
47
  "@working-theory/schema": "workspace:*",
48
+ "@working-theory/site-config": "workspace:*",
32
49
  "@working-theory/stripe-client": "workspace:*",
33
50
  "@working-theory/validation": "workspace:*",
34
- "@fastify/cors": "^11.2.0",
35
- "@fastify/rate-limit": "^10.3.0",
36
- "@prisma/adapter-pg": "^7.8.0",
37
- "@prisma/client": "^7.8.0",
38
51
  "dotenv": "^17.4.2",
39
- "fastify": "^5.7.2",
52
+ "fastify": "^5.12.1",
53
+ "pdf-lib": "^1.17.1",
40
54
  "pg": "^8.22.0",
55
+ "yaml": "^2.9.0",
41
56
  "zod": "^4.2.1"
42
57
  },
43
58
  "devDependencies": {
@@ -46,6 +61,7 @@
46
61
  "@types/pg": "^8.20.0",
47
62
  "@vercel/node": "^5.8.22",
48
63
  "jest": "^30.4.2",
64
+ "pdfjs-dist": "^6.3.289",
49
65
  "prisma": "^7.8.0",
50
66
  "ts-jest": "^29.4.11",
51
67
  "tsx": "^4.22.4",