create-ailk 0.1.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 (533) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +39 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +80 -0
  5. package/dist/copy.d.ts +8 -0
  6. package/dist/copy.js +109 -0
  7. package/dist/index.d.ts +10 -0
  8. package/dist/index.js +10 -0
  9. package/dist/lib/pro-callout.d.ts +12 -0
  10. package/dist/lib/pro-callout.js +20 -0
  11. package/dist/parse-args.d.ts +13 -0
  12. package/dist/parse-args.js +81 -0
  13. package/dist/programmatic.d.ts +49 -0
  14. package/dist/programmatic.js +89 -0
  15. package/dist/substitute.d.ts +31 -0
  16. package/dist/substitute.js +45 -0
  17. package/dist/validate.d.ts +8 -0
  18. package/dist/validate.js +70 -0
  19. package/package.json +47 -0
  20. package/templates/.claude/.gitkeep +0 -0
  21. package/templates/.claude/agents/web.md +80 -0
  22. package/templates/.claude/rules/architecture.md +62 -0
  23. package/templates/.claude/rules/preserve-existing-style.md +51 -0
  24. package/templates/.claude/skills/README.md +43 -0
  25. package/templates/.claude/skills/add-schema/SKILL.md +270 -0
  26. package/templates/.claude/skills/add-schema/references/conflict-handling.md +200 -0
  27. package/templates/.claude/skills/add-schema/references/file-finding.md +123 -0
  28. package/templates/.claude/skills/add-schema/references/schema-types.md +131 -0
  29. package/templates/.claude/skills/audit-site/SKILL.md +213 -0
  30. package/templates/.claude/skills/audit-site/references/common-errors.md +113 -0
  31. package/templates/.claude/skills/audit-site/references/findings-glossary.md +138 -0
  32. package/templates/.claude/skills/audit-site/references/severity-levels.md +114 -0
  33. package/templates/.claude/skills/provision-config/SKILL.md +243 -0
  34. package/templates/.claude/skills/provision-config/references/env-vars-template.md +184 -0
  35. package/templates/.claude/skills/provision-config/references/runbook-template.md +248 -0
  36. package/templates/.claude/skills/provision-config/references/vercel-json-template.md +98 -0
  37. package/templates/.claude/skills/scaffold-auth/SKILL.md +261 -0
  38. package/templates/.claude/skills/scaffold-auth/references/env-vars.md +91 -0
  39. package/templates/.claude/skills/scaffold-auth/references/oauth-app-setup.md +171 -0
  40. package/templates/.claude/skills/scaffold-commerce/SKILL.md +310 -0
  41. package/templates/.claude/skills/scaffold-commerce/references/lookup-keys-template.md +71 -0
  42. package/templates/.claude/skills/scaffold-commerce/references/marketplace-brand-pages.md +83 -0
  43. package/templates/.claude/skills/scaffold-commerce/templates/marketplace-cta-route.tsx.tmpl +72 -0
  44. package/templates/.claude/skills/scaffold-page/SKILL.md +243 -0
  45. package/templates/.claude/skills/scaffold-page/references/page-types.md +169 -0
  46. package/templates/.claude/skills/scaffold-page/templates/content.mdx.tmpl +28 -0
  47. package/templates/.claude/skills/scaffold-page/templates/route.tsx.tmpl +28 -0
  48. package/templates/.claude/skills/suggest-site-pages/SKILL.md +242 -0
  49. package/templates/.claude/skills/suggest-site-pages/references/categories.md +287 -0
  50. package/templates/.env.example +205 -0
  51. package/templates/.gitkeep +2 -0
  52. package/templates/CLAUDE.md +142 -0
  53. package/templates/CONVENTIONS.md +222 -0
  54. package/templates/README.md +110 -0
  55. package/templates/apps/api/.env.example +40 -0
  56. package/templates/apps/api/CLAUDE.md +63 -0
  57. package/templates/apps/api/api/index.ts +144 -0
  58. package/templates/apps/api/jest.config.cjs +74 -0
  59. package/templates/apps/api/package.json +54 -0
  60. package/templates/apps/api/src/__tests__/factories/content-fixture.ts +138 -0
  61. package/templates/apps/api/src/__tests__/factories/index.ts +70 -0
  62. package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +82 -0
  63. package/templates/apps/api/src/__tests__/index.test.ts +118 -0
  64. package/templates/apps/api/src/__tests__/server.test.ts +207 -0
  65. package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +126 -0
  66. package/templates/apps/api/src/__tests__/setup.ts +24 -0
  67. package/templates/apps/api/src/cli.ts +30 -0
  68. package/templates/apps/api/src/config/__tests__/index.test.ts +97 -0
  69. package/templates/apps/api/src/config/index.ts +56 -0
  70. package/templates/apps/api/src/index.ts +32 -0
  71. package/templates/apps/api/src/lib/__mocks__/prisma-client.js +15 -0
  72. package/templates/apps/api/src/lib/__mocks__/prisma.ts +45 -0
  73. package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +178 -0
  74. package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +100 -0
  75. package/templates/apps/api/src/lib/__tests__/errors.test.ts +94 -0
  76. package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +144 -0
  77. package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +8 -0
  78. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +227 -0
  79. package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +125 -0
  80. package/templates/apps/api/src/lib/__tests__/prisma.test.ts +165 -0
  81. package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +129 -0
  82. package/templates/apps/api/src/lib/__tests__/stripe.test.ts +74 -0
  83. package/templates/apps/api/src/lib/content-adapter.ts +86 -0
  84. package/templates/apps/api/src/lib/error-serializer.ts +77 -0
  85. package/templates/apps/api/src/lib/errors.ts +95 -0
  86. package/templates/apps/api/src/lib/file-fallback.ts +87 -0
  87. package/templates/apps/api/src/lib/lead-capture-store.ts +110 -0
  88. package/templates/apps/api/src/lib/locales.ts +201 -0
  89. package/templates/apps/api/src/lib/outbound-http.ts +122 -0
  90. package/templates/apps/api/src/lib/prisma.ts +21 -0
  91. package/templates/apps/api/src/lib/require-paid-tier.ts +53 -0
  92. package/templates/apps/api/src/lib/stripe.ts +30 -0
  93. package/templates/apps/api/src/lib/webhook-idempotency.ts +92 -0
  94. package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +111 -0
  95. package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +172 -0
  96. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +119 -0
  97. package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +138 -0
  98. package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +149 -0
  99. package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +139 -0
  100. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +175 -0
  101. package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +76 -0
  102. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +153 -0
  103. package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +72 -0
  104. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +292 -0
  105. package/templates/apps/api/src/middleware/auth.ts +246 -0
  106. package/templates/apps/api/src/middleware/rate-limit.ts +132 -0
  107. package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +129 -0
  108. package/templates/apps/api/src/openapi/index.ts +12 -0
  109. package/templates/apps/api/src/openapi/spec.ts +408 -0
  110. package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +193 -0
  111. package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +201 -0
  112. package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +294 -0
  113. package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +486 -0
  114. package/templates/apps/api/src/routes/auth/tokens.ts +199 -0
  115. package/templates/apps/api/src/routes/auth/user.ts +244 -0
  116. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +588 -0
  117. package/templates/apps/api/src/routes/checkout/index.ts +13 -0
  118. package/templates/apps/api/src/routes/checkout/sessions.ts +185 -0
  119. package/templates/apps/api/src/routes/content/__tests__/create.test.ts +239 -0
  120. package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +201 -0
  121. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +141 -0
  122. package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +122 -0
  123. package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +44 -0
  124. package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +118 -0
  125. package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +51 -0
  126. package/templates/apps/api/src/routes/content/__tests__/update.test.ts +252 -0
  127. package/templates/apps/api/src/routes/content/create.ts +114 -0
  128. package/templates/apps/api/src/routes/content/delete.ts +81 -0
  129. package/templates/apps/api/src/routes/content/get-page.ts +98 -0
  130. package/templates/apps/api/src/routes/content/index.ts +32 -0
  131. package/templates/apps/api/src/routes/content/list-pages.ts +83 -0
  132. package/templates/apps/api/src/routes/content/list-types.ts +19 -0
  133. package/templates/apps/api/src/routes/content/rate-limit.ts +13 -0
  134. package/templates/apps/api/src/routes/content/slug.ts +9 -0
  135. package/templates/apps/api/src/routes/content/update.ts +111 -0
  136. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +415 -0
  137. package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +165 -0
  138. package/templates/apps/api/src/routes/leads/index.ts +130 -0
  139. package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +296 -0
  140. package/templates/apps/api/src/routes/test/auth/session.ts +141 -0
  141. package/templates/apps/api/src/routes/webhooks/README.md +57 -0
  142. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +247 -0
  143. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +198 -0
  144. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +633 -0
  145. package/templates/apps/api/src/routes/webhooks/index.ts +41 -0
  146. package/templates/apps/api/src/routes/webhooks/stripe.ts +253 -0
  147. package/templates/apps/api/src/server.ts +157 -0
  148. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +395 -0
  149. package/templates/apps/api/src/services/enrichment-shim.ts +53 -0
  150. package/templates/apps/api/src/services/lead-routing.ts +338 -0
  151. package/templates/apps/api/tsconfig.json +34 -0
  152. package/templates/apps/api/vercel.json +17 -0
  153. package/templates/apps/mcp/.env.example +52 -0
  154. package/templates/apps/mcp/CLAUDE.md +84 -0
  155. package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +52 -0
  156. package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +46 -0
  157. package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +36 -0
  158. package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +54 -0
  159. package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +110 -0
  160. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +213 -0
  161. package/templates/apps/mcp/__tests__/audit.test.ts +217 -0
  162. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +52 -0
  163. package/templates/apps/mcp/__tests__/create_page.test.ts +201 -0
  164. package/templates/apps/mcp/__tests__/delete_page.test.ts +176 -0
  165. package/templates/apps/mcp/__tests__/get_business_hours.test.ts +82 -0
  166. package/templates/apps/mcp/__tests__/get_faq.test.ts +80 -0
  167. package/templates/apps/mcp/__tests__/get_locations.test.ts +65 -0
  168. package/templates/apps/mcp/__tests__/get_offerings.test.ts +90 -0
  169. package/templates/apps/mcp/__tests__/get_pricing.test.ts +80 -0
  170. package/templates/apps/mcp/__tests__/get_site_info.test.ts +81 -0
  171. package/templates/apps/mcp/__tests__/http-transport.test.ts +323 -0
  172. package/templates/apps/mcp/__tests__/lib/errors.test.ts +75 -0
  173. package/templates/apps/mcp/__tests__/lib/require-paid-tier.test.ts +75 -0
  174. package/templates/apps/mcp/__tests__/list_pages.test.ts +112 -0
  175. package/templates/apps/mcp/__tests__/locale.test.ts +135 -0
  176. package/templates/apps/mcp/__tests__/parity.test.ts +205 -0
  177. package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +34 -0
  178. package/templates/apps/mcp/__tests__/read_content.test.ts +153 -0
  179. package/templates/apps/mcp/__tests__/request_callback.test.ts +163 -0
  180. package/templates/apps/mcp/__tests__/search_content.test.ts +153 -0
  181. package/templates/apps/mcp/__tests__/server.test.ts +115 -0
  182. package/templates/apps/mcp/__tests__/submit_lead.test.ts +165 -0
  183. package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +161 -0
  184. package/templates/apps/mcp/__tests__/tools/purchase.test.ts +227 -0
  185. package/templates/apps/mcp/__tests__/tools/scaffold.test.ts +237 -0
  186. package/templates/apps/mcp/__tests__/update_page.test.ts +195 -0
  187. package/templates/apps/mcp/jest.config.cjs +82 -0
  188. package/templates/apps/mcp/package.json +37 -0
  189. package/templates/apps/mcp/src/abuse/daily-cap.ts +47 -0
  190. package/templates/apps/mcp/src/abuse/email-validator.ts +25 -0
  191. package/templates/apps/mcp/src/abuse/honeypot.ts +21 -0
  192. package/templates/apps/mcp/src/abuse/index.ts +111 -0
  193. package/templates/apps/mcp/src/abuse/user-agent-deny.ts +58 -0
  194. package/templates/apps/mcp/src/http-transport.ts +303 -0
  195. package/templates/apps/mcp/src/index.ts +67 -0
  196. package/templates/apps/mcp/src/lib/audit-single-page.ts +194 -0
  197. package/templates/apps/mcp/src/lib/errors.ts +61 -0
  198. package/templates/apps/mcp/src/lib/locales.ts +171 -0
  199. package/templates/apps/mcp/src/lib/require-paid-tier.ts +44 -0
  200. package/templates/apps/mcp/src/lib/resolve-locale.ts +30 -0
  201. package/templates/apps/mcp/src/server.ts +139 -0
  202. package/templates/apps/mcp/src/tools/audit.ts +103 -0
  203. package/templates/apps/mcp/src/tools/capture_lead.ts +52 -0
  204. package/templates/apps/mcp/src/tools/create_page.ts +95 -0
  205. package/templates/apps/mcp/src/tools/delete_page.ts +73 -0
  206. package/templates/apps/mcp/src/tools/get_business_hours.ts +66 -0
  207. package/templates/apps/mcp/src/tools/get_faq.ts +69 -0
  208. package/templates/apps/mcp/src/tools/get_locations.ts +85 -0
  209. package/templates/apps/mcp/src/tools/get_offerings.ts +66 -0
  210. package/templates/apps/mcp/src/tools/get_pricing.ts +74 -0
  211. package/templates/apps/mcp/src/tools/get_site_info.ts +84 -0
  212. package/templates/apps/mcp/src/tools/index.ts +125 -0
  213. package/templates/apps/mcp/src/tools/list_pages.ts +72 -0
  214. package/templates/apps/mcp/src/tools/purchase.ts +89 -0
  215. package/templates/apps/mcp/src/tools/read_content.ts +61 -0
  216. package/templates/apps/mcp/src/tools/request_callback.ts +51 -0
  217. package/templates/apps/mcp/src/tools/scaffold.ts +119 -0
  218. package/templates/apps/mcp/src/tools/search_content.ts +59 -0
  219. package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +47 -0
  220. package/templates/apps/mcp/src/tools/update_page.ts +91 -0
  221. package/templates/apps/mcp/tsconfig.json +19 -0
  222. package/templates/apps/web/.env.example +47 -0
  223. package/templates/apps/web/CLAUDE.md +81 -0
  224. package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +94 -0
  225. package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +75 -0
  226. package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +82 -0
  227. package/templates/apps/web/__tests__/auth/env-helpers.test.ts +168 -0
  228. package/templates/apps/web/__tests__/authority-list-routes.test.tsx +208 -0
  229. package/templates/apps/web/__tests__/better-stack.test.ts +66 -0
  230. package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +87 -0
  231. package/templates/apps/web/__tests__/blog-source-populated.test.ts +130 -0
  232. package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +60 -0
  233. package/templates/apps/web/__tests__/google-analytics.test.tsx +104 -0
  234. package/templates/apps/web/__tests__/i18n/middleware.test.ts +119 -0
  235. package/templates/apps/web/__tests__/i18n/routing.test.ts +114 -0
  236. package/templates/apps/web/__tests__/i18n/translations.test.ts +191 -0
  237. package/templates/apps/web/__tests__/json-ld.test.ts +98 -0
  238. package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +580 -0
  239. package/templates/apps/web/__tests__/layout-stealth.test.ts +39 -0
  240. package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +103 -0
  241. package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +114 -0
  242. package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +94 -0
  243. package/templates/apps/web/__tests__/page.test.tsx +230 -0
  244. package/templates/apps/web/__tests__/products-services-phase1.test.tsx +321 -0
  245. package/templates/apps/web/__tests__/projects-routes.test.tsx +392 -0
  246. package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +475 -0
  247. package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +53 -0
  248. package/templates/apps/web/__tests__/routes/blog-route.test.tsx +191 -0
  249. package/templates/apps/web/__tests__/routes/llms-txt.test.ts +123 -0
  250. package/templates/apps/web/__tests__/routes/robots-txt.test.ts +52 -0
  251. package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +78 -0
  252. package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +203 -0
  253. package/templates/apps/web/__tests__/section-routes.test.tsx +693 -0
  254. package/templates/apps/web/__tests__/security-headers.test.ts +201 -0
  255. package/templates/apps/web/__tests__/sentry-config.test.ts +116 -0
  256. package/templates/apps/web/__tests__/setup.ts +82 -0
  257. package/templates/apps/web/__tests__/sitemap-locales.test.ts +415 -0
  258. package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +844 -0
  259. package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +81 -0
  260. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +110 -0
  261. package/templates/apps/web/app/.well-known/mcp.json/route.ts +58 -0
  262. package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +120 -0
  263. package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +202 -0
  264. package/templates/apps/web/app/[locale]/about/page.tsx +31 -0
  265. package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +173 -0
  266. package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +45 -0
  267. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +117 -0
  268. package/templates/apps/web/app/[locale]/careers/page.tsx +25 -0
  269. package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +44 -0
  270. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +113 -0
  271. package/templates/apps/web/app/[locale]/case-studies/page.tsx +25 -0
  272. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +63 -0
  273. package/templates/apps/web/app/[locale]/clients/page.tsx +27 -0
  274. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +130 -0
  275. package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +152 -0
  276. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +92 -0
  277. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +79 -0
  278. package/templates/apps/web/app/[locale]/contact/error.tsx +24 -0
  279. package/templates/apps/web/app/[locale]/contact/page.tsx +38 -0
  280. package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +34 -0
  281. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +119 -0
  282. package/templates/apps/web/app/[locale]/courses/page.tsx +25 -0
  283. package/templates/apps/web/app/[locale]/dev/purchase/__tests__/actions.test.ts +160 -0
  284. package/templates/apps/web/app/[locale]/dev/purchase/error.tsx +25 -0
  285. package/templates/apps/web/app/[locale]/dev/purchase/page.tsx +117 -0
  286. package/templates/apps/web/app/[locale]/dev/purchase/purchase.actions.ts +58 -0
  287. package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +118 -0
  288. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +72 -0
  289. package/templates/apps/web/app/[locale]/downloads/page.tsx +25 -0
  290. package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +47 -0
  291. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +130 -0
  292. package/templates/apps/web/app/[locale]/events/page.tsx +25 -0
  293. package/templates/apps/web/app/[locale]/faq/page.tsx +36 -0
  294. package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +34 -0
  295. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +78 -0
  296. package/templates/apps/web/app/[locale]/how-to/page.tsx +40 -0
  297. package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +43 -0
  298. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +129 -0
  299. package/templates/apps/web/app/[locale]/integrations/page.tsx +25 -0
  300. package/templates/apps/web/app/[locale]/launch-service/page.tsx +31 -0
  301. package/templates/apps/web/app/[locale]/layout.tsx +241 -0
  302. package/templates/apps/web/app/[locale]/page.tsx +41 -0
  303. package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +44 -0
  304. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +113 -0
  305. package/templates/apps/web/app/[locale]/partners/page.tsx +25 -0
  306. package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +43 -0
  307. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +129 -0
  308. package/templates/apps/web/app/[locale]/products/page.tsx +25 -0
  309. package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +39 -0
  310. package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +138 -0
  311. package/templates/apps/web/app/[locale]/projects/page.tsx +30 -0
  312. package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +51 -0
  313. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +117 -0
  314. package/templates/apps/web/app/[locale]/resources/page.tsx +27 -0
  315. package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +43 -0
  316. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +129 -0
  317. package/templates/apps/web/app/[locale]/services/page.tsx +25 -0
  318. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +34 -0
  319. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +81 -0
  320. package/templates/apps/web/app/[locale]/software/page.tsx +39 -0
  321. package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +34 -0
  322. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +82 -0
  323. package/templates/apps/web/app/[locale]/tech-articles/page.tsx +39 -0
  324. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +63 -0
  325. package/templates/apps/web/app/[locale]/testimonials/page.tsx +27 -0
  326. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +63 -0
  327. package/templates/apps/web/app/[locale]/use-cases/page.tsx +27 -0
  328. package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +34 -0
  329. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +82 -0
  330. package/templates/apps/web/app/[locale]/whitepapers/page.tsx +39 -0
  331. package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +152 -0
  332. package/templates/apps/web/app/api/auth/[...all]/route.ts +16 -0
  333. package/templates/apps/web/app/error-fallback.tsx +75 -0
  334. package/templates/apps/web/app/error.tsx +23 -0
  335. package/templates/apps/web/app/layout.tsx +18 -0
  336. package/templates/apps/web/app/llms.txt/route.ts +101 -0
  337. package/templates/apps/web/app/not-found.tsx +48 -0
  338. package/templates/apps/web/app/og/__tests__/route.test.ts +164 -0
  339. package/templates/apps/web/app/og/route.tsx +135 -0
  340. package/templates/apps/web/app/robots.txt/route.ts +36 -0
  341. package/templates/apps/web/app/sitemap.xml/route.ts +146 -0
  342. package/templates/apps/web/auth.ts +141 -0
  343. package/templates/apps/web/components/ThemeToggle.tsx +60 -0
  344. package/templates/apps/web/components/google-analytics.tsx +34 -0
  345. package/templates/apps/web/content/en/blog/index.mdx +15 -0
  346. package/templates/apps/web/content/en/blog/launching-ailk.mdx +20 -0
  347. package/templates/apps/web/content/en/docs/getting-started.mdx +30 -0
  348. package/templates/apps/web/i18n/request.ts +36 -0
  349. package/templates/apps/web/jest.config.cjs +100 -0
  350. package/templates/apps/web/lib/__mocks__/next-mdx-remote-rsc.js +12 -0
  351. package/templates/apps/web/lib/__mocks__/source-server.js +31 -0
  352. package/templates/apps/web/lib/__tests__/og.test.ts +65 -0
  353. package/templates/apps/web/lib/auth-env.ts +66 -0
  354. package/templates/apps/web/lib/blog-list-data.ts +95 -0
  355. package/templates/apps/web/lib/blog-post-data.ts +79 -0
  356. package/templates/apps/web/lib/nav-config.ts +13 -0
  357. package/templates/apps/web/lib/observability/better-stack.ts +27 -0
  358. package/templates/apps/web/lib/og.ts +23 -0
  359. package/templates/apps/web/lib/prisma-for-auth.ts +34 -0
  360. package/templates/apps/web/lib/source.ts +34 -0
  361. package/templates/apps/web/messages/en.json +131 -0
  362. package/templates/apps/web/middleware.ts +80 -0
  363. package/templates/apps/web/next.config.mjs +167 -0
  364. package/templates/apps/web/package.json +62 -0
  365. package/templates/apps/web/public/.well-known/security.txt +17 -0
  366. package/templates/apps/web/public/android-chrome-192x192.png +0 -0
  367. package/templates/apps/web/public/android-chrome-512x512.png +0 -0
  368. package/templates/apps/web/public/apple-touch-icon.png +0 -0
  369. package/templates/apps/web/public/favicon-16x16.png +0 -0
  370. package/templates/apps/web/public/favicon-32x32.png +0 -0
  371. package/templates/apps/web/public/favicon.ico +0 -0
  372. package/templates/apps/web/public/favicon.svg +4 -0
  373. package/templates/apps/web/public/logo-dark.svg +21 -0
  374. package/templates/apps/web/public/logo-light.svg +21 -0
  375. package/templates/apps/web/public/logomark-dark.svg +4 -0
  376. package/templates/apps/web/public/logomark-light.svg +4 -0
  377. package/templates/apps/web/public/og-default.png +0 -0
  378. package/templates/apps/web/public/site.webmanifest +19 -0
  379. package/templates/apps/web/scripts/assert-content-bundled.ts +55 -0
  380. package/templates/apps/web/security-headers.config.ts +132 -0
  381. package/templates/apps/web/sentry.client.config.ts +27 -0
  382. package/templates/apps/web/sentry.edge.config.ts +15 -0
  383. package/templates/apps/web/sentry.server.config.ts +20 -0
  384. package/templates/apps/web/source.config.ts +78 -0
  385. package/templates/apps/web/src/components/SiteNav.tsx +21 -0
  386. package/templates/apps/web/src/lib/routes.ts +37 -0
  387. package/templates/apps/web/tsconfig.json +35 -0
  388. package/templates/apps/web/types/messages.d.ts +19 -0
  389. package/templates/content/.gitkeep +0 -0
  390. package/templates/content/CLAUDE.md +85 -0
  391. package/templates/content/_site.mdx +38 -0
  392. package/templates/content/ar/HomePage/home.mdx +123 -0
  393. package/templates/content/ar/_site.mdx +35 -0
  394. package/templates/content/de/_site.mdx +29 -0
  395. package/templates/content/en/.gitkeep +0 -0
  396. package/templates/content/en/AboutPage/about.mdx +19 -0
  397. package/templates/content/en/AboutPage/about.schema.json +82 -0
  398. package/templates/content/en/BookCall/book-call.mdx +19 -0
  399. package/templates/content/en/BookCall/book-call.schema.json +121 -0
  400. package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +20 -0
  401. package/templates/content/en/CareersList/careers.mdx +24 -0
  402. package/templates/content/en/CaseStudiesList/case-studies.mdx +22 -0
  403. package/templates/content/en/CaseStudiesList/showcase.mdx +8 -0
  404. package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +32 -0
  405. package/templates/content/en/CaseStudy/schema-builder-migration.mdx +41 -0
  406. package/templates/content/en/ClientsList/clients.mdx +38 -0
  407. package/templates/content/en/ContactPage/contact.mdx +19 -0
  408. package/templates/content/en/ContactPage/contact.schema.json +100 -0
  409. package/templates/content/en/ContactPoint/primary.mdx +14 -0
  410. package/templates/content/en/Course/aeo-fundamentals.mdx +37 -0
  411. package/templates/content/en/Course/schema-builder-workshop.mdx +62 -0
  412. package/templates/content/en/CoursesList/courses.mdx +22 -0
  413. package/templates/content/en/DownloadsList/downloads.mdx +22 -0
  414. package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +39 -0
  415. package/templates/content/en/Event/ailk-launch-day-2026.mdx +35 -0
  416. package/templates/content/en/EventsList/events.mdx +26 -0
  417. package/templates/content/en/FAQPage/faq.mdx +420 -0
  418. package/templates/content/en/FAQPage/faq.schema.json +231 -0
  419. package/templates/content/en/GlossaryList/glossary.mdx +19 -0
  420. package/templates/content/en/GlossaryList/glossary.schema.json +300 -0
  421. package/templates/content/en/HomePage/home.mdx +312 -0
  422. package/templates/content/en/HomePage/home.schema.json +88 -0
  423. package/templates/content/en/HomePage/launch-service.mdx +475 -0
  424. package/templates/content/en/HomePage/launch-service.schema.json +138 -0
  425. package/templates/content/en/HowTo/add-mdx-content.mdx +38 -0
  426. package/templates/content/en/HowTo/configure-aeo-scoring.mdx +35 -0
  427. package/templates/content/en/HowTo/set-up-json-ld.mdx +36 -0
  428. package/templates/content/en/Integration/github-actions.mdx +31 -0
  429. package/templates/content/en/Integration/openai-api.mdx +26 -0
  430. package/templates/content/en/Integration/vercel.mdx +32 -0
  431. package/templates/content/en/IntegrationsList/integrations.mdx +22 -0
  432. package/templates/content/en/JobPosting/content-strategist.mdx +46 -0
  433. package/templates/content/en/JobPosting/developer-advocate.mdx +47 -0
  434. package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +57 -0
  435. package/templates/content/en/LandingPage/aeo-audit.mdx +19 -0
  436. package/templates/content/en/LandingPage/aeo-audit.schema.json +92 -0
  437. package/templates/content/en/LandingPage/agency-waitlist.mdx +340 -0
  438. package/templates/content/en/LandingPage/agency-waitlist.schema.json +152 -0
  439. package/templates/content/en/LandingPage/developers.mdx +19 -0
  440. package/templates/content/en/LandingPage/developers.schema.json +109 -0
  441. package/templates/content/en/LandingPage/for-agencies.mdx +390 -0
  442. package/templates/content/en/LandingPage/for-agencies.schema.json +107 -0
  443. package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +417 -0
  444. package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +105 -0
  445. package/templates/content/en/LandingPage/for-businesses.mdx +19 -0
  446. package/templates/content/en/LandingPage/for-businesses.schema.json +96 -0
  447. package/templates/content/en/LandingPage/platform.mdx +369 -0
  448. package/templates/content/en/LandingPage/platform.schema.json +166 -0
  449. package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +19 -0
  450. package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +102 -0
  451. package/templates/content/en/LandingPage/vs-wordpress.mdx +19 -0
  452. package/templates/content/en/LandingPage/vs-wordpress.schema.json +53 -0
  453. package/templates/content/en/NewsletterSignup/newsletter.mdx +236 -0
  454. package/templates/content/en/NewsletterSignup/newsletter.schema.json +91 -0
  455. package/templates/content/en/Organization/site-owner.mdx +16 -0
  456. package/templates/content/en/Partner/prisma.mdx +31 -0
  457. package/templates/content/en/Partner/supabase.mdx +30 -0
  458. package/templates/content/en/Partner/vercel.mdx +28 -0
  459. package/templates/content/en/PartnersList/partners.mdx +22 -0
  460. package/templates/content/en/Person/founder.mdx +18 -0
  461. package/templates/content/en/Pricing/pricing.mdx +538 -0
  462. package/templates/content/en/Pricing/pricing.schema.json +209 -0
  463. package/templates/content/en/PrivacyPage/privacy.mdx +165 -0
  464. package/templates/content/en/PrivacyPage/privacy.schema.json +64 -0
  465. package/templates/content/en/Product/ailk.mdx +19 -0
  466. package/templates/content/en/Product/ailk.schema.json +94 -0
  467. package/templates/content/en/Product/api-launch-kit.mdx +26 -0
  468. package/templates/content/en/Product/launch-kit.mdx +28 -0
  469. package/templates/content/en/ProductsList/products.mdx +26 -0
  470. package/templates/content/en/Project/ailk-phase-2.mdx +54 -0
  471. package/templates/content/en/ProjectsList/projects.mdx +25 -0
  472. package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +27 -0
  473. package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +28 -0
  474. package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +39 -0
  475. package/templates/content/en/ResourcesHub/resources.mdx +22 -0
  476. package/templates/content/en/Service/consulting.mdx +22 -0
  477. package/templates/content/en/Service/implementation.mdx +30 -0
  478. package/templates/content/en/Service/launch-service.mdx +232 -0
  479. package/templates/content/en/Service/launch.mdx +228 -0
  480. package/templates/content/en/ServicesList/services.mdx +84 -0
  481. package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +44 -0
  482. package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +47 -0
  483. package/templates/content/en/SoftwareProduct/ailk-schema.mdx +49 -0
  484. package/templates/content/en/TeamList/team.mdx +63 -0
  485. package/templates/content/en/TeamMember/founder.mdx +72 -0
  486. package/templates/content/en/TermsPage/terms.mdx +19 -0
  487. package/templates/content/en/TermsPage/terms.schema.json +99 -0
  488. package/templates/content/en/TestimonialsList/testimonials.mdx +44 -0
  489. package/templates/content/en/UseCasesList/use-cases.mdx +30 -0
  490. package/templates/content/en/Whitepaper/ax-first-product-development.mdx +27 -0
  491. package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +27 -0
  492. package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +31 -0
  493. package/templates/content/en-XA/AboutPage/about.mdx +8 -0
  494. package/templates/content/en-XA/FAQPage/faq.mdx +8 -0
  495. package/templates/content/en-XA/HomePage/home.mdx +8 -0
  496. package/templates/content/es/_site.mdx +30 -0
  497. package/templates/content/fr/_site.mdx +30 -0
  498. package/templates/content/ja/_site.mdx +30 -0
  499. package/templates/content/pt-BR/AboutPage/about.mdx +8 -0
  500. package/templates/content/pt-BR/FAQPage/faq.mdx +8 -0
  501. package/templates/content/pt-BR/HomePage/home.mdx +23 -0
  502. package/templates/database/CHANGELOG.md +5 -0
  503. package/templates/database/README.md +234 -0
  504. package/templates/database/__tests__/user-cascade.test.ts +125 -0
  505. package/templates/database/auth/.gitkeep +0 -0
  506. package/templates/database/config/.gitkeep +0 -0
  507. package/templates/database/content/.gitkeep +0 -0
  508. package/templates/database/inbox/.gitkeep +0 -0
  509. package/templates/database/inbox/README.md +3 -0
  510. package/templates/database/inbox/__tests__/schema.test.ts +40 -0
  511. package/templates/database/inbox/schema.prisma +52 -0
  512. package/templates/database/jest.config.cjs +29 -0
  513. package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +328 -0
  514. package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +100 -0
  515. package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +28 -0
  516. package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +25 -0
  517. package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +42 -0
  518. package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +67 -0
  519. package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +21 -0
  520. package/templates/database/migrations/migration_lock.toml +3 -0
  521. package/templates/database/ops/.gitkeep +0 -0
  522. package/templates/database/package.json +45 -0
  523. package/templates/database/prisma.config.ts +20 -0
  524. package/templates/database/schema.prisma +487 -0
  525. package/templates/database/scripts/db-generate-locked.sh +80 -0
  526. package/templates/database/seed-test.ts +85 -0
  527. package/templates/database/tsconfig.build.json +16 -0
  528. package/templates/database/tsconfig.json +9 -0
  529. package/templates/package.json +125 -0
  530. package/templates/pnpm-workspace.yaml +6 -0
  531. package/templates/project.yaml +59 -0
  532. package/templates/tsconfig.base.json +18 -0
  533. package/templates/tsconfig.json +45 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Programmatic API for create-ailk.
3
+ *
4
+ * Extracts the core scaffolding logic from cli.ts so it can be exercised
5
+ * directly in tests and by other consumers without spawning a subprocess.
6
+ *
7
+ * The CLI entry point (cli.ts) delegates to scaffoldSync() here; no logic is
8
+ * duplicated between the CLI and the programmatic surface.
9
+ *
10
+ * Usage (async, for MCP tool or external tooling):
11
+ * import { scaffold } from './programmatic.js';
12
+ * const result = await scaffold({ targetDir: '/tmp/my-site', projectName: 'my-site' });
13
+ *
14
+ * Usage (sync, for the CLI):
15
+ * import { scaffoldSync } from './programmatic.js';
16
+ * const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
17
+ */
18
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
19
+ import { basename, dirname, resolve } from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+ import { copyTemplate } from "./copy.js";
22
+ import { validateTarget } from "./validate.js";
23
+ const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
24
+ const TEMPLATES_DIR = resolve(PKG_ROOT, "templates");
25
+ const VERSIONS_FILE = resolve(PKG_ROOT, "versions.json");
26
+ function readVersionMap() {
27
+ if (!existsSync(VERSIONS_FILE)) {
28
+ // Empty map is a valid state for tests / dev where build-templates has
29
+ // not been re-run since the last clean.
30
+ return {};
31
+ }
32
+ const raw = readFileSync(VERSIONS_FILE, "utf8");
33
+ return JSON.parse(raw);
34
+ }
35
+ /**
36
+ * Count all files recursively under a directory. Used to report filesCreated.
37
+ */
38
+ function countFiles(dir) {
39
+ if (!existsSync(dir))
40
+ return 0;
41
+ let count = 0;
42
+ const stack = [dir];
43
+ while (stack.length > 0) {
44
+ const current = stack.pop();
45
+ for (const entry of readdirSync(current, { withFileTypes: true })) {
46
+ if (entry.isDirectory()) {
47
+ stack.push(`${current}/${entry.name}`);
48
+ }
49
+ else {
50
+ count++;
51
+ }
52
+ }
53
+ }
54
+ return count;
55
+ }
56
+ /**
57
+ * Scaffold an AI Launch Kit starter project into targetDir (synchronous).
58
+ *
59
+ * Throws ValidationError if targetDir already exists and is non-empty.
60
+ * Throws Error if the template copy fails for any other reason.
61
+ */
62
+ export function scaffoldSync(opts) {
63
+ // Validate target — throws ValidationError on rejection.
64
+ const targetAbs = validateTarget(opts.targetDir);
65
+ const projectName = opts.projectName ?? basename(targetAbs);
66
+ const versions = readVersionMap();
67
+ copyTemplate({
68
+ templatesDir: TEMPLATES_DIR,
69
+ targetDir: targetAbs,
70
+ versions,
71
+ markers: {
72
+ PROJECT_NAME: projectName,
73
+ COMPANY_NAME: "Your Company",
74
+ COMPANY_DOMAIN: "example.com",
75
+ },
76
+ });
77
+ const filesCreated = countFiles(targetAbs);
78
+ return { targetDir: targetAbs, filesCreated };
79
+ }
80
+ /**
81
+ * Scaffold an AI Launch Kit starter project into targetDir (async wrapper).
82
+ *
83
+ * Wraps scaffoldSync for callers that prefer Promise-based APIs. The
84
+ * underlying I/O is synchronous; the async signature is provided for
85
+ * compatibility with async callers (e.g. the MCP tool handler via subprocess).
86
+ */
87
+ export async function scaffold(opts) {
88
+ return scaffoldSync(opts);
89
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * String-template substitution helpers.
3
+ *
4
+ * Two surfaces:
5
+ * - substituteWorkspaceVersions — `workspace:*` → `^<semver>` for @working-theory/*
6
+ * deps in package.json text. Throws if a `@working-theory/*` entry has no canonical
7
+ * version (escalation per spec §5.3).
8
+ * - substituteMarkers — replaces every `{{KEY}}` with the matching value
9
+ * from the provided map. Markers without a matching entry are left
10
+ * unchanged so the user can author their own.
11
+ *
12
+ * The package.json substitution operates on text (regex), not on parsed JSON,
13
+ * to preserve formatting (whitespace, key order, trailing commas) of the
14
+ * canonical source. Re-serializing JSON would create gratuitous diffs in
15
+ * scaffolder output and obscure intent.
16
+ */
17
+ export type WorkspaceVersionMap = Record<string, string>;
18
+ /**
19
+ * Replaces every `"@working-theory/<pkg>": "workspace:*"` occurrence with the matching
20
+ * caret-prefixed version from `versions`. Throws when an `@working-theory/*` entry has
21
+ * no version map entry.
22
+ *
23
+ * Non-`@working-theory/*` deps are not touched; non-package.json input is not touched.
24
+ */
25
+ export declare function substituteWorkspaceVersions(input: string, versions: WorkspaceVersionMap): string;
26
+ export type MarkerMap = Record<string, string>;
27
+ /**
28
+ * Replaces `{{KEY}}` markers with values from the provided map. Markers
29
+ * without a matching entry are left as-is (e.g. user-authored placeholders).
30
+ */
31
+ export declare function substituteMarkers(input: string, markers: MarkerMap): string;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * String-template substitution helpers.
3
+ *
4
+ * Two surfaces:
5
+ * - substituteWorkspaceVersions — `workspace:*` → `^<semver>` for @working-theory/*
6
+ * deps in package.json text. Throws if a `@working-theory/*` entry has no canonical
7
+ * version (escalation per spec §5.3).
8
+ * - substituteMarkers — replaces every `{{KEY}}` with the matching value
9
+ * from the provided map. Markers without a matching entry are left
10
+ * unchanged so the user can author their own.
11
+ *
12
+ * The package.json substitution operates on text (regex), not on parsed JSON,
13
+ * to preserve formatting (whitespace, key order, trailing commas) of the
14
+ * canonical source. Re-serializing JSON would create gratuitous diffs in
15
+ * scaffolder output and obscure intent.
16
+ */
17
+ /**
18
+ * Replaces every `"@working-theory/<pkg>": "workspace:*"` occurrence with the matching
19
+ * caret-prefixed version from `versions`. Throws when an `@working-theory/*` entry has
20
+ * no version map entry.
21
+ *
22
+ * Non-`@working-theory/*` deps are not touched; non-package.json input is not touched.
23
+ */
24
+ export function substituteWorkspaceVersions(input, versions) {
25
+ // Match `"@working-theory/<name>": "workspace:*"` with arbitrary whitespace between
26
+ // the colon and the value. The captured group is the package name.
27
+ const re = /"(@working-theory\/[a-z0-9-]+)"(\s*:\s*)"workspace:\*"/g;
28
+ return input.replace(re, (_match, pkg, sep) => {
29
+ const v = versions[pkg];
30
+ if (!v) {
31
+ throw new Error(`no version found for ${pkg} in canonical workspace map. Update scripts/build-templates.mjs or escalate per spec §5.3.`);
32
+ }
33
+ return `"${pkg}"${sep}"^${v}"`;
34
+ });
35
+ }
36
+ /**
37
+ * Replaces `{{KEY}}` markers with values from the provided map. Markers
38
+ * without a matching entry are left as-is (e.g. user-authored placeholders).
39
+ */
40
+ export function substituteMarkers(input, markers) {
41
+ return input.replace(/\{\{([A-Z_][A-Z0-9_]*)\}\}/g, (whole, key) => {
42
+ const value = markers[key];
43
+ return value !== undefined ? value : whole;
44
+ });
45
+ }
@@ -0,0 +1,8 @@
1
+ export declare class ValidationError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ /**
5
+ * Validates the user-supplied target dir. Returns the resolved absolute path
6
+ * on success; throws ValidationError on any rejection.
7
+ */
8
+ export declare function validateTarget(rawTarget: string): string;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Target-directory validation for `create-ailk`.
3
+ *
4
+ * Spec §2.2 + §5.1 + §5.2:
5
+ * - Reject if target exists AND is non-empty.
6
+ * - Reject if target arg contains `..` (path traversal guard).
7
+ * - Reject if target arg contains a NUL byte (`\0`) — defense-in-depth
8
+ * against C-string truncation tricks in any downstream syscall path.
9
+ * - Reject filesystem root.
10
+ * - Reject when the parent directory does not exist (surface user error).
11
+ * - Reject when target points at an existing file (not a directory).
12
+ *
13
+ * Note on TOCTOU: validation runs before `copyTemplate` performs writes, so
14
+ * a concurrent process could in principle populate the target between the
15
+ * two. Acceptable for a CLI run interactively by the user themselves; if
16
+ * this scaffolder ever runs in an adversarial multi-tenant context, add a
17
+ * re-check immediately before write.
18
+ */
19
+ import { existsSync, readdirSync, statSync } from "node:fs";
20
+ import { dirname, isAbsolute, resolve, sep } from "node:path";
21
+ export class ValidationError extends Error {
22
+ constructor(message) {
23
+ super(message);
24
+ this.name = "ValidationError";
25
+ }
26
+ }
27
+ /**
28
+ * Validates the user-supplied target dir. Returns the resolved absolute path
29
+ * on success; throws ValidationError on any rejection.
30
+ */
31
+ export function validateTarget(rawTarget) {
32
+ if (typeof rawTarget !== "string" || rawTarget.length === 0) {
33
+ throw new ValidationError("target directory must be a non-empty string");
34
+ }
35
+ // Defense-in-depth: reject NUL bytes — they truncate C strings on some
36
+ // syscalls and have no legitimate use in a directory name.
37
+ if (rawTarget.includes("\0")) {
38
+ throw new ValidationError("target path contains NUL byte (`\\0`); this is never legitimate");
39
+ }
40
+ // Defense-in-depth: reject `..` segments BEFORE resolution. We compare
41
+ // path-separator-bracketed segments so a directory literally named "..foo"
42
+ // is allowed (.. only blocks the parent-traversal segment).
43
+ const segments = rawTarget.split(/[\\/]/);
44
+ if (segments.some((s) => s === "..")) {
45
+ throw new ValidationError(`target path contains \`..\` traversal segment: ${rawTarget}`);
46
+ }
47
+ const resolved = isAbsolute(rawTarget)
48
+ ? rawTarget
49
+ : resolve(process.cwd(), rawTarget);
50
+ // Reject filesystem root (e.g. `/`, `C:\`).
51
+ if (resolved === sep || /^[A-Za-z]:[\\/]?$/.test(resolved)) {
52
+ throw new ValidationError(`target directory cannot be the filesystem root: ${resolved}`);
53
+ }
54
+ // Parent must exist.
55
+ const parent = dirname(resolved);
56
+ if (!existsSync(parent)) {
57
+ throw new ValidationError(`parent directory does not exist: ${parent}. Create it first or choose a different path.`);
58
+ }
59
+ if (existsSync(resolved)) {
60
+ const s = statSync(resolved);
61
+ if (!s.isDirectory()) {
62
+ throw new ValidationError(`target exists but is not a directory: ${resolved}`);
63
+ }
64
+ const entries = readdirSync(resolved);
65
+ if (entries.length > 0) {
66
+ throw new ValidationError(`target directory exists and is not empty: ${resolved}`);
67
+ }
68
+ }
69
+ return resolved;
70
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "create-ailk",
3
+ "version": "0.1.0",
4
+ "description": "Scaffolder for AI Launch Kit — `pnpm create ailk@latest <dir>` produces a starter repo consuming @working-theory/* from npm (per ADR 0007).",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "create-ailk": "./dist/cli.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "templates",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/tailwind-ai/ai-launch-kit.git",
23
+ "directory": "packages/create-ailk"
24
+ },
25
+ "homepage": "https://github.com/tailwind-ai/ai-launch-kit/tree/main/packages/create-ailk#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/tailwind-ai/ai-launch-kit/issues"
28
+ },
29
+ "engines": {
30
+ "node": ">=20.0.0"
31
+ },
32
+ "keywords": [
33
+ "ailk",
34
+ "scaffolder",
35
+ "create-ailk",
36
+ "ai-launch-kit"
37
+ ],
38
+ "license": "Apache-2.0",
39
+ "scripts": {
40
+ "build": "tsc -b",
41
+ "type-check": "tsc --noEmit",
42
+ "test": "tsc -b && node scripts/build-templates.mjs && jest",
43
+ "test:watch": "jest --watch",
44
+ "test:coverage": "jest --coverage",
45
+ "build-templates": "node scripts/build-templates.mjs"
46
+ }
47
+ }
File without changes
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: web
3
+ description: Frontend specialist for apps/web and any project-local UI components. Use when work touches React components, pages, styles, or visitor-facing UX. Not for api routes or schema work.
4
+ allowed_tools: [Read, Edit, Write, Glob, Grep, Bash, Agent]
5
+ model: sonnet
6
+ ---
7
+
8
+ You are the frontend specialist for this project. You own the
9
+ visitor-facing UX surface — the marketing site, any dashboard pages,
10
+ and any project-local components.
11
+
12
+ ## Scope
13
+
14
+ - `apps/web/**` — Next.js 16 + React 19 app, Server Components by
15
+ default.
16
+ - Any project-local component or theme overrides you add alongside
17
+ `apps/web`.
18
+
19
+ You consume `@working-theory/ui` and `@working-theory/theme` from npm — those are
20
+ upstream packages; don't try to edit them locally.
21
+
22
+ ## Read before edit
23
+
24
+ 1. `.claude/rules/architecture.md` — confirm what `apps/web` may
25
+ import. NextAuth handlers are the only API-shaped code allowed in
26
+ `apps/web`; everything else server-side goes through `apps/api`.
27
+ 2. The page or component you're modifying, plus any sibling files in
28
+ the same directory.
29
+ 3. Any project-local theme override file before touching styles —
30
+ tokens come from `@working-theory/theme` unless you've extended it.
31
+
32
+ ## Verification
33
+
34
+ ```bash
35
+ pnpm --filter ./apps/web type-check
36
+ pnpm --filter ./apps/web build
37
+ ```
38
+
39
+ Run `pnpm preflight` before opening a PR.
40
+
41
+ ## Hand-off rules
42
+
43
+ - Need a new HTTP endpoint? Don't invent it in `apps/web`. Add the
44
+ route in `apps/api` (or open an issue if you don't own that surface
45
+ yet) and consume it via `@working-theory/api-client`.
46
+ - Need a new content type? Add it under `content/<TypeName>/` and
47
+ reference the schema from `@working-theory/schema`.
48
+ - Need a database read? Wrong layer — `apps/web` does not read the
49
+ database. Route through `apps/api`.
50
+
51
+ ## Domain conventions
52
+
53
+ - **Server Components by default.** `'use client'` only when the
54
+ component needs browser-only APIs (state, refs, browser events).
55
+ Adding `'use client'` to a file that just renders JSX is the
56
+ default failure mode — resist it.
57
+ - **Tailwind tokens only.** No raw hex, rgb, or arbitrary colors.
58
+ Use semantic tokens from `@working-theory/theme` (`bg-canvas`, `text-fg`,
59
+ `border-border`, etc.). If a token doesn't exist, extend the theme;
60
+ don't bypass.
61
+ - **Mobile-first responsive.** Default styles target mobile;
62
+ `md:`/`lg:` modifiers for larger viewports.
63
+ - **MDX rendering** uses `next-mdx-remote/rsc`, never `@next/mdx`
64
+ (the latter requires runtime config that fights Server Components).
65
+ - **NextAuth handlers** are the only API-shaped code in `apps/web`
66
+ — they live at `apps/web/app/api/auth/[...nextauth]/route.ts`.
67
+ Everything else goes to `apps/api`.
68
+
69
+ ## Forbidden
70
+
71
+ - Importing from `apps/api` or `apps/mcp` — these are peer apps;
72
+ speak to the API via `@working-theory/api-client`.
73
+ - Importing `@working-theory/database` — `apps/web` does not touch the DB;
74
+ route through `apps/api`.
75
+ - Importing `stripe`, `resend`, `@react-email/*` directly — wrap
76
+ through `@working-theory/stripe-client` or `@working-theory/email`, server-side via
77
+ `apps/api`.
78
+ - Adding a `utils.ts`, `helpers.ts`, `common.ts`, or `misc.ts` file
79
+ — use a descriptive name.
80
+ - Reformatting unrelated lines. Diff is the contract.
@@ -0,0 +1,62 @@
1
+ # Architecture Discipline
2
+
3
+ ## The boundary
4
+
5
+ `apps/web`, `apps/api`, and `apps/mcp` are **peer apps**. They share
6
+ code via published `@working-theory/*` packages. They do not import from each
7
+ other.
8
+
9
+ ## Why this matters
10
+
11
+ - The agent surface (`apps/api`, `apps/mcp`) is a co-equal product, not
12
+ a bolt-on. Coupling apps means changing the agent surface forces
13
+ changes to the visitor-facing UX.
14
+ - Each app deploys independently. Cross-app imports prevent that.
15
+ - Reading any one app should make sense without reference to the
16
+ others. If it doesn't, you're carrying coupling that will hurt later.
17
+
18
+ ## How to apply
19
+
20
+ - Need to share code between apps? Find an existing `@working-theory/*` package
21
+ that fits, or open an issue upstream at
22
+ <https://github.com/tailwind-ai/ai-launch-kit> requesting a new one.
23
+ Do not vendor a copy.
24
+ - Need types shared across apps? Use `@working-theory/validation` (Zod schemas)
25
+ or `@working-theory/schema` (schema.org types).
26
+ - Need an HTTP call from `apps/web` to `apps/api`? Use
27
+ `@working-theory/api-client`. Don't import API route handlers directly.
28
+ - Need database access? Only `apps/api` and `apps/mcp` import
29
+ `@working-theory/database`. `apps/web` never reads the database directly — it
30
+ goes through the HTTP API.
31
+ - Cross-cutting integrations (auth, payments, email, analytics) go
32
+ through their wrapper packages: `@working-theory/auth-client`,
33
+ `@working-theory/stripe-client`, `@working-theory/email`, `@working-theory/analytics`. Never
34
+ import `next-auth`, `stripe`, `resend`, etc. directly.
35
+
36
+ ## What you can verify, what you can't
37
+
38
+ - Static imports across boundaries are easy to spot in code review and
39
+ with most TypeScript tooling.
40
+ - Runtime `fetch` calls to internal-only endpoints are NOT enforced by
41
+ any tool. Treat `apps/api` like a third-party HTTP API even when
42
+ you control both ends — version the contract, validate the response.
43
+ - Dynamic `import()` with a runtime-constructed path is also
44
+ unenforced. Don't use it to evade the boundary.
45
+
46
+ ## Escalation
47
+
48
+ If a task seems to require crossing a boundary: stop and write a short
49
+ note in `docs/` capturing what you wanted to do and why the boundary
50
+ gets in the way. Don't add the cross-import. Either the boundary moves
51
+ (and you have a record of why) or the task changes shape — both are
52
+ better than a quiet violation.
53
+
54
+ ## Forbidden patterns
55
+
56
+ These never appear in source code:
57
+
58
+ - `sk_live_*`, `pk_live_*` — live Stripe keys live in your deployment
59
+ platform's secrets store, never in source files or `.env`.
60
+ - Direct vendor SDK imports outside the wrapper packages
61
+ (`import 'stripe'` outside `@working-theory/stripe-client`, etc.).
62
+ - Hardcoded production database URLs in committed files.
@@ -0,0 +1,51 @@
1
+ # Preserve Existing Style
2
+
3
+ When editing existing files, preserve their existing formatting. Do
4
+ **not** reformat, reflow, reorganize imports, change quote style,
5
+ change indentation, or rearrange whitespace on lines that aren't
6
+ materially changing as part of your task.
7
+
8
+ Your diff should contain only the lines you deliberately touched. A
9
+ 20-line functional change should produce a ~20-line diff, not a
10
+ 900-line diff with 880 lines of formatting churn.
11
+
12
+ ## Why
13
+
14
+ Formatting churn:
15
+
16
+ - Obscures real changes during code review.
17
+ - Creates noise in `git blame` / `git log`.
18
+ - Triggers unnecessary merge conflicts.
19
+ - Violates the spirit of "behavior must not change unless the
20
+ acceptance criteria say so" — even if runtime behavior is identical,
21
+ the meaning to a human reader has changed.
22
+
23
+ ## How to apply
24
+
25
+ - **Before committing:** run `git diff --stat`. If the delta is
26
+ wildly larger than the work you did, investigate before pushing.
27
+ - **If your editor runs a formatter on save:** disable it for the
28
+ session, configure it to match the existing style, or revert
29
+ formatting-only lines before committing.
30
+ - **If quotes, semicolons, or import grouping differ from the
31
+ existing file:** match the existing file, not your editor's
32
+ defaults.
33
+ - **The diff is the contract.** A reviewer should see only the lines
34
+ you meant to change.
35
+
36
+ ## Not covered by this rule
37
+
38
+ - Deliberate cleanup (removing dead code, inlining single-use
39
+ helpers, collapsing redundant abstraction) is fine when it's the
40
+ point of the task and called out in the PR.
41
+ - Net-new files set their own style, subject to the project's
42
+ existing conventions.
43
+ - A task whose acceptance criteria explicitly say "reformat file X"
44
+ (rare).
45
+
46
+ ## Escalation
47
+
48
+ If you believe the existing style is genuinely wrong and want to
49
+ change it: stop. Note it in the PR description and propose the
50
+ reformat as a separate PR. Do not unilaterally reformat the codebase
51
+ as a side effect of an unrelated task.
@@ -0,0 +1,43 @@
1
+ # Skills
2
+
3
+ Skills are reusable Claude Code workflows scoped to this project. Each
4
+ lives in its own subdirectory with a `SKILL.md` describing when to use
5
+ it and how it works.
6
+
7
+ The seven OSS skills below are the canonical AI Launch Kit workflows.
8
+ Their status reflects what's available at the upstream
9
+ <https://github.com/tailwind-ai/ai-launch-kit> repository today. Issue
10
+ numbers in the table refer to that upstream repo (the
11
+ `tailwind-ai/ai-launch-kit#N` form makes the link explicit), not your
12
+ local project's issues.
13
+
14
+ ## Status
15
+
16
+ | Skill | Purpose | Status |
17
+ | -------------------- | ------------------------------------------------------ | ---------------------------------------------------- |
18
+ | `suggest-site-pages` | Generic page-type suggestions by category | coming soon — issue #361 (tailwind-ai/ai-launch-kit) |
19
+ | `scaffold-page` | Generate a page with the appropriate schema.org type | coming soon — issue #362 (tailwind-ai/ai-launch-kit) |
20
+ | `scaffold-commerce` | Sell stuff: external store link or direct payments | coming soon — issue #363 (tailwind-ai/ai-launch-kit) |
21
+ | `scaffold-auth` | Wire up an auth flow against `@working-theory/auth-client` | coming soon — issue #364 (tailwind-ai/ai-launch-kit) |
22
+ | `audit-site` | Run `ailk audit` and explain the results | coming soon — issue #365 (tailwind-ai/ai-launch-kit) |
23
+ | `add-schema` | Add Product / Service / FAQ schema to an existing page | coming soon — issue #366 (tailwind-ai/ai-launch-kit) |
24
+ | `provision-config` | Generate `vercel.json` and environment templates | coming soon — issue #367 (tailwind-ai/ai-launch-kit) |
25
+
26
+ ## How a skill ships
27
+
28
+ When a skill is built upstream, this directory will contain a
29
+ subdirectory of the same name, each holding:
30
+
31
+ - `SKILL.md` — when to invoke, what it produces, what it requires.
32
+ - Any supporting prompt fragments, code templates, or reference
33
+ files the skill loads at runtime.
34
+
35
+ Until then, the workflows the skills will perform can still be done
36
+ by hand or by asking Claude Code directly.
37
+
38
+ ## Adding your own
39
+
40
+ To add a project-specific skill, create a folder here with a
41
+ `SKILL.md` describing it. Claude Code will discover it automatically
42
+ on session start. See the upstream `@working-theory/*` repository for examples
43
+ of the format.