create-ailk 0.7.0 → 0.9.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 (310) hide show
  1. package/README.md +112 -10
  2. package/component-catalog.json +798 -49
  3. package/component-catalog.md +9 -6
  4. package/dist/add-module.d.ts +20 -0
  5. package/dist/add-module.js +43 -7
  6. package/dist/add-route.d.ts +56 -0
  7. package/dist/add-route.js +286 -0
  8. package/dist/apply-design-md.d.ts +7 -0
  9. package/dist/apply-design-md.js +50 -0
  10. package/dist/apply-design.d.ts +64 -0
  11. package/dist/apply-design.js +273 -0
  12. package/dist/claude-md.d.ts +111 -0
  13. package/dist/claude-md.js +334 -0
  14. package/dist/cli.js +114 -28
  15. package/dist/derive-architecture.js +41 -36
  16. package/dist/design-compile.d.ts +71 -0
  17. package/dist/design-compile.js +98 -0
  18. package/dist/design-package.d.ts +83 -0
  19. package/dist/design-package.js +468 -0
  20. package/dist/design-presets.d.ts +86 -0
  21. package/dist/design-presets.js +642 -0
  22. package/dist/design-scaffold.d.ts +76 -0
  23. package/dist/design-scaffold.js +220 -0
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.js +4 -1
  26. package/dist/legacy-nav-renderers.d.ts +45 -0
  27. package/dist/legacy-nav-renderers.js +545 -0
  28. package/dist/lib/auth-secret-file.d.ts +19 -0
  29. package/dist/lib/auth-secret-file.js +112 -0
  30. package/dist/lib/design-checks.d.ts +78 -0
  31. package/dist/lib/design-checks.js +174 -0
  32. package/dist/lib/extract-module-bundle.js +5 -1
  33. package/dist/lib/license-key-files.d.ts +9 -0
  34. package/dist/lib/license-key-files.js +2 -2
  35. package/dist/lib/module-license-gate.d.ts +89 -0
  36. package/dist/lib/module-license-gate.js +171 -12
  37. package/dist/lib/module-tier.d.ts +45 -16
  38. package/dist/lib/module-tier.js +76 -0
  39. package/dist/lib/pro-callout.js +10 -2
  40. package/dist/lib/render-verdict.d.ts +52 -0
  41. package/dist/lib/render-verdict.js +77 -0
  42. package/dist/lib/scaffold-render-sweep.d.ts +105 -0
  43. package/dist/lib/scaffold-render-sweep.js +236 -0
  44. package/dist/module-architecture.d.ts +19 -16
  45. package/dist/module-architecture.js +64 -21
  46. package/dist/parse-args.d.ts +88 -10
  47. package/dist/parse-args.js +272 -21
  48. package/dist/programmatic.d.ts +66 -12
  49. package/dist/programmatic.js +361 -34
  50. package/dist/site-chrome.d.ts +19 -9
  51. package/dist/site-chrome.js +23 -13
  52. package/dist/site-manifest.d.ts +25 -0
  53. package/dist/site-manifest.js +254 -0
  54. package/dist/site-roster.d.ts +41 -0
  55. package/dist/site-roster.js +149 -11
  56. package/dist/starter-grid.d.ts +232 -0
  57. package/dist/starter-grid.js +545 -0
  58. package/dist/surfaces.d.ts +41 -9
  59. package/dist/surfaces.js +268 -92
  60. package/dist/template-manifest.d.ts +65 -29
  61. package/dist/template-manifest.js +161 -382
  62. package/dist/template-names.d.ts +14 -12
  63. package/dist/template-names.js +13 -17
  64. package/package.json +5 -4
  65. package/site-templates/_base/content/en/Feature/feature-1.mdx +69 -0
  66. package/site-templates/_base/content/en/Feature/feature-2.mdx +69 -0
  67. package/site-templates/_base/content/en/Feature/feature-3.mdx +69 -0
  68. package/site-templates/_base/content/en/FeaturesList/features.mdx +91 -0
  69. package/site-templates/_base/content/en/GlossaryList/glossary.mdx +0 -1
  70. package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +0 -1
  71. package/site-templates/_base/content/en/PortfolioItem/sample-four.mdx +105 -0
  72. package/site-templates/_base/content/en/PortfolioItem/sample-one.mdx +34 -0
  73. package/site-templates/_base/content/en/PortfolioItem/sample-three.mdx +94 -0
  74. package/site-templates/_base/content/en/PortfolioItem/sample-two.mdx +45 -0
  75. package/site-templates/_base/content/en/PortfolioList/portfolio.mdx +169 -0
  76. package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +15 -0
  77. package/site-templates/_base/content/en/UseCase/persona-1.mdx +70 -0
  78. package/site-templates/_base/content/en/UseCase/persona-2.mdx +70 -0
  79. package/site-templates/_base/content/en/UseCase/persona-3.mdx +70 -0
  80. package/site-templates/{minimalism-site/TEMPLATE-MANIFEST.json → aliases/minimalism-site.TEMPLATE-MANIFEST.json} +72 -40
  81. package/site-templates/designs/minimalism/DESIGN.md +98 -6
  82. package/site-templates/designs/minimalism/sample/README.md +48 -0
  83. package/site-templates/designs/standard/DESIGN.md +103 -6
  84. package/site-templates/marketing-site/DESIGN.md +103 -6
  85. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +144 -47
  86. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +82 -41
  87. package/site-templates/marketing-site-free/DESIGN.md +103 -6
  88. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +150 -48
  89. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +114 -67
  90. package/site-templates/marketing-site-free/ailk-template.json +1 -1
  91. package/site-templates/marketing-site-free/content/en/NewsletterSignup/newsletter.mdx +59 -0
  92. package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +199 -0
  93. package/site-templates/saas-product/DESIGN.md +103 -6
  94. package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
  95. package/site-templates/{simple-service → shapes/local-business-service}/TEMPLATE-MANIFEST.json +210 -81
  96. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +356 -0
  97. package/site-templates/shapes/local-business-service/ailk-template.json +10 -0
  98. package/site-templates/{simple-service → shapes/local-business-service}/content/en/AboutPage/about.mdx +4 -4
  99. package/site-templates/shapes/local-business-service/content/en/HomePage/home.mdx +70 -0
  100. package/site-templates/shapes/local-business-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  101. package/site-templates/shapes/local-business-service/content/en/PortfolioList/portfolio.mdx +171 -0
  102. package/site-templates/{minimalism-site → shapes/local-business-service}/content/en/PurchasePolicyPage/purchase-policy.mdx +7 -8
  103. package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +39 -0
  104. package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +39 -0
  105. package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +39 -0
  106. package/site-templates/shapes/local-business-service/content/en/ServicesList/services.mdx +61 -0
  107. package/site-templates/shapes/local-business-service/provenance.json +4 -0
  108. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +471 -0
  109. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +354 -0
  110. package/site-templates/shapes/organization-service/ailk-template.json +10 -0
  111. package/site-templates/shapes/organization-service/content/en/AboutPage/about.mdx +38 -0
  112. package/site-templates/shapes/organization-service/content/en/HomePage/home.mdx +85 -0
  113. package/site-templates/shapes/organization-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  114. package/site-templates/shapes/organization-service/content/en/PortfolioList/portfolio.mdx +171 -0
  115. package/site-templates/shapes/organization-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  116. package/site-templates/{minimalism-site → shapes/organization-service}/content/en/ServicesList/services.mdx +3 -4
  117. package/site-templates/shapes/organization-service/provenance.json +4 -0
  118. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +478 -0
  119. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +353 -0
  120. package/site-templates/shapes/person-service/ailk-template.json +10 -0
  121. package/site-templates/shapes/person-service/content/_site.mdx +85 -0
  122. package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +39 -0
  123. package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +97 -0
  124. package/site-templates/shapes/person-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  125. package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +171 -0
  126. package/site-templates/{simple-service → shapes/person-service}/content/en/PurchasePolicyPage/purchase-policy.mdx +10 -11
  127. package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +38 -0
  128. package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +38 -0
  129. package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +38 -0
  130. package/site-templates/{simple-service → shapes/person-service}/content/en/ServicesList/services.mdx +16 -16
  131. package/site-templates/shapes/person-service/provenance.json +4 -0
  132. package/templates/.claude/rules/architecture.md +7 -0
  133. package/templates/.claude/skills/README.md +5 -3
  134. package/templates/.claude/skills/add-auth/references/env-vars.md +22 -15
  135. package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +3 -2
  136. package/templates/.claude/skills/add-page/SKILL.md +241 -238
  137. package/templates/.claude/skills/add-page/references/page-types.md +85 -72
  138. package/templates/.claude/skills/add-page/scripts/site-pages.mjs +87 -0
  139. package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +99 -0
  140. package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +8 -18
  141. package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +43 -0
  142. package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +52 -0
  143. package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +38 -0
  144. package/templates/.claude/skills/check-site/SKILL.md +23 -0
  145. package/templates/.claude/skills/fill-page/SKILL.md +26 -7
  146. package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +1 -1
  147. package/templates/.claude/skills/setup-database/SKILL.md +156 -0
  148. package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +154 -0
  149. package/templates/.claude/skills/setup-deploy/SKILL.md +64 -32
  150. package/templates/.claude/skills/setup-deploy/references/env-vars-template.md +44 -36
  151. package/templates/.claude/skills/setup-deploy/references/runbook-template.md +58 -102
  152. package/templates/.claude/skills/update-page/SKILL.md +117 -0
  153. package/templates/.claude/skills/update-page/scripts/update-page.ts +640 -0
  154. package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +31 -0
  155. package/templates/.claude/skills/upgrade-plan/SKILL.md +12 -8
  156. package/templates/.github/workflows/ci.yml +4 -0
  157. package/templates/.prettierignore +1 -0
  158. package/templates/CLAUDE.md +146 -103
  159. package/templates/DESIGN.md +103 -6
  160. package/templates/README.md +63 -43
  161. package/templates/apps/api/.env.example +2 -1
  162. package/templates/apps/api/CLAUDE.md +3 -2
  163. package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +2 -0
  164. package/templates/apps/api/src/__tests__/server.test.ts +116 -0
  165. package/templates/apps/api/src/config/__tests__/index.test.ts +115 -14
  166. package/templates/apps/api/src/config/index.ts +35 -16
  167. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +30 -0
  168. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +96 -0
  169. package/templates/apps/api/src/lib/lead-capture-store.ts +12 -0
  170. package/templates/apps/api/src/lib/lead-delivery.ts +52 -0
  171. package/templates/apps/api/src/lib/stripe.ts +9 -0
  172. package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +140 -0
  173. package/templates/apps/api/src/middleware/auth.ts +54 -0
  174. package/templates/apps/api/src/openapi/spec.ts +63 -12
  175. package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +5 -2
  176. package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +628 -0
  177. package/templates/apps/api/src/routes/checkout/sessions.ts +222 -24
  178. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +88 -0
  179. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +100 -0
  180. package/templates/apps/api/src/routes/leads/index.ts +46 -1
  181. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +1 -1
  182. package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +5 -1
  183. package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +521 -20
  184. package/templates/apps/api/src/routes/webhooks/stripe.ts +124 -32
  185. package/templates/apps/api/src/server.ts +35 -0
  186. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +194 -0
  187. package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +124 -0
  188. package/templates/apps/api/src/services/__tests__/revalidation.test.ts +90 -15
  189. package/templates/apps/api/src/services/checkout-buyer.ts +72 -0
  190. package/templates/apps/api/src/services/lead-routing.ts +140 -30
  191. package/templates/apps/api/src/services/leads-inbox.ts +48 -11
  192. package/templates/apps/api/src/services/revalidation.ts +60 -15
  193. package/templates/apps/mcp/__tests__/parity.test.ts +5 -4
  194. package/templates/apps/mcp/__tests__/tools/create_project.test.ts +30 -24
  195. package/templates/apps/mcp/src/tools/create_project.ts +21 -6
  196. package/templates/apps/mcp/src/tools/purchase.ts +4 -2
  197. package/templates/apps/web/.env.example +13 -0
  198. package/templates/apps/web/CLAUDE.md +22 -28
  199. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +1 -1
  200. package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +24 -0
  201. package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +17 -6
  202. package/templates/apps/web/app/[locale]/[slug]/[detail]/__tests__/page.test.tsx +110 -0
  203. package/templates/apps/web/app/[locale]/[slug]/[detail]/page.tsx +60 -0
  204. package/templates/apps/web/app/[locale]/[slug]/page.tsx +1 -1
  205. package/templates/apps/web/app/[locale]/alternatives/__tests__/page.test.tsx +161 -0
  206. package/templates/apps/web/app/[locale]/alternatives/page.tsx +104 -0
  207. package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +14 -6
  208. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +10 -9
  209. package/templates/apps/web/app/[locale]/contact/__tests__/contact-form-text.test.ts +32 -0
  210. package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +129 -0
  211. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +227 -84
  212. package/templates/apps/web/app/[locale]/contact/contact-form-text.ts +50 -0
  213. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +73 -20
  214. package/templates/apps/web/app/[locale]/contact/page.tsx +105 -15
  215. package/templates/apps/web/app/[locale]/contact/site-contact-email.ts +54 -0
  216. package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +64 -0
  217. package/templates/apps/web/app/[locale]/features/page.tsx +52 -0
  218. package/templates/apps/web/app/[locale]/{use-cases → for}/[slug]/page.tsx +21 -5
  219. package/templates/apps/web/app/[locale]/for/__tests__/page-renderer-migration.test.tsx +73 -0
  220. package/templates/apps/web/app/[locale]/{use-cases → for}/page.tsx +8 -7
  221. package/templates/apps/web/app/[locale]/glossary/page.tsx +1 -1
  222. package/templates/apps/web/app/[locale]/layout.tsx +65 -17
  223. package/templates/apps/web/app/[locale]/newsletter/__tests__/newsletter.actions.test.ts +75 -0
  224. package/templates/apps/web/app/[locale]/newsletter/__tests__/page.test.tsx +163 -0
  225. package/templates/apps/web/app/[locale]/newsletter/newsletter.actions.ts +66 -0
  226. package/templates/apps/web/app/[locale]/newsletter/page.tsx +106 -14
  227. package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +59 -0
  228. package/templates/apps/web/app/[locale]/{book-a-call → portfolio}/page.tsx +12 -13
  229. package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +112 -0
  230. package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +70 -0
  231. package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +236 -44
  232. package/templates/apps/web/app/api/revalidate/route.ts +78 -36
  233. package/templates/apps/web/lib/__tests__/site-brand.test.ts +79 -0
  234. package/templates/apps/web/lib/__tests__/site-theme.test.ts +104 -11
  235. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +21 -4
  236. package/templates/apps/web/lib/locale-guard.ts +18 -0
  237. package/templates/apps/web/lib/meet-placeholder.ts +5 -0
  238. package/templates/apps/web/lib/nav-config.ts +50 -37
  239. package/templates/apps/web/lib/site-brand.tsx +13 -9
  240. package/templates/apps/web/lib/site-identity.ts +14 -0
  241. package/templates/apps/web/lib/site-logo.tsx +36 -0
  242. package/templates/apps/web/lib/site-theme.ts +46 -26
  243. package/templates/apps/web/messages/en.json +45 -5
  244. package/templates/apps/web/middleware.ts +28 -4
  245. package/templates/content/_site.mdx +4 -2
  246. package/templates/content/en/BlogList/blog.mdx +37 -16
  247. package/templates/content/en/BookCall/book-a-call.mdx +80 -0
  248. package/templates/content/en/BookCall/onsite-estimate.mdx +56 -0
  249. package/templates/content/en/BookCall/onsite-service.mdx +56 -0
  250. package/templates/content/en/BookCall/start-project.mdx +56 -0
  251. package/templates/content/en/ContactPage/contact.mdx +43 -34
  252. package/templates/content/en/HomePage/home.mdx +10 -22
  253. package/templates/content/en/LandingPage/meet.mdx +59 -0
  254. package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +0 -1
  255. package/templates/content/en/UseCasesList/{use-cases.mdx → for.mdx} +19 -18
  256. package/templates/database/CHANGELOG.md +14 -0
  257. package/templates/database/package.json +1 -1
  258. package/templates/package.json +2 -1
  259. package/templates/tools/check-claude-md.ts +128 -0
  260. package/versions.json +33 -33
  261. package/site-templates/_base/content/en/BookCall/book-call.mdx +0 -53
  262. package/site-templates/_base/content/en/UseCase/first-use-case.mdx +0 -23
  263. package/site-templates/_base/content/en/UseCase/second-use-case.mdx +0 -23
  264. package/site-templates/_base/content/en/UseCase/third-use-case.mdx +0 -23
  265. package/site-templates/minimalism-site/DESIGN.md +0 -162
  266. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +0 -470
  267. package/site-templates/minimalism-site/ailk-template.json +0 -23
  268. package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +0 -110
  269. package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +0 -53
  270. package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +0 -34
  271. package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +0 -57
  272. package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +0 -77
  273. package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +0 -73
  274. package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +0 -52
  275. package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +0 -52
  276. package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +0 -52
  277. package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +0 -52
  278. package/site-templates/minimalism-site/flows/referral.flow.json +0 -71
  279. package/site-templates/minimalism-site/provenance.json +0 -4
  280. package/site-templates/simple-service/DESIGN.md +0 -162
  281. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +0 -333
  282. package/site-templates/simple-service/ailk-template.json +0 -11
  283. package/site-templates/simple-service/content/en/BookCall/book-call.mdx +0 -53
  284. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +0 -32
  285. package/site-templates/simple-service/content/en/FAQPage/faq.mdx +0 -56
  286. package/site-templates/simple-service/content/en/HomePage/home.mdx +0 -85
  287. package/site-templates/simple-service/content/en/Service/landscape-design.mdx +0 -40
  288. package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +0 -40
  289. package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +0 -40
  290. package/site-templates/simple-service/provenance.json +0 -4
  291. package/templates/.claude/skills/add-page/templates/route.tsx.tmpl +0 -28
  292. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +0 -211
  293. package/templates/apps/web/app/[locale]/contact/__tests__/ContactForm.test.tsx +0 -96
  294. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +0 -72
  295. package/templates/content/en/SoftwareProduct/product.mdx +0 -175
  296. /package/site-templates/{minimalism-site → designs/minimalism/sample}/content/en/HomePage/home.mdx +0 -0
  297. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-1.svg +0 -0
  298. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-2.svg +0 -0
  299. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-3.svg +0 -0
  300. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-4.svg +0 -0
  301. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-5.svg +0 -0
  302. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-6.svg +0 -0
  303. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/hero-backdrop.svg +0 -0
  304. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-1.svg +0 -0
  305. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-2.svg +0 -0
  306. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-3.svg +0 -0
  307. /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/wordmark-placeholder.svg +0 -0
  308. /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/first-engagement.mdx +0 -0
  309. /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/second-engagement.mdx +0 -0
  310. /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/third-engagement.mdx +0 -0
@@ -7,6 +7,9 @@
7
7
  * On any parse / validation failure: throws ParseError. The orchestrator's
8
8
  * top-level catch turns this into a stderr write + non-zero exit.
9
9
  */
10
+ import { existsSync, statSync } from "node:fs";
11
+ import { join, resolve } from "node:path";
12
+ import { createInterface } from "node:readline/promises";
10
13
  import { parseArgs } from "node:util";
11
14
  import { assertLicenseKeyShape } from "./lib/license-key-files.js";
12
15
  import { RECOGNIZED_SURFACES, parseSurfaces } from "./surfaces.js";
@@ -29,8 +32,33 @@ export const RECOGNIZED_MODULES = [
29
32
  "signal-collectors",
30
33
  "commerce",
31
34
  ];
32
- /** The default module selection when `--modules` is absent (reproduces today's scaffold). */
33
- const DEFAULT_MODULES = ["marketing"];
35
+ /**
36
+ * Shapes a starter can be built from today (`--shape`, #6754 D1).
37
+ *
38
+ * Declared HERE rather than imported from `template-manifest.ts` for the
39
+ * reason `RECOGNIZED_MODULES` is: importing the registry closes the runtime
40
+ * cycle `template-names.ts`'s header records. `parse-args.test.ts` pins this
41
+ * list, `RESERVED_SHAPES` and `RECOGNIZED_DESIGNS` to their authorities
42
+ * (`STARTER_SHAPES`, `STARTER_DESIGNS`, `SHAPE_ROSTERS`).
43
+ */
44
+ export const RECOGNIZED_SHAPES = [
45
+ "organization-product",
46
+ "organization-service",
47
+ "local-business-service",
48
+ "person-service",
49
+ ];
50
+ /** Shapes the contract names but no release builds yet. */
51
+ export const RESERVED_SHAPES = ["local-business-product"];
52
+ /** The `--design` vocabulary (#6754 D1) — `STARTER_DESIGNS`, pinned by test. */
53
+ export const RECOGNIZED_DESIGNS = ["standard", "minimalism"];
54
+ /** What each shape is, for the prompt (D3). A shape without one is a type error. */
55
+ const SHAPE_DESCRIPTIONS = {
56
+ "organization-product": "a company selling a product",
57
+ "organization-service": "a company selling a service",
58
+ "local-business-service": "a local business selling a service",
59
+ "person-service": "a person selling their own service",
60
+ };
61
+ const SHAPE_LIST = RECOGNIZED_SHAPES.join(", ");
34
62
  export class ParseError extends Error {
35
63
  constructor(message) {
36
64
  super(message);
@@ -51,11 +79,32 @@ Arguments:
51
79
  Options:
52
80
  --modules <csv> Comma-separated list of modules to compose the site
53
81
  from (recognized: ${RECOGNIZED_MODULES.join(", ")}).
54
- Defaults to \`marketing\`, which reproduces today's
55
- scaffold. A module is a composable unit across the
56
- three tiers (data · API · presentation).
82
+ Trims or ADDS relative to the level your licence
83
+ key unlocks (#6759) — it never replaces it. With no
84
+ key, the level is Free (\`marketing\`). A Pro key
85
+ switches on docs-blog, scheduling and
86
+ signal-collectors too; Pro Plus adds multi-tenant.
87
+ Naming modules here keeps EXACTLY those, trimming
88
+ the level's default. Naming only \`commerce\` (a
89
+ per-site add-on) or \`workspace\` (included at Pro,
90
+ opt-in) ADDS it on top of the level's default
91
+ without trimming. A module your licence does not
92
+ include is refused, naming the level that does. A
93
+ module is a composable unit across the three tiers
94
+ (data · API · presentation).
95
+ --shape <shape> The kind of site to build (recognized:
96
+ ${SHAPE_LIST}).
97
+ Installs that shape's Free starter. A run naming
98
+ neither --shape nor --template asks for a shape on
99
+ a terminal, and refuses without one.
100
+ --design <design> The look to render the starter in: a design name
101
+ (recognized: ${RECOGNIZED_DESIGNS.join(", ")}) or a
102
+ directory holding a DESIGN.md. Defaults to the
103
+ starter's own.
57
104
  --template <name> The site template to install (recognized:
58
105
  ${RECOGNIZED_TEMPLATES.join(", ")}).
106
+ A template already fixes its shape and design, so
107
+ it cannot be combined with --shape or --design.
59
108
  A template is a page roster plus seed content and
60
109
  config — never code. Its required modules are ADDED
61
110
  to whatever \`--modules\` names, so the two compose.
@@ -74,8 +123,9 @@ Options:
74
123
  Surfaces the declared architecture does not carry are
75
124
  NOT scaffolded — their routes are absent, so a fresh
76
125
  site never serves a stock page with placeholder
77
- content. Add one later with the \`add-page\`
78
- skill, or re-run with the surface named here.
126
+ content. Add one later with
127
+ \`create-ailk add-route <surface>\`, or re-run with
128
+ the surface named here.
79
129
  --sync-architecture <csv> Regenerate architecture.yaml in place in an
80
130
  already-scaffolded repo from the given module set
81
131
  (recognized: ${RECOGNIZED_MODULES.join(", ")}), then
@@ -94,6 +144,12 @@ Options:
94
144
  file, at the target dir (positional arg, else cwd).
95
145
  Bypasses the scaffold path — copies no template, runs
96
146
  no install. Re-run after upgrading create-ailk.
147
+ --sync-claude-md Rewrite the AI Launch Kit sections of CLAUDE.md in
148
+ an already-scaffolded repo to the template this
149
+ create-ailk ships, then exit. Only CLAUDE.md
150
+ changes; your Site notes and anything between the
151
+ sections are kept byte for byte. Target dir is the
152
+ positional arg, else cwd.
97
153
  --license <key> Your licence key: fetch paid modules with it and
98
154
  write it into the scaffold (apps/api/.env and a
99
155
  gitignored ailk.key, both owner-only).
@@ -103,8 +159,8 @@ Options:
103
159
  --version Print the scaffolder version.
104
160
 
105
161
  Examples:
106
- pnpm create ailk@latest my-site
107
- pnpm create ailk@latest /tmp/test-site --install
162
+ pnpm create ailk@latest my-site --shape organization-product
163
+ pnpm create ailk@latest /tmp/test-site --template marketing-site-free --install
108
164
 
109
165
  Next steps after a successful scaffold:
110
166
  cd <target-dir>
@@ -113,7 +169,12 @@ Next steps after a successful scaffold:
113
169
 
114
170
  Reference: ADR 0007 — \`pnpm create ailk@latest\` is the canonical install path.
115
171
  `;
116
- export function parseCliArgs(argv) {
172
+ /**
173
+ * Parse `create-ailk` argv. `env.interactive` defaults to false —
174
+ * fail-closed: a caller that does not assert a human is present gets refusal
175
+ * R1, never a prompt it cannot answer (#6754 D2).
176
+ */
177
+ export function parseCliArgs(argv, env = { interactive: false }) {
117
178
  let parsed;
118
179
  try {
119
180
  parsed = parseArgs({
@@ -123,10 +184,13 @@ export function parseCliArgs(argv) {
123
184
  options: {
124
185
  modules: { type: "string" },
125
186
  template: { type: "string" },
187
+ shape: { type: "string" },
188
+ design: { type: "string" },
126
189
  license: { type: "string" },
127
190
  surfaces: { type: "string" },
128
191
  "sync-architecture": { type: "string" },
129
192
  "sync-catalog": { type: "boolean", default: false },
193
+ "sync-claude-md": { type: "boolean", default: false },
130
194
  "with-catalog": { type: "boolean", default: false },
131
195
  install: { type: "boolean", default: false },
132
196
  help: { type: "boolean", default: false, short: "h" },
@@ -140,17 +204,28 @@ export function parseCliArgs(argv) {
140
204
  const help = parsed.values.help === true;
141
205
  const version = parsed.values.version === true;
142
206
  const install = parsed.values.install === true;
143
- const modules = parseModules(parsed.values.modules);
207
+ // #6759 D3 — an absent flag stays `undefined` (the key's level decides);
208
+ // only a PRESENT value goes through `parseModules`.
209
+ const rawModules = parsed.values.modules;
210
+ const modules = rawModules === undefined ? undefined : parseModules(rawModules);
144
211
  const template = parseTemplate(parsed.values.template);
212
+ const shape = parseShape(parsed.values.shape);
213
+ const design = parseDesign(parsed.values.design);
145
214
  const surfaces = parseSurfaceList(parsed.values.surfaces);
146
215
  const syncArchitecture = parsed.values["sync-architecture"];
147
216
  const syncCatalog = parsed.values["sync-catalog"] === true;
217
+ const syncClaudeMd = parsed.values["sync-claude-md"] === true;
148
218
  const withCatalog = parsed.values["with-catalog"] === true;
149
219
  const license = parseLicense(parsed.values.license);
150
- // The two sync modes each exit after rewriting their one file, so asking for
151
- // both in one invocation has no coherent meaning.
152
- if (syncCatalog && syncArchitecture !== undefined) {
153
- throw new ParseError("--sync-catalog and --sync-architecture cannot be combined; run them one at a time");
220
+ // The sync modes each exit after rewriting their one file, so asking for
221
+ // more than one in one invocation has no coherent meaning.
222
+ const syncFlags = [
223
+ syncCatalog ? "--sync-catalog" : undefined,
224
+ syncArchitecture !== undefined ? "--sync-architecture" : undefined,
225
+ syncClaudeMd ? "--sync-claude-md" : undefined,
226
+ ].filter((f) => f !== undefined);
227
+ if (syncFlags.length > 1) {
228
+ throw new ParseError(`${syncFlags.join(" and ")} cannot be combined; run them one at a time`);
154
229
  }
155
230
  // Validate the sync-architecture value now, through the SAME parseModules
156
231
  // path `--modules` uses, so an unknown module throws ParseError at parse time
@@ -163,30 +238,34 @@ export function parseCliArgs(argv) {
163
238
  return {
164
239
  target: undefined,
165
240
  template: undefined,
241
+ needsShapePrompt: false,
166
242
  install,
167
243
  help,
168
244
  version,
169
245
  modules,
170
246
  surfaces,
171
247
  syncCatalog: false,
248
+ syncClaudeMd: false,
172
249
  withCatalog: false,
173
250
  syncArchitecture: undefined,
174
251
  };
175
252
  }
176
253
  // Sync modes: the target dir is optional (positional if given, else cwd).
177
- if (syncArchitecture !== undefined || syncCatalog) {
254
+ if (syncArchitecture !== undefined || syncCatalog || syncClaudeMd) {
178
255
  if (parsed.positionals.length > 1) {
179
256
  throw new ParseError(`expected at most one target directory, got ${parsed.positionals.length}`);
180
257
  }
181
258
  return {
182
259
  target: parsed.positionals[0],
183
260
  template,
261
+ needsShapePrompt: false,
184
262
  install,
185
263
  help,
186
264
  version,
187
265
  modules,
188
266
  surfaces,
189
267
  syncCatalog,
268
+ syncClaudeMd,
190
269
  withCatalog,
191
270
  syncArchitecture,
192
271
  };
@@ -197,20 +276,192 @@ export function parseCliArgs(argv) {
197
276
  if (parsed.positionals.length > 1) {
198
277
  throw new ParseError(`expected exactly one target directory, got ${parsed.positionals.length}`);
199
278
  }
279
+ // R3 — a template already fixes its shape and design.
280
+ if (template !== undefined && (shape !== undefined || design !== undefined)) {
281
+ const flags = shape !== undefined && design !== undefined
282
+ ? "--shape and --design"
283
+ : shape !== undefined
284
+ ? "--shape"
285
+ : "--design";
286
+ throw new ParseError(`--template cannot be combined with ${flags}: a template already fixes its shape and design. Pass --template alone, or --shape with an optional --design.`);
287
+ }
288
+ // R1 — no silent default: with neither a template nor a shape, ask on a
289
+ // terminal and refuse without one.
290
+ const needsShapePrompt = template === undefined && shape === undefined;
291
+ if (needsShapePrompt && !env.interactive) {
292
+ throw new ParseError(`no shape given, and there is no terminal to ask on. Pass --shape <shape> (one of: ${SHAPE_LIST}), or --template <name>.`);
293
+ }
200
294
  return {
201
295
  target: parsed.positionals[0],
202
296
  template,
297
+ ...(shape !== undefined ? { shape } : {}),
298
+ ...(design !== undefined ? { design } : {}),
299
+ needsShapePrompt,
203
300
  install,
204
301
  help,
205
302
  version,
206
303
  modules,
207
304
  surfaces,
208
305
  syncCatalog,
306
+ syncClaudeMd,
209
307
  withCatalog,
210
308
  syncArchitecture: undefined,
211
309
  ...(license !== undefined ? { license } : {}),
212
310
  };
213
311
  }
312
+ /**
313
+ * Validate `--shape` (#6754 D2 step 2): trimmed and lowercased. A reserved
314
+ * shape is refusal R2; any other unrecognized value names the recognized set.
315
+ */
316
+ function parseShape(raw) {
317
+ if (raw === undefined)
318
+ return undefined;
319
+ const name = raw.trim().toLowerCase();
320
+ if (RESERVED_SHAPES.includes(name)) {
321
+ throw new ParseError(`shape "${name}" is not available yet. Choose one of: ${SHAPE_LIST}.`);
322
+ }
323
+ if (!RECOGNIZED_SHAPES.includes(name)) {
324
+ throw new ParseError(`unknown shape "${raw}". Recognized: ${SHAPE_LIST}`);
325
+ }
326
+ return name;
327
+ }
328
+ /** `path` is an existing directory. */
329
+ function isExistingDir(path) {
330
+ try {
331
+ return statSync(path).isDirectory();
332
+ }
333
+ catch {
334
+ return false;
335
+ }
336
+ }
337
+ /**
338
+ * `dir` (resolved from `raw`) as a design path: an existing directory
339
+ * holding a `DESIGN.md`, else `ParseError` naming `raw` (#6813 D1 rule 2).
340
+ */
341
+ function validateDesignDir(dir, raw) {
342
+ if (!isExistingDir(dir)) {
343
+ throw new ParseError(`design directory "${raw}" does not exist`);
344
+ }
345
+ if (!existsSync(join(dir, "DESIGN.md"))) {
346
+ throw new ParseError(`design directory "${raw}" holds no DESIGN.md`);
347
+ }
348
+ return dir;
349
+ }
350
+ /**
351
+ * Validate `--design` (#6754 D2 step 2, widened #6813 D1): a recognized
352
+ * name, or a directory holding a `DESIGN.md`. A value with no `/` or `\` is
353
+ * classified as a name first (trimmed and lowercased, filesystem never
354
+ * consulted) — falling back to a path only when it names an existing
355
+ * directory in `process.cwd()`, so `--design mydesign` and `--design
356
+ * ./mydesign` can differ. A value with a separator is always a path,
357
+ * resolved against `process.cwd()`, case preserved. The package's CONTENT is
358
+ * validated later, in `scaffold()` (`resolveDesign`) — this parser checks
359
+ * presence only.
360
+ */
361
+ function parseDesign(raw) {
362
+ if (raw === undefined)
363
+ return undefined;
364
+ const trimmed = raw.trim();
365
+ const hasSeparator = trimmed.includes("/") || trimmed.includes("\\");
366
+ if (!hasSeparator) {
367
+ const name = trimmed.toLowerCase();
368
+ if (RECOGNIZED_DESIGNS.includes(name)) {
369
+ return name;
370
+ }
371
+ const dir = resolve(process.cwd(), trimmed);
372
+ if (isExistingDir(dir)) {
373
+ return validateDesignDir(dir, raw);
374
+ }
375
+ throw new ParseError(`unknown design "${raw}". Recognized: ${RECOGNIZED_DESIGNS.join(", ")}`);
376
+ }
377
+ return validateDesignDir(resolve(process.cwd(), trimmed), raw);
378
+ }
379
+ /** How many answers the prompt takes before it gives up. */
380
+ const PROMPT_ATTEMPTS = 3;
381
+ /**
382
+ * Ask once for a shape (#6754 D3): a number 1–4 or a shape name. A bad answer
383
+ * re-asks, naming what was wrong; the third bad answer, or a closed input,
384
+ * throws. There is no default — an empty line is a bad answer.
385
+ */
386
+ export async function promptForShape(io) {
387
+ const width = Math.max(...RECOGNIZED_SHAPES.map((s) => s.length));
388
+ io.output.write([
389
+ "Which kind of site is this?",
390
+ ...RECOGNIZED_SHAPES.map((s, i) => ` ${i + 1}) ${s.padEnd(width)} ${SHAPE_DESCRIPTIONS[s]}`),
391
+ "",
392
+ ].join("\n"));
393
+ const noShape = new ParseError(`no shape chosen. Re-run with --shape <shape> (one of: ${SHAPE_LIST}).`);
394
+ const rl = createInterface({ input: io.input, terminal: false });
395
+ // The async iterator buffers every line, so an answer typed (or piped)
396
+ // ahead of its question is never dropped, and a closed input ends it.
397
+ const lines = rl[Symbol.asyncIterator]();
398
+ try {
399
+ for (let attempt = 0; attempt < PROMPT_ATTEMPTS; attempt++) {
400
+ io.output.write(`Shape [1-${RECOGNIZED_SHAPES.length} or name]: `);
401
+ const next = await lines.next();
402
+ if (next.done === true)
403
+ throw noShape;
404
+ const answer = next.value;
405
+ const picked = pickShape(answer);
406
+ if (picked !== undefined)
407
+ return picked;
408
+ const shown = answer.trim();
409
+ io.output.write(shown === ""
410
+ ? "No answer given.\n"
411
+ : `"${shown}" is not a shape. Answer 1-${RECOGNIZED_SHAPES.length} or a shape name.\n`);
412
+ }
413
+ throw noShape;
414
+ }
415
+ finally {
416
+ rl.close();
417
+ }
418
+ }
419
+ /** A prompt answer as a shape, or undefined when it names none. */
420
+ function pickShape(answer) {
421
+ const value = answer.trim().toLowerCase();
422
+ if (/^[0-9]+$/.test(value))
423
+ return RECOGNIZED_SHAPES[Number(value) - 1];
424
+ return RECOGNIZED_SHAPES.includes(value)
425
+ ? value
426
+ : undefined;
427
+ }
428
+ /**
429
+ * Fill `opts.shape` by prompting when, and only when, `needsShapePrompt` is
430
+ * set (#6754 D3). Help, version, sync and every run naming a shape or a
431
+ * template come back unchanged, with nothing written to `io.output`.
432
+ */
433
+ export async function resolveCliShape(opts, io) {
434
+ if (!opts.needsShapePrompt)
435
+ return opts;
436
+ const shape = await promptForShape(io);
437
+ return { ...opts, shape, needsShapePrompt: false };
438
+ }
439
+ /**
440
+ * The one mapping from parsed flags to `scaffold()` options (#6754 D4).
441
+ * `template`, `shape`, `design` and `license` are each spread only when set,
442
+ * so a `--template` run hands `scaffold()` the object it did before #6754.
443
+ *
444
+ * @throws ParseError when the shape prompt is unresolved or the target is
445
+ * unset — an unresolved prompt must never fall through to the bare overlay.
446
+ */
447
+ export function toScaffoldOptions(opts) {
448
+ if (opts.needsShapePrompt) {
449
+ throw new ParseError(`no shape given. Pass --shape <shape> (one of: ${SHAPE_LIST}), or --template <name>.`);
450
+ }
451
+ if (opts.target === undefined) {
452
+ throw new ParseError("missing target directory. Usage: pnpm create ailk@latest <target-dir>");
453
+ }
454
+ return {
455
+ targetDir: opts.target,
456
+ surfaces: opts.surfaces,
457
+ withCatalog: opts.withCatalog,
458
+ ...(opts.modules !== undefined ? { modules: opts.modules } : {}),
459
+ ...(opts.template !== undefined ? { template: opts.template } : {}),
460
+ ...(opts.shape !== undefined ? { shape: opts.shape } : {}),
461
+ ...(opts.design !== undefined ? { design: opts.design } : {}),
462
+ ...(opts.license !== undefined ? { license: opts.license } : {}),
463
+ };
464
+ }
214
465
  /**
215
466
  * Shape-check the `--license` value through the one validator `license set`
216
467
  * also uses, re-thrown as a ParseError. The message never repeats the value.
@@ -270,20 +521,20 @@ function parseSurfaceList(raw) {
270
521
  * validated, normalized string[].
271
522
  *
272
523
  * Splits on `,`, trims and lowercases each entry, drops empties, and validates
273
- * each against RECOGNIZED_MODULES. An absent flag (or an all-empty value)
274
- * defaults to DEFAULT_MODULES (`['marketing']`) — reproducing today's scaffold.
524
+ * each against RECOGNIZED_MODULES. Takes a PRESENT value only — an ABSENT
525
+ * `--modules` flag is `undefined` (#6759 D3: the key's level decides) and
526
+ * never reaches this function; an all-empty value (`--modules ""`,
527
+ * `--modules ,`) still names the Free set, spelled inline here.
275
528
  *
276
529
  * @throws ParseError on an unrecognized module value, naming the recognized set.
277
530
  */
278
531
  export function parseModules(raw) {
279
- if (raw === undefined)
280
- return [...DEFAULT_MODULES];
281
532
  const requested = raw
282
533
  .split(",")
283
534
  .map((m) => m.trim().toLowerCase())
284
535
  .filter(Boolean);
285
536
  if (requested.length === 0)
286
- return [...DEFAULT_MODULES];
537
+ return ["marketing"];
287
538
  for (const m of requested) {
288
539
  if (!RECOGNIZED_MODULES.includes(m)) {
289
540
  throw new ParseError(`unknown module "${m}". Recognized: ${RECOGNIZED_MODULES.join(", ")}`);
@@ -16,11 +16,12 @@
16
16
  * const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
17
17
  */
18
18
  import { type AddModuleResult } from "./add-module.js";
19
+ import { type SyncClaudeMdResult } from "./claude-md.js";
19
20
  import { CATALOG_TARGET_PATH } from "./component-catalog.js";
20
21
  import { type ModuleName } from "./parse-args.js";
21
22
  import { type TemplateLayout } from "./site-chrome.js";
22
23
  import { type SyncRoutesResult } from "./sync-routes.js";
23
- import { type StarterDesign } from "./template-manifest.js";
24
+ import { type StarterShape } from "./template-manifest.js";
24
25
  export interface ScaffoldOptions {
25
26
  /** Absolute or relative path to the target directory. Must not exist or be empty. */
26
27
  targetDir: string;
@@ -36,9 +37,10 @@ export interface ScaffoldOptions {
36
37
  *
37
38
  * Consumed ONLY by the async `scaffold()` below. `scaffoldSync` stays
38
39
  * template-oblivious for exactly the reason it stays licensing-oblivious
39
- * (spec 5481 § 3 DD3): a call naming no template takes a code path with no
40
- * new statement in it, which is a stronger byte-identity guarantee than a
41
- * test asserting the output happens to match.
40
+ * (spec 5481 § 3 DD3): a call naming neither a template nor a `shape`
41
+ * takes a code path with no new statement in it — the bare overlay, the
42
+ * library's default. The CLI never takes that path (#6754 D2: it refuses a
43
+ * run naming neither, or asks for a shape on a terminal).
42
44
  *
43
45
  * What a template DOES change is `modules` — `scaffold()` unions the
44
46
  * template's `requires` with whatever `--modules` named and passes THAT
@@ -46,6 +48,13 @@ export interface ScaffoldOptions {
46
48
  * `architecture.yaml` and the generated nav are all functions of the union.
47
49
  */
48
50
  template?: string;
51
+ /**
52
+ * The starter shape to install (`--shape`, #6754 D5): `scaffold()` resolves
53
+ * it to the one template of that shape whose delivery is `free`, then runs
54
+ * exactly as a `template` naming it would. Mutually exclusive with
55
+ * `template`. A shape with no Free starter yet is refused (D6).
56
+ */
57
+ shape?: StarterShape;
49
58
  /**
50
59
  * Selected modules (recognized: marketing, docs-blog, multi-tenant,
51
60
  * scheduling). Defaults to
@@ -110,14 +119,23 @@ export interface ScaffoldOptions {
110
119
  */
111
120
  layout?: TemplateLayout;
112
121
  /**
113
- * The design whose layout knobs fill what `layout` leaves unset (#6638,
114
- * `DESIGN_LAYOUTS`). `scaffold()` sets it from the resolved template's
115
- * `design`; a caller may name one to OVERRIDE the template's — the CI-only
122
+ * A design name or a directory holding a DESIGN.md (#6638; widened to a
123
+ * path #6813 D1/D3). `scaffold()` sets it from the resolved template's
124
+ * `design`; a caller may name one to OVERRIDE the template's — the
116
125
  * shape × design pairing `verify-scaffold.mjs --design` renders (#6638
117
- * DD-4). No CLI flag sets it. Unset (every existing `scaffoldSync` caller)
118
- * resolves exactly as before.
126
+ * DD-4), and the CLI's `--design` beside `--shape` (#6754). Unset (every
127
+ * existing `scaffoldSync` caller) resolves exactly as before. Gated
128
+ * (#6760): a non-Free design needs a Pro or Pro Plus level.
129
+ */
130
+ design?: string;
131
+ /**
132
+ * INTERNAL — the resolved design's own layout knobs (#6813 D2/D4/D8),
133
+ * populated by `scaffold()` from `resolveDesign(...).pkg.layout` before
134
+ * calling `scaffoldSync`. Never set by a CLI/MCP caller. Replaces the
135
+ * design-NAME lookup `scaffoldSync` used to do internally through the
136
+ * code registry that has since been deleted (#6638's per-name table).
119
137
  */
120
- design?: StarterDesign;
138
+ designLayout?: TemplateLayout;
121
139
  }
122
140
  export interface ScaffoldResult {
123
141
  /** Resolved absolute path to the scaffolded directory. */
@@ -126,6 +144,23 @@ export interface ScaffoldResult {
126
144
  filesCreated: number;
127
145
  /** The gateable route surfaces this scaffold declares (sorted). */
128
146
  surfaces: string[];
147
+ /**
148
+ * The starter this scaffold resolved (#6754 D5) — set whenever a template
149
+ * was resolved, from `template` or from `shape`; absent for the bare overlay.
150
+ * `design` is the applied design's recorded name (#6813 D6): the shipped
151
+ * registry name, or the package's own `name` for an unrecognized one.
152
+ */
153
+ starter?: {
154
+ template: string;
155
+ shape: StarterShape;
156
+ design: string;
157
+ };
158
+ /**
159
+ * The effective module set this scaffold installed (#6759 D6) — what
160
+ * `scaffoldSync` actually received, never the requested `--modules` alone:
161
+ * a keyed run with no `--modules` carries the key's derived level here.
162
+ */
163
+ modules: ModuleName[];
129
164
  }
130
165
  /**
131
166
  * Scaffold an AI Launch Kit starter project into targetDir (synchronous).
@@ -152,8 +187,14 @@ export declare function scaffoldSync(opts: ScaffoldOptions): ScaffoldResult;
152
187
  * its fetched bundle or — when it requires only free modules — from the
153
188
  * `site-templates/` tree this package ships.
154
189
  *
155
- * And, ahead of all five when `opts.template` is set (0): resolve the
156
- * template and union its `requires` with `opts.modules`, so every step above
190
+ * Between 2 and 3, `assertDesignAllowed` (#6760) refuses a design the caller
191
+ * CHOSE (`opts.design`) for a level below Pro, HERE, also before anything is
192
+ * written to disk. A template's own declared design is never gated (#6778
193
+ * option (c)): the template's `requires` already decide its level.
194
+ *
195
+ * And, ahead of all five when `opts.template` (or `opts.shape`, #6754 D5) is
196
+ * set (0): resolve the template and union its `requires` with `opts.modules`,
197
+ * so every step above
157
198
  * runs over the EFFECTIVE module set rather than the requested one.
158
199
  *
159
200
  * `scaffoldSync` itself stays licensing-oblivious on purpose: every existing
@@ -228,6 +269,19 @@ export interface SyncCatalogResult {
228
269
  export declare function syncCatalogSync(opts: {
229
270
  targetDir: string;
230
271
  }): SyncCatalogResult;
272
+ /**
273
+ * Rewrite the template-owned sections of an already-scaffolded repo's root
274
+ * `CLAUDE.md` to the template this create-ailk ships (#6904 D3). The logic
275
+ * lives in `claude-md.ts` (a module jest imports directly); this wrapper
276
+ * only supplies the package's `templates/CLAUDE.md` — the `syncRoutesSync`
277
+ * split. `templateText` stands in for the shipped template in tests.
278
+ */
279
+ export declare function syncClaudeMdSync(opts: {
280
+ targetDir: string;
281
+ templateText?: string;
282
+ }): SyncClaudeMdResult;
283
+ /** Re-exported beside the other sync results so consumers see one surface. */
284
+ export type { SyncClaudeMdResult } from "./claude-md.js";
231
285
  export interface SyncRoutesSyncOptions {
232
286
  /** The already-scaffolded repo to sync (absolute or relative). */
233
287
  targetDir: string;