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,72 @@
1
+ // Emitted by `scaffold-commerce` (link path). Owns its own
2
+ // <MarketplaceCTA> component definition — not imported from
3
+ // @working-theory/ui — so you can edit the styling, add tracking, change
4
+ // the icon layout, etc., without forking a shared package.
5
+ //
6
+ // The skill substitutes:
7
+ // {{HREF}} — storefront URL (e.g., https://amazon.com/my-shop)
8
+ // {{LABEL}} — button text (e.g., "Buy on Amazon")
9
+ // {{ICON}} — optional iconSrc prop binding (e.g., iconSrc="/logos/amazon.svg")
10
+ // or empty when the consumer chose text-only
11
+
12
+ import type { ReactNode } from "react";
13
+
14
+ interface MarketplaceCTAProps {
15
+ href: string;
16
+ label: ReactNode;
17
+ iconSrc?: string;
18
+ className?: string;
19
+ }
20
+
21
+ /**
22
+ * MarketplaceCTA — outbound link to an external storefront.
23
+ *
24
+ * Renders a single anchor styled as a button. Optional iconSrc renders
25
+ * a small <img> next to the label; omitting it produces a clean
26
+ * text-only button. Customize freely — this component is yours, not
27
+ * a shared dep.
28
+ */
29
+ function MarketplaceCTA({
30
+ href,
31
+ label,
32
+ iconSrc,
33
+ className,
34
+ }: MarketplaceCTAProps) {
35
+ const baseClasses =
36
+ "inline-flex items-center gap-2 rounded-md border border-current px-4 py-2 text-sm font-medium hover:bg-current/5 transition-colors";
37
+ const finalClassName = className
38
+ ? `${baseClasses} ${className}`
39
+ : baseClasses;
40
+
41
+ return (
42
+ <a
43
+ href={href}
44
+ target="_blank"
45
+ rel="noopener noreferrer"
46
+ className={finalClassName}
47
+ >
48
+ {iconSrc ? (
49
+ <img src={iconSrc} alt="" aria-hidden="true" className="h-5 w-5" />
50
+ ) : null}
51
+ <span>{label}</span>
52
+ </a>
53
+ );
54
+ }
55
+
56
+ export default function BuyPage() {
57
+ return (
58
+ <main className="mx-auto max-w-2xl px-6 py-12">
59
+ <h1 className="text-3xl font-semibold">Get yours</h1>
60
+ <p className="mt-3 text-muted-foreground">
61
+ Available at our store on the marketplace below.
62
+ </p>
63
+ <div className="mt-8">
64
+ <MarketplaceCTA
65
+ href="{{HREF}}"
66
+ label="{{LABEL}}"
67
+ {{ICON}}
68
+ />
69
+ </div>
70
+ </main>
71
+ );
72
+ }
@@ -0,0 +1,243 @@
1
+ ---
2
+ name: scaffold-page
3
+ description: Generate a new page on an AILK consumer site — App Router route + MDX content stub + typed JSON-LD attachment — in a single confirm-before-write pass. Use when the user says "scaffold me a /pricing page", "add an about page", "create a /contact route", or chains a row from `suggest-site-pages` output (e.g., "scaffold home — Organization — anchor with hero, value prop, CTA"). Both invocation shapes flow through the same pipeline. MDX-only at v1; refuses on existing routes and points at `add-schema` (#366).
4
+ ---
5
+
6
+ # scaffold-page
7
+
8
+ Generate a new page in one pass. Three artifacts emit together:
9
+
10
+ 1. **App Router route** at `app/<slug>/page.tsx`
11
+ 2. **MDX content stub** at `content/<Type>/<slug>.mdx`
12
+ 3. **JSON-LD attachment** via `<JsonLd schema={build<Type>(page)} />` from
13
+ `@working-theory/jsonld` (component) and `@working-theory/schema` (typed builder)
14
+
15
+ Single confirm-before-write — no per-file or per-step prompts.
16
+
17
+ ## When to use
18
+
19
+ The consumer wants a new page on their AILK site. Triggers:
20
+
21
+ - "scaffold me a /pricing page" / "create a /contact route"
22
+ - "add an about page" / "I need a /privacy page"
23
+ - A row chained from `suggest-site-pages` output:
24
+ `home — Organization — anchor with hero, value prop, CTA`
25
+ - "scaffold that one" referring to a specific row from prior chat output
26
+
27
+ Skip this skill when:
28
+
29
+ - The consumer wants to **add schema to an existing page** — that's
30
+ `add-schema` (#366). This skill refuses on existing routes and
31
+ points at #366 explicitly.
32
+ - The consumer wants to **plan their pages** — that's
33
+ `suggest-site-pages` (#361). Output of #361 is this skill's chained
34
+ input contract.
35
+ - The consumer's content backend is **not MDX**. v1 is MDX-only —
36
+ other adapters (Sanity, Payload, additional adapters) are additive
37
+ future PRs. Refuse with a clear message.
38
+
39
+ ## What this skill does
40
+
41
+ 1. Parses the consumer's input — chained format
42
+ (`<slug> — <Schema.orgType> — <purpose>`) OR free-text.
43
+ 2. Resolves the **primary schema.org type** for the page using
44
+ `references/page-types.md` (about → AboutPage, pricing → Service,
45
+ etc.). Confirms the choice before writing.
46
+ 3. Detects existing routes and refuses if `app/<slug>/page.tsx`
47
+ already exists, pointing at `add-schema` (#366).
48
+ 4. Detects content adapter — only MDX is supported at v1; refuses
49
+ on any other adapter with a clear message.
50
+ 5. Emits three files via `templates/route.tsx.tmpl` and
51
+ `templates/content.mdx.tmpl` (instantiated per page) plus a
52
+ typed builder import from `@working-theory/schema`.
53
+ 6. Shows the consumer a **single diff** of all three files and waits
54
+ for one confirmation. After approval, writes all files.
55
+ 7. Closing summary: pointer at `add-schema` (#366) for additional
56
+ schema, pointer at `audit-site` (#365) for citation-readiness check.
57
+
58
+ ## What this skill does NOT do
59
+
60
+ - Modify an existing route. Refuses + points at `add-schema` (#366).
61
+ - Run `pnpm dev` or rebuild content. The consumer does that.
62
+ - Detect content-adapter type beyond "is it MDX?". v1 ships MDX
63
+ only; other adapters are out of scope.
64
+ - Use `<script type="application/ld+json">` blocks or
65
+ `generateMetadata.other`. The canonical attachment is always
66
+ `<JsonLd>` from `@working-theory/jsonld`.
67
+ - Hand-code JSON-LD object literals. The typed builder from
68
+ `@working-theory/schema` is the source of truth (e.g. `buildOrganization(...)`,
69
+ `buildHomePage(...)`).
70
+
71
+ ## The mechanic
72
+
73
+ ### Step 1 — Parse the input
74
+
75
+ The consumer's request can arrive in either shape:
76
+
77
+ **Chained shape** (from `suggest-site-pages` output):
78
+
79
+ ```
80
+ home — Organization — anchor with hero, value prop, CTA
81
+ about — AboutPage — company story and team
82
+ pricing — Service — public price tiers and feature comparison
83
+ ```
84
+
85
+ Three em-dash-separated fields: `<slug>` `<Schema.orgType>` `<purpose>`.
86
+
87
+ **Free-text shape:**
88
+
89
+ ```
90
+ "scaffold me a /pricing page"
91
+ "add an about page"
92
+ "create a /contact route for sales"
93
+ ```
94
+
95
+ Both shapes resolve to the same internal triple: `(slug, type, purpose)`.
96
+
97
+ For free-text:
98
+
99
+ - Extract the slug from the URL-shaped fragment ("/pricing" → "pricing"; "an about page" → "about").
100
+ - Resolve the `type` from `references/page-types.md` (the slug is the lookup key).
101
+ - The `purpose` is whatever description the consumer gave — used as MDX `description` frontmatter.
102
+
103
+ If you can't resolve a slug → type from the references file, **ask the consumer** rather than guessing. Don't fabricate types.
104
+
105
+ ### Step 2 — Detect MDX adapter
106
+
107
+ Quick check: does the consumer's project have an MDX content
108
+ backend?
109
+
110
+ - Look for `content/` directory at the project root.
111
+ - Look for `apps/web/source.config.ts` or `next.config.ts` that
112
+ references `@working-theory/content-adapters` MDX adapter.
113
+
114
+ If neither exists, refuse:
115
+
116
+ > "scaffold-page only supports the MDX content backend at v1. Your
117
+ > project doesn't appear to have one — file an issue at the upstream
118
+ > repo if you'd like Sanity / Payload / additional adapter support."
119
+
120
+ Stop. No writes.
121
+
122
+ ### Step 3 — Detect existing route
123
+
124
+ Check for `apps/web/app/<slug>/page.tsx` (or `app/<slug>/page.tsx`
125
+ depending on the consumer's structure).
126
+
127
+ If it exists, refuse:
128
+
129
+ > "A route at `/<slug>` already exists. To **add schema** to an
130
+ > existing page, run `add-schema` (#366) instead. To **replace** the
131
+ > page entirely, delete the existing files first and re-run this
132
+ > skill."
133
+
134
+ Stop. No writes.
135
+
136
+ ### Step 4 — Instantiate the templates
137
+
138
+ Use `templates/route.tsx.tmpl` and `templates/content.mdx.tmpl` as
139
+ sources. Substitute:
140
+
141
+ | Placeholder | Source |
142
+ | ----------------- | -------------------------------------------------- |
143
+ | `{{SLUG}}` | from Step 1 (e.g., `pricing`) |
144
+ | `{{TYPE}}` | from Step 1 (e.g., `Service`) |
145
+ | `{{TYPE_KEBAB}}` | type lowercased + kebab (e.g., `service`) |
146
+ | `{{TYPE_CAMEL}}` | type camelCased for builder name (e.g., `service`) |
147
+ | `{{BUILDER}}` | builder function name (e.g., `buildService`) |
148
+ | `{{TITLE}}` | derived from slug, title-cased (e.g., "Pricing") |
149
+ | `{{DESCRIPTION}}` | the `purpose` field from input |
150
+
151
+ Builder name resolution: every type in `references/page-types.md`
152
+ maps to a `build<Type>` export from `@working-theory/schema`. Verify the
153
+ builder exists in the consumer's installed `@working-theory/schema` (check
154
+ `node_modules/@working-theory/schema/dist/index.d.ts` or its README) before
155
+ emitting the import. If the builder is missing, surface a clear
156
+ "`@working-theory/schema` doesn't export `build<Type>` yet — file an issue
157
+ upstream" message and stop.
158
+
159
+ ### Step 5 — Show the diff
160
+
161
+ Present all three files (route + MDX + import path) in one
162
+ combined diff message. Single confirmation question:
163
+
164
+ > "I'll create:
165
+ >
166
+ > - `app/<slug>/page.tsx` (App Router route, ~30 lines)
167
+ > - `content/<Type>/<slug>.mdx` (content stub with frontmatter)
168
+ >
169
+ > The route imports `<JsonLd>` from `@working-theory/jsonld` and `build<Type>` from
170
+ > `@working-theory/schema`. JSON-LD is rendered server-side from the MDX
171
+ > frontmatter via the typed builder.
172
+ >
173
+ > Confirm to write all three files, or tell me what to change."
174
+
175
+ Wait for the consumer's confirmation. Do not write per-step.
176
+
177
+ ### Step 6 — Write all three files
178
+
179
+ After confirmation, write the route file and MDX stub atomically.
180
+ The third "file" is the import line inside the route — already
181
+ included in the route template.
182
+
183
+ ### Step 7 — Closing summary
184
+
185
+ Print:
186
+
187
+ - The two paths written.
188
+ - Reminder: `pnpm dev` to see the page, `pnpm build` to confirm it
189
+ compiles.
190
+ - Pointer at `add-schema` (#366) for adding supplementary schema
191
+ (FAQPage, HowTo, Product, etc.) to this page later.
192
+ - Pointer at `audit-site` (#365) for citation-readiness check after
193
+ adding pages.
194
+
195
+ ## Cross-skill chaining
196
+
197
+ Output of `suggest-site-pages` (#361) is this skill's input contract.
198
+ The consumer can paste any row of #361's output verbatim and this
199
+ skill scaffolds it. Example end-to-end:
200
+
201
+ 1. Consumer asks `suggest-site-pages` for a SaaS page list.
202
+ 2. Output includes: `pricing — Service — public price tiers and feature comparison`
203
+ 3. Consumer says: "scaffold that pricing one"
204
+ 4. This skill resolves the row, emits route + MDX + JSON-LD, all in
205
+ one confirm-before-write pass.
206
+ 5. Consumer continues with the next row, or moves on.
207
+
208
+ ## What lives in `references/page-types.md`
209
+
210
+ The type-to-schema mapping is data, not logic. Read the references
211
+ file at runtime — don't try to remember the table.
212
+
213
+ The mapping covers the canonical AILK page types:
214
+
215
+ - Identity — `home → HomePage`, `about → AboutPage`
216
+ - Conversion — `pricing → Service`, `contact → ContactPage`
217
+ - Trust — `privacy → PrivacyPage`, `terms → TermsPage`
218
+ - Editorial — `blog → Blog`, `blog/<slug> → BlogPosting`
219
+ - Catalog — `products → ItemList`, `products/<slug> → Product`
220
+ - Q&A — `faq → FAQPage`, `how-to/<slug> → HowTo`
221
+
222
+ The full list is in `references/page-types.md`. New types added to
223
+ `@working-theory/schema` should be added to that file in a follow-up PR; the
224
+ skill renders unrecognized types as a "missing from page-types.md"
225
+ prompt to ask the consumer rather than guessing.
226
+
227
+ ## Coordination
228
+
229
+ - **`suggest-site-pages` (#361)** — output is this skill's chained
230
+ input. The two skills' references corpora (`categories.md` and
231
+ `page-types.md`) must agree on schema-type names.
232
+ - **`add-schema` (#366)** — modifies existing pages. The
233
+ `<JsonLd schema={build<Type>(...)} />` attachment pattern is
234
+ shared with this skill (canonical pattern landed in #389 /
235
+ `@working-theory/jsonld`).
236
+ - **`audit-site` (#365)** — citation-readiness check. Runs after
237
+ pages exist; not invoked from inside this skill.
238
+ - **`@working-theory/jsonld`** (#389) — the React component for JSON-LD
239
+ rendering. Single source of truth for the attachment pattern.
240
+ - **`@working-theory/schema`** — typed builders (`buildHomePage`,
241
+ `buildAboutPage`, etc.). The skill's emit imports from here.
242
+ - **`@working-theory/content-adapters`** (MDX) — the content backend. v1 is
243
+ MDX-only; other adapters are deferred.
@@ -0,0 +1,169 @@
1
+ # Page-Type → schema.org Mapping
2
+
3
+ The lookup table the `scaffold-page` skill reads at runtime to
4
+ resolve a slug or page-purpose hint to a primary schema.org `@type`
5
+ plus the matching `@working-theory/schema` builder name.
6
+
7
+ The skill resolves in this order:
8
+
9
+ 1. **Exact slug match** — `pricing` → `Service`.
10
+ 2. **Slug-prefix match** — `blog/<anything>` → `BlogPosting`.
11
+ 3. **Free-text hint match** — "company story" / "team" → `AboutPage`.
12
+ 4. **Ask** — if nothing matches, ask the consumer rather than
13
+ guessing.
14
+
15
+ This file's table must agree with the entries
16
+ `suggest-site-pages` (#361) emits in `categories.md`. When new types
17
+ land in `@working-theory/schema`, both files update in the same follow-up PR.
18
+
19
+ ## Identity / surface pages
20
+
21
+ | Slug | Primary `@type` | Builder | When to pick |
22
+ | ------- | --------------- | ---------------- | --------------------------------------------------------------------- |
23
+ | `home` | `HomePage` | `buildHomePage` | The site's root landing page. Anchors hero, value prop, primary CTAs. |
24
+ | `about` | `AboutPage` | `buildAboutPage` | Company story / team / founders. Trust + narrative. |
25
+
26
+ ## Conversion pages
27
+
28
+ | Slug | Primary `@type` | Builder | When to pick |
29
+ | --------- | --------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
30
+ | `pricing` | `Service` | `buildService` | Public price tiers and feature comparison. (Or `Product` if the consumer sells discrete physical/digital products with SKUs.) |
31
+ | `contact` | `ContactPage` | `buildContactPage` | Sales / support entry point. Form, address, hours. |
32
+ | `book` | `Reservation` | _consumer-defined_ | Service businesses with appointment booking (salon, contractor, restaurant table). Requires consumer to wire the reservation flow. |
33
+
34
+ ## Trust pages
35
+
36
+ | Slug | Primary `@type` | Builder | When to pick |
37
+ | --------- | --------------- | ------------------ | ----------------- |
38
+ | `privacy` | `PrivacyPage` | `buildPrivacyPage` | Privacy policy. |
39
+ | `terms` | `TermsPage` | `buildTermsPage` | Terms of service. |
40
+
41
+ ## Editorial / blog
42
+
43
+ | Slug | Primary `@type` | Builder | When to pick |
44
+ | ------------- | --------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------- |
45
+ | `blog` | `Blog` | _consumer-defined_ | Blog index page. Lists posts. |
46
+ | `blog/<slug>` | `BlogPosting` | _consumer-defined_ | Individual blog post. The skill's chained input handles the per-post case naturally — ask `scaffold-page` per post. |
47
+
48
+ > Builder availability for editorial types depends on `@working-theory/schema`
49
+ > exports at the consumer's installed version. If
50
+ > `buildBlogPosting` is missing, fall back to manually authoring
51
+ > the JSON-LD via `<JsonLd schema={{...}} />`.
52
+
53
+ ## Catalog / commerce
54
+
55
+ | Slug | Primary `@type` | Builder | When to pick |
56
+ | ----------------- | --------------- | ------------------ | ----------------------------------------------------- |
57
+ | `products` | `ItemList` | _consumer-defined_ | Product index. Lists products. |
58
+ | `products/<slug>` | `Product` | _consumer-defined_ | Individual product page. |
59
+ | `services` | `ServicesList` | _consumer-defined_ | Service index for service-business consumer profiles. |
60
+ | `services/<slug>` | `Service` | `buildService` | Individual service page. |
61
+
62
+ > For commerce wiring (Stripe products + lookup_keys), use
63
+ > `scaffold-commerce` (#363). This skill emits the page; commerce
64
+ > wires it.
65
+
66
+ ## Q&A / how-to
67
+
68
+ | Slug | Primary `@type` | Builder | When to pick |
69
+ | --------------- | --------------- | ------------------ | -------------------------------- |
70
+ | `faq` | `FAQPage` | _consumer-defined_ | Frequently-asked-questions page. |
71
+ | `how-to/<slug>` | `HowTo` | _consumer-defined_ | Step-by-step instructions page. |
72
+
73
+ ## Real estate / listings
74
+
75
+ | Slug | Primary `@type` | Builder | When to pick |
76
+ | ----------------- | ------------------- | ------------------ | ----------------------------- |
77
+ | `listings` | `ItemList` | _consumer-defined_ | Property index. |
78
+ | `listings/<slug>` | `RealEstateListing` | _consumer-defined_ | Individual listing. |
79
+ | `agent` | `RealEstateAgent` | _consumer-defined_ | Solo realtor / agent profile. |
80
+
81
+ ## Healthcare / medical
82
+
83
+ | Slug | Primary `@type` | Builder | When to pick |
84
+ | ----------------- | ------------------------------ | ------------------ | ------------------------------------------------- |
85
+ | `practice` | `MedicalBusiness` | _consumer-defined_ | Practice / clinic landing. |
86
+ | `provider` | `Physician` / `Dentist` / etc. | _consumer-defined_ | Solo provider profile. Type depends on specialty. |
87
+ | `services/<slug>` | `MedicalProcedure` | _consumer-defined_ | Procedure / treatment page. |
88
+
89
+ ## Course / education
90
+
91
+ | Slug | Primary `@type` | Builder | When to pick |
92
+ | ---------------- | ------------------ | ------------------ | --------------------- |
93
+ | `courses` | `ItemList` | _consumer-defined_ | Course catalog. |
94
+ | `courses/<slug>` | `Course` | _consumer-defined_ | Individual course. |
95
+ | `lesson/<slug>` | `LearningResource` | _consumer-defined_ | Free / sample lesson. |
96
+
97
+ ## Nonprofit / org
98
+
99
+ | Slug | Primary `@type` | Builder | When to pick |
100
+ | ----------------- | --------------- | ------------------ | -------------------------------- |
101
+ | `mission` | `AboutPage` | `buildAboutPage` | Mission statement / what we do. |
102
+ | `donate` | `DonateAction` | _consumer-defined_ | Donation page. |
103
+ | `programs/<slug>` | `Program` | _consumer-defined_ | Individual program / initiative. |
104
+
105
+ ## Identity entity (Organization vs Person)
106
+
107
+ The site's **identity entity** is emitted on `home` (or in a layout
108
+ component). Two flavors:
109
+
110
+ | Site profile | Identity `@type` | Builder |
111
+ | ------------------ | ---------------- | ------------------- |
112
+ | Business / company | `Organization` | `buildOrganization` |
113
+ | Solo individual | `Person` | `buildPerson` |
114
+
115
+ For categories that admit both (real estate, healthcare,
116
+ professional services, course/education), `suggest-site-pages`
117
+ (#361) disambiguates Person vs Organization based on the consumer's
118
+ free-text. This skill receives the resolved type as part of the
119
+ chained input or asks if free-text is ambiguous.
120
+
121
+ ## When a slug doesn't match anything above
122
+
123
+ Don't guess. Ask the consumer:
124
+
125
+ > "I don't have a default schema.org type mapped for `/<slug>`. Two
126
+ > options:
127
+ >
128
+ > - Tell me which schema.org `@type` to use (e.g., `WebPage`,
129
+ > `Article`, `Event`).
130
+ > - Skip JSON-LD on this page; I emit a vanilla route + MDX stub
131
+ > and you wire schema later via `add-schema` (#366).
132
+ >
133
+ > Which?"
134
+
135
+ ## Generic fallbacks
136
+
137
+ For pages that don't match a specific category, two safe fallbacks:
138
+
139
+ - `WebPage` — the most generic schema.org `@type`. Always valid, low
140
+ citation value.
141
+ - `Article` — for editorial / longform content that isn't a blog
142
+ post specifically.
143
+
144
+ The `WebPage` fallback is the implicit default if the consumer
145
+ explicitly says "no schema" — emit the route + MDX without an
146
+ emitted `<JsonLd>` block; consumer can add later via #366.
147
+
148
+ ## When `@working-theory/schema` doesn't yet export the builder
149
+
150
+ Some types in this table say `_consumer-defined_` for the builder
151
+ column. That means `@working-theory/schema` doesn't export a typed builder
152
+ for that type yet. The skill's behavior:
153
+
154
+ 1. Surface the gap to the consumer:
155
+
156
+ > "`@working-theory/schema` doesn't export `build<Type>` yet. I can:
157
+ >
158
+ > - Emit the route with an inline JSON-LD object literal (less
159
+ > type-safe but works).
160
+ > - Skip JSON-LD on this page; you wire it via `add-schema`
161
+ > (#366) once the builder ships upstream.
162
+ > - File an upstream issue requesting the builder.
163
+ >
164
+ > Which?"
165
+
166
+ 2. Wait for the consumer's choice. Don't fabricate a builder.
167
+
168
+ The fallback to inline literals is documented in `add-schema`
169
+ (#366) too — both skills handle this case the same way.
@@ -0,0 +1,28 @@
1
+ ---
2
+ type: {{TYPE}}
3
+ slug: {{SLUG}}
4
+ title: {{TITLE}}
5
+ description: {{DESCRIPTION}}
6
+ ---
7
+
8
+ # {{TITLE}}
9
+
10
+ {{DESCRIPTION}}
11
+
12
+ <!--
13
+ This is the MDX content stub emitted by `scaffold-page`.
14
+ The frontmatter is the source of truth for JSON-LD — the
15
+ `{{BUILDER}}(page)` call in `app/{{SLUG}}/page.tsx` reads it.
16
+
17
+ Edit this file freely:
18
+ - Add sections, prose, components imported from your project.
19
+ - Update `description` (it's used both as the meta description
20
+ and as input to the JSON-LD builder).
21
+ - Don't change `type` unless you also update the route's import
22
+ to match a different `@working-theory/schema` builder.
23
+
24
+ When you're happy with the page, run `audit-site` (#365) to see
25
+ how it scores on citation-readiness. Use `add-schema` (#366) to
26
+ add supplementary schema (FAQPage, HowTo, etc.) without
27
+ re-scaffolding.
28
+ -->
@@ -0,0 +1,28 @@
1
+ // Emitted by `scaffold-page` at `app/{{SLUG}}/page.tsx`. Substitutions:
2
+ // {{SLUG}} — page slug (e.g., "pricing")
3
+ // {{TYPE}} — schema.org @type (e.g., "Service")
4
+ // {{BUILDER}} — typed builder name (e.g., "buildService")
5
+ // {{TITLE}} — page title (e.g., "Pricing")
6
+ import { notFound } from "next/navigation";
7
+
8
+ import { JsonLd } from "@working-theory/jsonld";
9
+ import { {{BUILDER}} } from "@working-theory/schema";
10
+ import { mdxAdapter } from "@/lib/content";
11
+
12
+ export default async function {{TYPE}}Page() {
13
+ const page = await mdxAdapter.getPage("{{SLUG}}");
14
+ if (!page) return notFound();
15
+
16
+ const schema = {{BUILDER}}(page);
17
+
18
+ return (
19
+ <main className="mx-auto max-w-3xl px-6 py-12">
20
+ <JsonLd schema={schema} />
21
+ <article className="prose dark:prose-invert">
22
+ <h1>{page.title}</h1>
23
+ {page.description ? <p className="lead">{page.description}</p> : null}
24
+ {/* Render MDX body via your project's MDX renderer of choice. */}
25
+ </article>
26
+ </main>
27
+ );
28
+ }