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,132 @@
1
+ // S16 — Security-headers config (#612)
2
+ //
3
+ // Source of truth for the 7 baseline security headers applied by
4
+ // `apps/web/middleware.ts`, plus the typed customer-extension interface.
5
+ //
6
+ // Spec: docs/internal/specs/ailk-pre-oss-security-phase-3-s16-security-headers-spec.md
7
+ // Customer guide: docs/security/csp.md
8
+ //
9
+ // Locked directives — customers may NOT relax these via extension:
10
+ // - CSP `frame-ancestors 'none'`
11
+ // - CSP `base-uri 'self'`
12
+ // - Strict-Transport-Security (HSTS) entirely
13
+ //
14
+ // Customers MAY add additional sources to the extensible CSP directives
15
+ // (`script-src`, `style-src`, `img-src`, `font-src`, `connect-src`, `media-src`,
16
+ // `worker-src`, `frame-src`, `object-src`) by listing them in the
17
+ // `csp` field of a `SecurityHeadersExtension`.
18
+
19
+ /** Map of CSP directives keyed by directive name → list of source expressions. */
20
+ export type CspDirectiveMap = Record<string, readonly string[]>;
21
+
22
+ /** Customer-supplied extension; only the listed surfaces can be extended. */
23
+ export type SecurityHeadersExtension = {
24
+ /**
25
+ * Additional CSP source expressions to append per directive.
26
+ * Customers may extend directives like `script-src`, `style-src`,
27
+ * `connect-src`, `img-src`, `font-src`, `media-src`, `worker-src`,
28
+ * `frame-src`, `object-src`. Attempting to extend a locked directive
29
+ * (`frame-ancestors`, `base-uri`) throws at build time.
30
+ */
31
+ csp?: CspDirectiveMap;
32
+ };
33
+
34
+ /** CSP directives that customers cannot override or relax. */
35
+ const LOCKED_CSP_DIRECTIVES = new Set(["frame-ancestors", "base-uri"]);
36
+
37
+ /** Top-level extension keys that attempt to relax HSTS. Customers may not
38
+ * reach Strict-Transport-Security via any of these aliases. */
39
+ const HSTS_ALIASES = new Set([
40
+ "hsts",
41
+ "strict-transport-security",
42
+ "Strict-Transport-Security",
43
+ ]);
44
+
45
+ /** Baseline CSP directives. Each key is a directive; each value is the list
46
+ * of source expressions emitted as a single space-joined directive entry. */
47
+ const BASELINE_CSP: CspDirectiveMap = {
48
+ "default-src": ["'self'"],
49
+ // 'unsafe-inline' kept until app inline scripts are nonced (see csp.md).
50
+ "script-src": ["'self'", "'unsafe-inline'"],
51
+ "style-src": ["'self'", "'unsafe-inline'"],
52
+ "img-src": ["'self'", "data:", "https:"],
53
+ "font-src": ["'self'"],
54
+ "connect-src": ["'self'", "https://api.stripe.com"],
55
+ "frame-ancestors": ["'none'"],
56
+ "form-action": ["'self'"],
57
+ "base-uri": ["'self'"],
58
+ };
59
+
60
+ /** Compose a CSP header string from a directive map. */
61
+ function serializeCsp(directives: CspDirectiveMap): string {
62
+ return Object.entries(directives)
63
+ .map(([directive, sources]) => `${directive} ${sources.join(" ")}`)
64
+ .join("; ");
65
+ }
66
+
67
+ /** Merge customer CSP extension into the baseline, refusing locked directives. */
68
+ function mergeCsp(extension: CspDirectiveMap | undefined): CspDirectiveMap {
69
+ if (!extension) return BASELINE_CSP;
70
+
71
+ const merged: Record<string, string[]> = {};
72
+ for (const [directive, sources] of Object.entries(BASELINE_CSP)) {
73
+ merged[directive] = [...sources];
74
+ }
75
+
76
+ for (const [directive, sources] of Object.entries(extension)) {
77
+ if (LOCKED_CSP_DIRECTIVES.has(directive)) {
78
+ throw new Error(
79
+ `Security headers: CSP directive '${directive}' is locked and cannot be overridden by customer extension.`,
80
+ );
81
+ }
82
+ if (!sources || sources.length === 0) continue;
83
+ const existing = merged[directive] ?? [];
84
+ // Baseline ordering preserved first; new sources appended; duplicates dropped.
85
+ merged[directive] = Array.from(new Set([...existing, ...sources]));
86
+ }
87
+ return merged;
88
+ }
89
+
90
+ /** Compose the final header map, given an optional customer extension. */
91
+ export function buildHeaders(
92
+ extension?: SecurityHeadersExtension,
93
+ ): Record<string, string> {
94
+ // SecurityHeadersExtension only exposes `csp`, but a customer that bypasses
95
+ // the type (e.g. JSON config) might smuggle an HSTS override. Reject named
96
+ // attempts; tolerate unknown keys silently for forward-compatibility.
97
+ if (extension) {
98
+ for (const key of Object.keys(extension)) {
99
+ if (HSTS_ALIASES.has(key)) {
100
+ throw new Error(
101
+ "Security headers: Strict-Transport-Security (HSTS) is locked and cannot be overridden by customer extension.",
102
+ );
103
+ }
104
+ }
105
+ }
106
+
107
+ const cspMap = mergeCsp(extension?.csp);
108
+ return {
109
+ "Content-Security-Policy": serializeCsp(cspMap),
110
+ "Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
111
+ "X-Frame-Options": "DENY",
112
+ "X-Content-Type-Options": "nosniff",
113
+ "Referrer-Policy": "strict-origin-when-cross-origin",
114
+ "Permissions-Policy":
115
+ "camera=(), microphone=(), geolocation=(), interest-cohort=()",
116
+ "X-DNS-Prefetch-Control": "off",
117
+ };
118
+ }
119
+
120
+ /** Canonical default header map — no customer extension. Frozen for safety. */
121
+ export const DEFAULT_SECURITY_HEADERS: Readonly<Record<string, string>> =
122
+ Object.freeze(buildHeaders());
123
+
124
+ /** Write every entry from a header map onto a Headers object. */
125
+ export function applyHeaders(
126
+ target: Headers,
127
+ source: Record<string, string>,
128
+ ): void {
129
+ for (const [key, value] of Object.entries(source)) {
130
+ target.set(key, value);
131
+ }
132
+ }
@@ -0,0 +1,27 @@
1
+ // Sentry client-side init for apps/web (#894).
2
+ //
3
+ // Loaded automatically by @sentry/nextjs at the start of every browser bundle.
4
+ // When NEXT_PUBLIC_SENTRY_DSN is unset (the OSS-install default), `enabled`
5
+ // resolves false and the SDK becomes a no-op — no network, no captures, no
6
+ // console noise. When the DSN is set, the SDK initialises in the browser and
7
+ // every uncaught error or unhandled promise rejection is forwarded to Sentry.
8
+ //
9
+ // Mirrors the env-driven OSS-default-on shape from #884 (stealth) and #886
10
+ // (Google Analytics). Per Sentry's Next.js SDK skill, this file (or
11
+ // `instrumentation-client.ts` on newer scaffolds) is the canonical browser
12
+ // entry point.
13
+
14
+ import * as Sentry from "@sentry/nextjs";
15
+
16
+ Sentry.init({
17
+ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
18
+ enabled: !!process.env.NEXT_PUBLIC_SENTRY_DSN,
19
+
20
+ // Capture 10% of transactions in production; 100% in development. The
21
+ // production rate keeps the Sentry quota workable; dev sees everything.
22
+ tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
23
+
24
+ // Session replays: 10% of all sessions, 100% of sessions that hit an error.
25
+ replaysSessionSampleRate: 0.1,
26
+ replaysOnErrorSampleRate: 1.0,
27
+ });
@@ -0,0 +1,15 @@
1
+ // Sentry edge-runtime init for apps/web (#894).
2
+ //
3
+ // Loaded by @sentry/nextjs in the Edge runtime (middleware, edge route
4
+ // handlers). When SENTRY_DSN is unset (the OSS-install default), `enabled`
5
+ // resolves false and the SDK becomes a no-op. Paired with
6
+ // sentry.client.config.ts (browser) and sentry.server.config.ts (Node.js).
7
+
8
+ import * as Sentry from "@sentry/nextjs";
9
+
10
+ Sentry.init({
11
+ dsn: process.env.SENTRY_DSN,
12
+ enabled: !!process.env.SENTRY_DSN,
13
+
14
+ tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
15
+ });
@@ -0,0 +1,20 @@
1
+ // Sentry server-runtime init for apps/web (#894).
2
+ //
3
+ // Loaded by @sentry/nextjs in the Node.js runtime (App Router server
4
+ // components, route handlers, server actions). When SENTRY_DSN is unset
5
+ // (the OSS-install default), `enabled` resolves false and the SDK becomes a
6
+ // no-op. When the DSN is set, every server-side uncaught exception is
7
+ // forwarded to Sentry.
8
+ //
9
+ // Paired with sentry.client.config.ts (browser) and sentry.edge.config.ts
10
+ // (Edge runtime) — all three gate on the same env presence pattern from
11
+ // #884 / #886.
12
+
13
+ import * as Sentry from "@sentry/nextjs";
14
+
15
+ Sentry.init({
16
+ dsn: process.env.SENTRY_DSN,
17
+ enabled: !!process.env.SENTRY_DSN,
18
+
19
+ tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
20
+ });
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Fumadocs MDX collection definitions.
3
+ *
4
+ * Drives the source loader in `lib/source.ts`. Per-app content directories
5
+ * (2026-05-25 path divergence — issue #1459): each deploy target owns its own
6
+ * content directory. Blog and docs content for the OSS template live at
7
+ * `apps/web/content/en/{blog,docs}/`. Fresh OSS forks own their content
8
+ * directory cleanly without inheriting ailaunchkit.ai-specific posts.
9
+ *
10
+ * i18n Phase 3 S2 (2026-05-18) moved content to `content/<locale>/<type>/`.
11
+ * Default-locale content lives at `content/en/`. Per-locale fumadocs
12
+ * collections (Spanish, French, etc.) are a Working Theory paid feature —
13
+ * out of scope for OSS.
14
+ *
15
+ * Frontmatter contract for blog:
16
+ * - `title` (string, required) — maps to schema.org `headline`
17
+ * - `description` (string, required) — maps to schema.org `description`
18
+ * - `date` (ISO date string, optional) — maps to schema.org `datePublished`
19
+ * - `updated` (ISO date string, optional) — maps to schema.org `dateModified`
20
+ * - `image` (URL/path string, optional) — maps to schema.org `image`
21
+ * - `author` (object, optional) — `{ name, avatar? }`; feeds the
22
+ * BlogList/BlogPost section byline (issue #2713).
23
+ * - `tags` (string[], optional) — feeds the section `categories`
24
+ * chips (issue #2713).
25
+ *
26
+ * Frontmatter contract for docs:
27
+ * - `title` (string, required)
28
+ * - `description` (string, required)
29
+ */
30
+ import * as path from "path";
31
+ import { fileURLToPath } from "url";
32
+
33
+ import { defineDocs } from "fumadocs-mdx/config";
34
+ import { z } from "zod";
35
+
36
+ // fumadocs-mdx compiles source.config.ts to .source/source.config.mjs before
37
+ // running it, so import.meta.url inside the compiled file resolves to
38
+ // apps/web/.source/source.config.mjs. The content directories live one level
39
+ // up at apps/web/content/en/{blog,docs}/, so the relative prefix is "../".
40
+ // Using a bare "content/en/blog" (no "../") anchors to .source/content/en/blog
41
+ // which does not exist and produces an empty blog source at runtime (404 on
42
+ // /blog/* routes). Fix: issue #1518.
43
+ const blogDir = path.resolve(
44
+ path.dirname(fileURLToPath(import.meta.url)),
45
+ "../content/en/blog",
46
+ );
47
+
48
+ const docsDir = path.resolve(
49
+ path.dirname(fileURLToPath(import.meta.url)),
50
+ "../content/en/docs",
51
+ );
52
+
53
+ export const blog = defineDocs({
54
+ dir: blogDir,
55
+ docs: {
56
+ schema: z.object({
57
+ title: z.string(),
58
+ description: z.string(),
59
+ date: z.string().optional(),
60
+ updated: z.string().optional(),
61
+ image: z.string().optional(),
62
+ author: z
63
+ .object({ name: z.string(), avatar: z.string().optional() })
64
+ .optional(),
65
+ tags: z.array(z.string()).optional(),
66
+ }),
67
+ },
68
+ });
69
+
70
+ export const docs = defineDocs({
71
+ dir: docsDir,
72
+ docs: {
73
+ schema: z.object({
74
+ title: z.string(),
75
+ description: z.string(),
76
+ }),
77
+ },
78
+ });
@@ -0,0 +1,21 @@
1
+ // SiteNav — minimal site-wide navigation. Server Component (no interactivity needed).
2
+ // data-testid anchors serve the post-OSS e2e suite (e2e-testing-roadmap.md §5.2).
3
+ import { Link } from "@working-theory/ui";
4
+ import type { ReactElement } from "react";
5
+
6
+ // i18n-allow: nav labels are static English for v1 (single-locale). ADR 0019
7
+ // follow-up: migrate to getTranslations when SiteNav becomes async.
8
+ const NAV_LABELS = { home: "Home", contact: "Contact" } as const;
9
+
10
+ export function SiteNav(): ReactElement {
11
+ return (
12
+ <nav aria-label="Site navigation">
13
+ <Link href="/" data-testid="nav-home-link">
14
+ {NAV_LABELS.home}
15
+ </Link>
16
+ <Link href="/contact" data-testid="nav-contact-link">
17
+ {NAV_LABELS.contact}
18
+ </Link>
19
+ </nav>
20
+ );
21
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared route utilities for agent-surface discovery routes.
3
+ *
4
+ * Extracted from llms.txt, sitemap.xml, robots.txt, and ai-plugin.json
5
+ * handlers to avoid copy-paste duplication.
6
+ */
7
+
8
+ /**
9
+ * Resolves the canonical base URL for the site.
10
+ * Falls back to a placeholder so routes work without env configuration.
11
+ */
12
+ export function resolveBaseUrl(): string {
13
+ return process.env["NEXT_PUBLIC_BASE_URL"] ?? "https://ailk.example.com";
14
+ }
15
+
16
+ /**
17
+ * Maps a content-adapter page type + slug to a site-relative path.
18
+ * Drives both /llms.txt and /sitemap.xml URL generation.
19
+ */
20
+ export function slugToPath(type: string, slug: string): string {
21
+ switch (type) {
22
+ case "HomePage":
23
+ return "/";
24
+ case "BlogPosting":
25
+ return `/blog/${slug}`;
26
+ case "Product":
27
+ return `/products/${slug}`;
28
+ case "Service":
29
+ return `/services/${slug}`;
30
+ case "AboutPage":
31
+ return "/about";
32
+ case "ContactPage":
33
+ return "/contact";
34
+ default:
35
+ return `/${slug}`;
36
+ }
37
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "paths": {
5
+ "@/*": ["./*"]
6
+ },
7
+ "target": "ES2022",
8
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
9
+ "module": "ESNext",
10
+ "moduleResolution": "bundler",
11
+ "jsx": "preserve",
12
+ "allowJs": true,
13
+ "noEmit": true,
14
+ "incremental": true,
15
+ "plugins": [{ "name": "next" }],
16
+ "types": ["jest", "node", "@testing-library/jest-dom"]
17
+ },
18
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
19
+ "exclude": ["node_modules", ".next", "dist"],
20
+ "references": [
21
+ { "path": "../../packages/analytics" },
22
+ { "path": "../../packages/page-renderer" },
23
+ { "path": "../../packages/api-client" },
24
+ { "path": "../../packages/theme" },
25
+ { "path": "../../packages/content-adapters" },
26
+ { "path": "../../packages/fumadocs-schema" },
27
+ { "path": "../../packages/metadata" },
28
+ { "path": "../../packages/schema" },
29
+ { "path": "../../packages/schema-pack-registry" },
30
+ { "path": "../../packages/templates" },
31
+ { "path": "../../packages/ui" },
32
+ { "path": "../../packages/validation" },
33
+ { "path": "../../packages/web-i18n" }
34
+ ]
35
+ }
@@ -0,0 +1,19 @@
1
+ // i18n S2 — Type-safe useTranslations key declarations (#949)
2
+ //
3
+ // Declares the shape of `messages/en.json` to TypeScript so that
4
+ // `useTranslations('namespace')` returns a narrowly typed accessor.
5
+ // Typos in key names (e.g. `t('consnt.title')`) are caught at compile time
6
+ // by `tsc --noEmit`.
7
+ //
8
+ // To verify: intentionally misspell a key in a component and run
9
+ // `pnpm --filter @working-theory/web type-check` — the compiler will error.
10
+
11
+ import type enMessages from "../messages/en.json";
12
+
13
+ type Messages = typeof enMessages;
14
+
15
+ declare global {
16
+ // next-intl reads this via module augmentation.
17
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
18
+ interface IntlMessages extends Messages {}
19
+ }
File without changes
@@ -0,0 +1,85 @@
1
+ # content/ — MDX Content Authoring
2
+
3
+ Inherits root `CLAUDE.md`. This file owns content-authoring rules.
4
+
5
+ ## What lives here
6
+
7
+ File-based MDX content, one file per page, organized by page type:
8
+
9
+ content/
10
+ ├── HomePage/home.mdx
11
+ ├── ServicesList/services.mdx
12
+ ├── Service/<slug>.mdx
13
+ ├── BlogList/blog.mdx
14
+ ├── BlogPosting/<slug>.mdx
15
+ └── ...
16
+
17
+ For the full list of supported page types and what each emits, see `packages/schema/README.md`. It's the source of truth. For per-page-type component guidance (which `@working-theory/ui` components are idiomatic for each family), see `packages/schema/CLAUDE.md` § `@working-theory/ui` component map.
18
+
19
+ ## Frontmatter contract (hard rule)
20
+
21
+ Every MDX file has frontmatter validated at build time against `@working-theory/schema`. Required:
22
+
23
+ - `type` — must match a `SchemaOrgType` key from the schema README
24
+ - `slug` — URL slug, no leading slash
25
+ - `title` — visible page title
26
+ - `description` — meta description and JSON-LD `description`
27
+
28
+ Optional:
29
+
30
+ - `locale` — defaults to `'en'`. Emitted as `inLanguage`.
31
+ - `publishedAt`, `updatedAt`, `image`
32
+ - `schema` — escape hatch (see below)
33
+
34
+ Build fails on missing/invalid frontmatter. Fix the frontmatter, not the validator.
35
+
36
+ ## The `schema` field (escape hatch)
37
+
38
+ `schema` is a shallow-merged record. Frontmatter wins on conflicts with the builder. Use it to:
39
+
40
+ - Add structured sub-entities (`author`, `mainEntity`, `step`)
41
+ - Enrich page types whose schema.org default is generic (e.g. Integration → `mainEntity: SoftwareApplication`)
42
+ - Override a derived field (rare)
43
+
44
+ Some types (JobPosting in particular) REQUIRE programmatic overrides for full coverage — frontmatter alone can't express `baseSalary`, `employmentType`. See `packages/schema/README.md` for which types need code-level overrides.
45
+
46
+ After using `schema`, run `ailk audit` — a malformed override produces invalid JSON-LD and tanks AEO scoring.
47
+
48
+ ## Component vocabulary (universal — page type doesn't change this)
49
+
50
+ These components are available on any page. Choice depends on content, not page type. An FAQ block belongs in `<FAQ>` whether it's on a HomePage, ServicePage, or FAQPage.
51
+
52
+ - `<Hero>` — top-of-page hero. One per page max.
53
+ - `<FAQ>` — FAQ entry. **One question per block** (see AEO rules below).
54
+ - `<CTA>` — call-to-action card. Use sparingly.
55
+ - `<Testimonial>` — single testimonial. Multiple = multiple blocks.
56
+ - `<PriceTable>` — pricing display.
57
+ - `<FeatureGrid>` — feature/benefit grid.
58
+ - `<Locations>` — physical locations.
59
+ - `<BusinessHours>` — hours of operation.
60
+
61
+ For the per-page-type editorial map (which family of pages typically uses which components), see `packages/schema/CLAUDE.md` § `@working-theory/ui` component map.
62
+
63
+ Don't use raw HTML where a component exists. Components carry schema and styling guarantees; `<div>` soup throws both away.
64
+
65
+ ## AEO editorial craft (universal — this is the wedge)
66
+
67
+ **Lead with the answer.** First 60 words of body content state the answer to the page's implicit question. LLM citation extractors read top-down and bail early. Backstory comes after.
68
+
69
+ **One question per `<FAQ>` block.** Don't cram multiple Q&As into one block. Each block becomes one `Question` entity in JSON-LD — separation drives citability.
70
+
71
+ **Entity clarity in the first paragraph.** Name the company, product, location, or person explicitly. "We" and "our service" are entity-opaque. AEO rewards unambiguous attribution.
72
+
73
+ **Concrete claims over adjectives.** "Ships in 48 hours" beats "fast turnaround." Specifics get cited; vagueness gets skipped.
74
+
75
+ **Headings as questions when natural.** H2/H3 phrased as questions (when the content actually answers one) align with passage extraction.
76
+
77
+ **Don't pad for length.** A 400-word page that answers cleanly outperforms a 1,500-word page that buries the answer.
78
+
79
+ ## What NOT to do
80
+
81
+ - Don't hand-roll JSON-LD in MDX body. Ever.
82
+ - Don't use `<script type="application/ld+json">` inside content.
83
+ - Don't bypass the frontmatter validator.
84
+ - Don't write `type: WebPage` to silence a validator error — pick the right type.
85
+ - Don't use raw `<h1>` in body. The page template emits the H1 from `title`.
@@ -0,0 +1,38 @@
1
+ ---
2
+ version: "1"
3
+ siteName: AI Launch Kit
4
+ baseUrl: https://ailaunchkit.ai
5
+ defaultLocale: en
6
+ siteIdentity:
7
+ kind: Organization
8
+ name: AI Launch Kit
9
+ url: https://ailaunchkit.ai
10
+ logo: https://ailaunchkit.ai/opengraph-image.png
11
+ description: >
12
+ AI Launch Kit is the open-source website foundation for the agent-first
13
+ internet. Apache 2.0, agent-ready, AEO-scored, deployable in days.
14
+ sameAs:
15
+ - https://github.com/tailwind-ai/ai-launch-kit
16
+ foundingDate: "2024"
17
+ founderName: Sam Henry
18
+ analytics:
19
+ vercelAnalytics: true
20
+ brand:
21
+ logomark:
22
+ light: /logomark-light.svg
23
+ dark: /logomark-dark.svg
24
+ alt: AI Launch Kit
25
+ ---
26
+
27
+ <!--
28
+ This file is your site's canonical configuration. Edit the frontmatter
29
+ above to set your site name, base URL, default locale, and identity
30
+ (Organization, Person, or LocalBusiness).
31
+
32
+ For the agent-operator workflow, use the `set_site_identity` MCP tool
33
+ instead of editing this file directly — it validates input and writes
34
+ with optimistic locking.
35
+
36
+ See docs/site-config.md (introduced in Phase 3) for the full schema
37
+ reference and the three identity kinds.
38
+ -->
@@ -0,0 +1,123 @@
1
+ ---
2
+ type: HomePage
3
+ slug: home
4
+ title: AI Launch Kit — أساس الموقع الإلكتروني مفتوح المصدر لإنترنت عصر الذكاء الاصطناعي
5
+ description: قالب مفتوح المصدر Apache 2.0 مُصمَّم لبحث الذكاء الاصطناعي. جاهز للوكلاء، مُقيَّم بمعايير AEO، قابل للنشر في أيام.
6
+ sections:
7
+ - id: hero-1
8
+ type: hero
9
+ data:
10
+ variant: centered
11
+ headline: AI Launch Kit — أساس الموقع الإلكتروني مفتوح المصدر لإنترنت عصر الذكاء الاصطناعي
12
+ subheadline: قالب مفتوح المصدر Apache 2.0 مُصمَّم لبحث الذكاء الاصطناعي. جاهز للوكلاء، مُقيَّم بمعايير AEO، قابل للنشر في أيام.
13
+ body: مبني من قِبَل فريق Working Theory ومُستخدَم لتشغيل Sam Henry وWorking Theory وSalesSmyth على نفس البنية التحتية. ثلاثة مسارات أدناه. اختر الذي يناسبك.
14
+ primaryCta:
15
+ label: اختر مسارك
16
+ href: "#choose-your-path"
17
+ secondaryCta:
18
+ label: نجوم على GitHub
19
+ href: https://github.com/working-theory/ai-launch-kit
20
+ external: true
21
+
22
+ - id: stats-1
23
+ type: stats
24
+ data:
25
+ variant: tiles
26
+ headline: مبني ليُستشهد به منذ اليوم الأول
27
+ items:
28
+ - value: "45"
29
+ label: أنواع مخطط الصفحة
30
+ - value: "21"
31
+ label: أنواع الأقسام
32
+ - value: "14"
33
+ label: أدوات MCP
34
+ - value: Apache 2.0
35
+ label: الرخصة
36
+
37
+ - id: content-block-1
38
+ type: content-block
39
+ data:
40
+ variant: narrow
41
+ headline: الصفحة هي وحدة الاستشهاد، وليس الموقع بأكمله
42
+ body: |
43
+ عندما يوصي نموذج ذكاء اصطناعي بشركة ما، فإنه يجمع التوصية من صفحات فردية
44
+ قرأها ونسبها إلى علامة تجارية ووثق بها بما يكفي لاقتباسها. العلامة التجارية التي يُستشهد
45
+ بها هي العلامة التجارية التي قُرئت صفحاتها بشكل صحيح.
46
+
47
+ المواقع التي لا تحتوي على كيانات مُعلَنة تخسر في خطوة الإسناد. لا يستطيع النموذج
48
+ تحديد الكيان الذي تنتمي إليه الصفحة، لذا يستشهد بمنافس كانت صفحته أوضح.
49
+ ويفشل عمل AEO بصمت عند هذه النقطة.
50
+
51
+ - id: feature-1
52
+ type: feature
53
+ data:
54
+ variant: alternating
55
+ headline: أربع قدرات هيكلية تجعل الموقع قابلاً للاستشهاد به منذ وقت النشر
56
+ description: >
57
+ كل قدرة قابلة للتحقق اليوم — ليست وعداً في خارطة الطريق.
58
+ انسخ المستودع وشغِّل ailk audit لترى بنفسك.
59
+ features:
60
+ - title: سجل مخططات مُصنَّفة
61
+ description: >
62
+ 45 نوع صفحة تُعلِن كل كيان بشكل صحيح. النموذج يعرف موضوع الصفحة
63
+ والشركة التي تنتمي إليها.
64
+ icon: database
65
+ - title: خادم MCP من الدرجة الأولى
66
+ description: >
67
+ تكافؤ مُطبَّق في CI مع واجهة المستخدم البشرية. الوكلاء الذين يبحثون نيابة عن
68
+ المشتري يجدون نفس السطح، وليس تقريباً متدهوراً.
69
+ icon: bot
70
+ - title: CLI لتسجيل نقاط AEO
71
+ description: >
72
+ يُشغِّل ailk audit فحوصات الاستشهاد في CI قبل إطلاق الموقع.
73
+ المشاكل الهيكلية تُكتَشف في CI، وليس بعد ثلاثة أشهر من الإطلاق.
74
+ icon: check-circle
75
+ - title: سقالة مُساعَدة بالذكاء الاصطناعي
76
+ description: >
77
+ من العلامة التجارية المرجعية إلى الموقع المُنشَر في أيام. مسارات السقالة
78
+ تستهدف وكلاء Claude Code بمسار تثبيت قابل للتكرار.
79
+ icon: zap
80
+
81
+ - id: items-1
82
+ type: items
83
+ data:
84
+ headline: اختر مسارك
85
+ description: ثلاثة مسارات، بنية تحتية واحدة. كل بطاقة تقودك إلى الصفحة المكتوبة لدورك.
86
+ columns: 3
87
+ items:
88
+ - title: أدير وكالة بحث الذكاء الاصطناعي
89
+ description: AILK هو البنية التحتية لإطلاق مواقع الشركات الصغيرة والمتوسطة التي تعمل للوكلاء والبشر منذ اليوم الأول.
90
+ icon: briefcase
91
+ link:
92
+ label: اقرأ أطروحة الوكالة
93
+ href: /partners
94
+ - title: أنا مطور أو مستقل
95
+ description: مستودع Apache 2.0. pnpm create ailk@latest للسقالة؛ ailk audit للتسجيل؛ النشر على Vercel من نسخة جديدة.
96
+ icon: code
97
+ link:
98
+ label: افتح توثيقات المطور
99
+ href: /docs
100
+ - title: وكالة أخبرتني للنظر في هذا
101
+ description: AILK هو أساس الموقع الذي تستخدمه وكالتك. ChatGPT وClaude يستطيعان قراءة الصفحات المبنية عليه.
102
+ icon: users
103
+ link:
104
+ label: اعرف ما تبني وكالتك عليه
105
+ href: /for-businesses
106
+
107
+ - id: cta-1
108
+ type: cta
109
+ data:
110
+ variant: box
111
+ headline: اختر مساراً
112
+ description: ثلاثة مسارات من هنا. اختر المكتوب لك، أو نجِّم AILK على GitHub وارجع عندما تكون مستعداً.
113
+ primaryCta:
114
+ label: أدير وكالة بحث الذكاء الاصطناعي
115
+ href: /partners
116
+ secondaryCta:
117
+ label: نجِّم AILK على GitHub
118
+ href: https://github.com/working-theory/ai-launch-kit
119
+ external: true
120
+ ---
121
+
122
+ <!-- محتوى MDX محفوظ لمحولات المحتوى التي تستخدمه، لكن الصفحة تعرض من أقسام frontmatter. -->
123
+ <!-- RTL test page — Arabic placeholder content for architecture verification (TWP2-IV) -->