create-ailk 0.6.1 → 0.8.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.
- package/README.md +87 -14
- package/component-catalog.json +735 -95
- package/component-catalog.md +13 -7
- package/dist/add-module-core.d.ts +22 -0
- package/dist/add-module-core.js +50 -0
- package/dist/add-module.d.ts +89 -0
- package/dist/add-module.js +334 -0
- package/dist/category-profile.d.ts +126 -0
- package/dist/category-profile.js +262 -0
- package/dist/cli.js +89 -29
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -1
- package/dist/lib/extract-module-bundle.d.ts +56 -1
- package/dist/lib/extract-module-bundle.js +170 -14
- package/dist/lib/license-key-files.d.ts +15 -0
- package/dist/lib/license-key-files.js +102 -0
- package/dist/lib/module-license-gate.d.ts +79 -0
- package/dist/lib/module-license-gate.js +160 -12
- package/dist/lib/module-tier.d.ts +45 -16
- package/dist/lib/module-tier.js +76 -0
- package/dist/lib/pro-callout.d.ts +16 -10
- package/dist/lib/pro-callout.js +34 -3
- package/dist/license-set.d.ts +34 -0
- package/dist/license-set.js +194 -0
- package/dist/module-architecture.d.ts +20 -0
- package/dist/module-architecture.js +77 -19
- package/dist/modules/commerce/0.6.1.tar.gz +0 -0
- package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
- package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
- package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
- package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
- package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
- package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
- package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
- package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
- package/dist/modules/workspace/0.6.1.tar.gz +0 -0
- package/dist/parse-args.d.ts +85 -10
- package/dist/parse-args.js +227 -15
- package/dist/programmatic.d.ts +81 -5
- package/dist/programmatic.js +291 -32
- package/dist/site-chrome.d.ts +18 -7
- package/dist/site-chrome.js +32 -14
- package/dist/site-roster.d.ts +127 -0
- package/dist/site-roster.js +499 -0
- package/dist/starter-grid.d.ts +216 -0
- package/dist/starter-grid.js +449 -0
- package/dist/surfaces.d.ts +20 -7
- package/dist/surfaces.js +204 -24
- package/dist/sync-routes.d.ts +9 -0
- package/dist/sync-routes.js +2 -2
- package/dist/template-manifest.d.ts +94 -19
- package/dist/template-manifest.js +170 -289
- package/dist/template-names.d.ts +14 -12
- package/dist/template-names.js +13 -17
- package/package.json +6 -4
- package/site-templates/_base/content/en/BookCall/book-call.mdx +52 -0
- package/site-templates/_base/content/en/Feature/feature-1.mdx +69 -0
- package/site-templates/_base/content/en/Feature/feature-2.mdx +69 -0
- package/site-templates/_base/content/en/Feature/feature-3.mdx +69 -0
- package/site-templates/_base/content/en/FeaturesList/features.mdx +91 -0
- package/site-templates/_base/content/en/GlossaryList/glossary.mdx +65 -0
- package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +67 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-four.mdx +105 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-one.mdx +34 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-three.mdx +94 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-two.mdx +45 -0
- package/site-templates/_base/content/en/PortfolioList/portfolio.mdx +169 -0
- package/site-templates/_base/content/en/Pricing/pricing.mdx +71 -62
- package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +17 -3
- package/site-templates/_base/content/en/TermsPage/terms.mdx +2 -3
- package/site-templates/_base/content/en/UseCase/persona-1.mdx +69 -0
- package/site-templates/_base/content/en/UseCase/persona-2.mdx +69 -0
- package/site-templates/_base/content/en/UseCase/persona-3.mdx +69 -0
- package/site-templates/designs/minimalism/DESIGN.md +162 -0
- package/site-templates/designs/standard/DESIGN.md +167 -0
- package/site-templates/marketing-site/DESIGN.md +59 -40
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +376 -57
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +230 -90
- package/site-templates/marketing-site/ailk-template.json +1 -0
- package/site-templates/marketing-site-free/DESIGN.md +59 -40
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +323 -63
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +323 -113
- package/site-templates/marketing-site-free/ailk-template.json +3 -2
- package/site-templates/marketing-site-free/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +199 -0
- package/site-templates/minimalism-site/DESIGN.md +54 -40
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +246 -19
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +173 -51
- package/site-templates/minimalism-site/ailk-template.json +3 -2
- package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +3 -37
- package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
- package/site-templates/saas-product/DESIGN.md +59 -40
- package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
- package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.json +369 -0
- package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +302 -0
- package/site-templates/shapes/local-business-service/ailk-template.json +10 -0
- package/site-templates/{simple-service → shapes/local-business-service}/content/en/AboutPage/about.mdx +4 -4
- package/site-templates/shapes/local-business-service/content/en/HomePage/home.mdx +70 -0
- package/site-templates/shapes/local-business-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/shapes/local-business-service/content/en/PortfolioList/portfolio.mdx +171 -0
- package/site-templates/shapes/local-business-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
- package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +39 -0
- package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +39 -0
- package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +39 -0
- package/site-templates/shapes/local-business-service/content/en/ServicesList/services.mdx +61 -0
- package/site-templates/shapes/local-business-service/provenance.json +4 -0
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +362 -0
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +300 -0
- package/site-templates/shapes/organization-service/ailk-template.json +10 -0
- package/site-templates/shapes/organization-service/content/en/AboutPage/about.mdx +38 -0
- package/site-templates/shapes/organization-service/content/en/HomePage/home.mdx +85 -0
- package/site-templates/shapes/organization-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/shapes/organization-service/content/en/PortfolioList/portfolio.mdx +171 -0
- package/site-templates/shapes/organization-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
- package/site-templates/shapes/organization-service/content/en/Service/first-engagement.mdx +38 -0
- package/site-templates/shapes/organization-service/content/en/Service/second-engagement.mdx +38 -0
- package/site-templates/shapes/organization-service/content/en/Service/third-engagement.mdx +38 -0
- package/site-templates/shapes/organization-service/content/en/ServicesList/services.mdx +72 -0
- package/site-templates/shapes/organization-service/provenance.json +4 -0
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +369 -0
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +299 -0
- package/site-templates/shapes/person-service/ailk-template.json +10 -0
- package/site-templates/shapes/person-service/content/_site.mdx +85 -0
- package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +39 -0
- package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +97 -0
- package/site-templates/shapes/person-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +169 -0
- package/site-templates/shapes/person-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
- package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +38 -0
- package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +38 -0
- package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +38 -0
- package/site-templates/{simple-service → shapes/person-service}/content/en/ServicesList/services.mdx +16 -16
- package/site-templates/shapes/person-service/provenance.json +4 -0
- package/templates/.claude/settings.json +15 -0
- package/templates/.claude/skills/README.md +10 -9
- package/templates/.claude/skills/{scaffold-auth → add-auth}/SKILL.md +7 -7
- package/templates/.claude/skills/{scaffold-auth → add-auth}/references/env-vars.md +2 -2
- package/templates/.claude/skills/{scaffold-auth → add-auth}/references/oauth-app-setup.md +3 -3
- package/templates/.claude/skills/{scaffold-page → add-page}/SKILL.md +76 -62
- package/templates/.claude/skills/add-page/references/page-types.md +115 -0
- package/templates/.claude/skills/{scaffold-page → add-page}/templates/content.mdx.tmpl +4 -4
- package/templates/.claude/skills/{scaffold-page → add-page}/templates/route.tsx.tmpl +1 -1
- package/templates/.claude/skills/{audit-site → check-site}/SKILL.md +16 -17
- package/templates/.claude/skills/{audit-site → check-site}/references/common-errors.md +3 -3
- package/templates/.claude/skills/{audit-site → check-site}/references/findings-glossary.md +16 -14
- package/templates/.claude/skills/{audit-site → check-site}/references/severity-levels.md +1 -1
- package/templates/.claude/skills/fill-page/SKILL.md +180 -0
- package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +80 -0
- package/templates/.claude/skills/fill-page/references/section-sources.md +41 -0
- package/templates/.claude/skills/setup-database/SKILL.md +156 -0
- package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +154 -0
- package/templates/.claude/skills/{provision-config → setup-deploy}/SKILL.md +73 -41
- package/templates/.claude/skills/{provision-config → setup-deploy}/references/env-vars-template.md +21 -30
- package/templates/.claude/skills/setup-deploy/references/runbook-template.md +204 -0
- package/templates/.claude/skills/{provision-config → setup-deploy}/references/vercel-json-template.md +1 -1
- package/templates/.claude/skills/upgrade-plan/SKILL.md +117 -0
- package/templates/.claude/skills/upgrade-plan/references/options.md +24 -0
- package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +527 -0
- package/templates/.github/workflows/ci.yml +5 -0
- package/templates/CLAUDE.md +8 -2
- package/templates/DESIGN.md +56 -44
- package/templates/README.md +116 -46
- package/templates/apps/api/.env.example +2 -1
- package/templates/apps/api/CLAUDE.md +3 -2
- package/templates/apps/api/package.json +1 -1
- package/templates/apps/api/src/config/__tests__/index.test.ts +146 -10
- package/templates/apps/api/src/config/index.ts +46 -14
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +30 -0
- package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +96 -0
- package/templates/apps/api/src/lib/lead-capture-store.ts +12 -0
- package/templates/apps/api/src/lib/lead-delivery.ts +52 -0
- package/templates/apps/api/src/lib/license-key-store.ts +45 -0
- package/templates/apps/api/src/lib/site.ts +5 -3
- package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +97 -0
- package/templates/apps/api/src/middleware/auth.ts +9 -0
- package/templates/apps/api/src/openapi/spec.ts +63 -12
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +127 -5
- package/templates/apps/api/src/routes/content/get-page.ts +86 -2
- package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +88 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +100 -0
- package/templates/apps/api/src/routes/leads/index.ts +46 -1
- package/templates/apps/api/src/server.ts +13 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +194 -0
- package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +124 -0
- package/templates/apps/api/src/services/lead-routing.ts +140 -30
- package/templates/apps/api/src/services/leads-inbox.ts +48 -11
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +75 -1
- package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +57 -9
- package/templates/apps/mcp/__tests__/parity.test.ts +5 -4
- package/templates/apps/mcp/package.json +2 -1
- package/templates/apps/mcp/src/index.ts +7 -0
- package/templates/apps/mcp/src/lib/audit-single-page.ts +36 -10
- package/templates/apps/mcp/src/lib/license-key-store.ts +45 -0
- package/templates/apps/mcp/src/tools/create_project.ts +21 -6
- package/templates/apps/web/__tests__/setup.ts +18 -0
- package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +10 -2
- package/templates/apps/web/app/[locale]/(auth)/layout.tsx +2 -2
- package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +10 -4
- package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +22 -14
- package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +26 -18
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +12 -4
- package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +35 -4
- package/templates/apps/web/app/[locale]/[slug]/page.tsx +49 -9
- package/templates/apps/web/app/[locale]/book-a-call/page.tsx +50 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +67 -29
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +94 -11
- package/templates/apps/web/app/[locale]/contact/__tests__/contact-form-text.test.ts +32 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +129 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +228 -86
- package/templates/apps/web/app/[locale]/contact/contact-form-text.ts +50 -0
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +73 -20
- package/templates/apps/web/app/[locale]/contact/page.tsx +115 -7
- package/templates/apps/web/app/[locale]/contact/site-contact-email.ts +54 -0
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +4 -5
- package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +64 -0
- package/templates/apps/web/app/[locale]/features/page.tsx +52 -0
- package/templates/apps/web/app/[locale]/glossary/page.tsx +50 -0
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/how-to/page.tsx +25 -15
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/layout.tsx +146 -52
- package/templates/apps/web/app/[locale]/newsletter/__tests__/newsletter.actions.test.ts +75 -0
- package/templates/apps/web/app/[locale]/newsletter/__tests__/page.test.tsx +163 -0
- package/templates/apps/web/app/[locale]/newsletter/newsletter.actions.ts +66 -0
- package/templates/apps/web/app/[locale]/newsletter/page.tsx +142 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +59 -0
- package/templates/apps/web/app/[locale]/portfolio/page.tsx +49 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +4 -5
- package/templates/apps/web/app/[locale]/{cancellation → purchase-policy}/page.tsx +15 -10
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +4 -5
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +14 -1
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/software/page.tsx +25 -15
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/tech-articles/page.tsx +25 -15
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/use-cases/[slug]/page.tsx +63 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +15 -2
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/whitepapers/page.tsx +25 -15
- package/templates/apps/web/app/error-fallback.tsx +17 -45
- package/templates/apps/web/app/not-found.tsx +14 -38
- package/templates/apps/web/app/og/route.tsx +6 -0
- package/templates/apps/web/eslint.config.mjs +3 -0
- package/templates/apps/web/instrumentation.ts +14 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +38 -0
- package/templates/apps/web/lib/license-key-store.ts +52 -0
- package/templates/apps/web/lib/nav-config.ts +82 -18
- package/templates/apps/web/lib/prisma-for-auth.ts +9 -6
- package/templates/apps/web/lib/site-brand.tsx +1 -1
- package/templates/apps/web/lib/site-chrome.ts +3 -3
- package/templates/apps/web/lib/site-identity.ts +148 -0
- package/templates/apps/web/lib/site-theme.ts +11 -0
- package/templates/apps/web/messages/en.json +78 -37
- package/templates/apps/web/public/android-chrome-192x192.png +0 -0
- package/templates/apps/web/public/android-chrome-512x512.png +0 -0
- package/templates/apps/web/public/apple-touch-icon.png +0 -0
- package/templates/apps/web/public/favicon-16x16.png +0 -0
- package/templates/apps/web/public/favicon-32x32.png +0 -0
- package/templates/apps/web/public/favicon.ico +0 -0
- package/templates/apps/web/public/favicon.svg +3 -3
- package/templates/apps/web/public/logomark.svg +6 -3
- package/templates/apps/web/public/logos/ai-launch-kit-light.svg +4 -0
- package/templates/apps/web/public/logos/ai-launch-kit.svg +4 -0
- package/templates/apps/web/public/logos/atomic-agent-light.svg +4 -0
- package/templates/apps/web/public/logos/atomic-agent.svg +4 -0
- package/templates/apps/web/public/logos/salessmyth-light.svg +4 -0
- package/templates/apps/web/public/logos/salessmyth.svg +4 -0
- package/templates/apps/web/public/site.webmanifest +4 -4
- package/templates/apps/web/public/wordmark-light.svg +4 -0
- package/templates/apps/web/public/wordmark.svg +3 -3
- package/templates/apps/web/security-headers.config.ts +5 -1
- package/templates/content/_site.mdx +25 -0
- package/templates/content/en/AboutPage/about.mdx +150 -144
- package/templates/content/en/BlogList/blog.mdx +126 -0
- package/templates/content/en/ContactPage/contact.mdx +21 -92
- package/templates/content/en/FAQPage/faq.mdx +86 -57
- package/templates/content/en/HomePage/home.mdx +268 -217
- package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +181 -0
- package/templates/content/en/UseCasesList/use-cases.mdx +170 -0
- package/templates/database/CHANGELOG.md +14 -0
- package/templates/database/package.json +1 -1
- package/templates/package.json +3 -1
- package/templates/tools/lint-architecture.ts +315 -0
- package/templates/tools/tsconfig.json +14 -0
- package/versions.json +33 -33
- package/site-templates/simple-service/DESIGN.md +0 -148
- package/site-templates/simple-service/TEMPLATE-MANIFEST.json +0 -240
- package/site-templates/simple-service/TEMPLATE-MANIFEST.md +0 -278
- package/site-templates/simple-service/ailk-template.json +0 -10
- package/site-templates/simple-service/content/en/ContactPage/contact.mdx +0 -67
- package/site-templates/simple-service/content/en/FAQPage/faq.mdx +0 -56
- package/site-templates/simple-service/content/en/HomePage/home.mdx +0 -85
- package/site-templates/simple-service/content/en/Service/landscape-design.mdx +0 -40
- package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +0 -40
- package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +0 -40
- package/site-templates/simple-service/provenance.json +0 -4
- package/templates/.claude/skills/add-schema/SKILL.md +0 -277
- package/templates/.claude/skills/add-schema/references/conflict-handling.md +0 -200
- package/templates/.claude/skills/add-schema/references/file-finding.md +0 -123
- package/templates/.claude/skills/add-schema/references/schema-types.md +0 -234
- package/templates/.claude/skills/provision-config/references/runbook-template.md +0 -248
- package/templates/.claude/skills/scaffold-page/references/page-types.md +0 -169
- package/templates/.claude/skills/suggest-site-pages/SKILL.md +0 -242
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +0 -287
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +0 -150
- package/templates/apps/web/app/[locale]/returns/page.tsx +0 -44
- package/templates/apps/web/app/[locale]/shipping/page.tsx +0 -44
- package/templates/content/en/CancellationPolicyPage/cancellation.mdx +0 -108
- package/templates/content/en/LandingPage/blog.mdx +0 -83
- package/templates/content/en/LandingPage/features.mdx +0 -103
- package/templates/content/en/LandingPage/how-it-works.mdx +0 -143
- package/templates/content/en/ReturnsPolicyPage/returns.mdx +0 -108
- package/templates/content/en/ShippingPolicyPage/shipping.mdx +0 -108
package/dist/programmatic.js
CHANGED
|
@@ -15,21 +15,24 @@
|
|
|
15
15
|
* import { scaffoldSync } from './programmatic.js';
|
|
16
16
|
* const result = scaffoldSync({ targetDir: '/tmp/my-site', projectName: 'my-site' });
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
19
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
18
|
+
import { existsSync, readdirSync, readFileSync, rmdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
19
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
|
+
import { AddModuleRefusedError, applyModuleToScaffold, } from "./add-module.js";
|
|
21
22
|
import { CATALOG_TARGET_PATH, writeComponentCatalog, } from "./component-catalog.js";
|
|
22
23
|
import { buildScaffoldMarkers, copyTemplate } from "./copy.js";
|
|
23
24
|
import { deriveArchitecture } from "./derive-architecture.js";
|
|
24
25
|
import { extractModuleBundle, installBundleTree, } from "./lib/extract-module-bundle.js";
|
|
25
26
|
import { fetchTemplate } from "./lib/fetch-template.js";
|
|
26
|
-
import {
|
|
27
|
+
import { assertLicenseKeyShape, writeLicenseKeyFiles, } from "./lib/license-key-files.js";
|
|
28
|
+
import { FREE_DESIGNS, assertDesignAllowed, deriveLevel, resolveModuleSet, resolvePaidModules, } from "./lib/module-license-gate.js";
|
|
27
29
|
import { classifyModules } from "./lib/module-tier.js";
|
|
28
30
|
import { normalizeModules } from "./module-architecture.js";
|
|
31
|
+
import { RECOGNIZED_SHAPES, RESERVED_SHAPES, } from "./parse-args.js";
|
|
29
32
|
import { SITE_CHROME_PATH, renderSiteChrome, resolveSiteChrome, } from "./site-chrome.js";
|
|
30
33
|
import { GATEABLE_SURFACES, MODULE_SURFACES, NAV_CONFIG_PATH, excludedRoutePaths, renderNavConfig, resolveSurfaces, } from "./surfaces.js";
|
|
31
34
|
import { syncRoutes } from "./sync-routes.js";
|
|
32
|
-
import { BASE_LAYER_DIR, mergeRoster, resolveTemplate, resolveTemplateLineage, templateDelivery, } from "./template-manifest.js";
|
|
35
|
+
import { BASE_LAYER_DIR, SHAPE_STARTERS, STARTER_DESIGNS, TEMPLATE_MANIFESTS, TemplateError, mergeRoster, resolveTemplate, resolveTemplateLineage, rosterDeclares, templateDelivery, templateTreeDir, } from "./template-manifest.js";
|
|
33
36
|
import { validateTarget } from "./validate.js";
|
|
34
37
|
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
35
38
|
const TEMPLATES_DIR = resolve(PKG_ROOT, "templates");
|
|
@@ -73,6 +76,37 @@ function countFiles(dir) {
|
|
|
73
76
|
}
|
|
74
77
|
return count;
|
|
75
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* The template a `shape` scaffolds (#6754 D5, extended #6757 D6 row 1): the
|
|
81
|
+
* one FREE-delivery manifest of that shape — a declared `--template` alias
|
|
82
|
+
* (`TEMPLATE_MANIFESTS`) or a bare-shape starter with no alias of its own
|
|
83
|
+
* (`SHAPE_STARTERS`), the union the candidate set draws from. Reads manifest
|
|
84
|
+
* fields only — no roster.
|
|
85
|
+
*
|
|
86
|
+
* @throws TemplateError on a reserved or unknown shape, a shape with no Free
|
|
87
|
+
* starter yet (D6), or more than one (never picked silently).
|
|
88
|
+
*/
|
|
89
|
+
function resolveShapeTemplate(shape) {
|
|
90
|
+
if (!RECOGNIZED_SHAPES.includes(shape)) {
|
|
91
|
+
const known = RECOGNIZED_SHAPES.join(", ");
|
|
92
|
+
throw new TemplateError(RESERVED_SHAPES.includes(shape)
|
|
93
|
+
? `shape "${shape}" is not available yet. Choose one of: ${known}.`
|
|
94
|
+
: `unknown shape "${shape}". Recognized: ${known}`);
|
|
95
|
+
}
|
|
96
|
+
const ofShape = [
|
|
97
|
+
...Object.values(TEMPLATE_MANIFESTS),
|
|
98
|
+
...Object.values(SHAPE_STARTERS),
|
|
99
|
+
].filter((manifest) => manifest.shape === shape);
|
|
100
|
+
const free = ofShape.filter((manifest) => templateDelivery(manifest) === "free");
|
|
101
|
+
if (free.length === 0) {
|
|
102
|
+
const names = ofShape.map((manifest) => manifest.name).join(", ");
|
|
103
|
+
throw new TemplateError(`shape "${shape}" has no Free starter yet — its page list lands with #6743. Templates built on this shape: ${names || "none"}.`);
|
|
104
|
+
}
|
|
105
|
+
if (free.length > 1) {
|
|
106
|
+
throw new TemplateError(`shape "${shape}" has more than one Free starter: ${free.map((manifest) => manifest.name).join(", ")}`);
|
|
107
|
+
}
|
|
108
|
+
return free[0];
|
|
109
|
+
}
|
|
76
110
|
/**
|
|
77
111
|
* Scaffold an AI Launch Kit starter project into targetDir (synchronous).
|
|
78
112
|
*
|
|
@@ -110,13 +144,18 @@ export function scaffoldSync(opts) {
|
|
|
110
144
|
// template's `layout` block; a bare `scaffoldSync` call (every existing
|
|
111
145
|
// synchronous caller) writes DEFAULT_SITE_CHROME, byte-identical to the
|
|
112
146
|
// monorepo's own committed apps/web/lib/site-chrome.ts.
|
|
113
|
-
writeFileSync(join(targetAbs, SITE_CHROME_PATH), renderSiteChrome(resolveSiteChrome(opts.layout)));
|
|
147
|
+
writeFileSync(join(targetAbs, SITE_CHROME_PATH), renderSiteChrome(resolveSiteChrome(opts.layout, opts.design)));
|
|
114
148
|
// Opt-in only (#4636). Every write above this line is unconditional, so a
|
|
115
149
|
// scaffold with `withCatalog` unset touches exactly the files it did before.
|
|
116
150
|
if (opts.withCatalog === true)
|
|
117
151
|
writeComponentCatalog(targetAbs);
|
|
118
152
|
const filesCreated = countFiles(targetAbs);
|
|
119
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
targetDir: targetAbs,
|
|
155
|
+
filesCreated,
|
|
156
|
+
surfaces: enabledSurfaces,
|
|
157
|
+
modules: normalizeModules(opts.modules ?? ["marketing"]),
|
|
158
|
+
};
|
|
120
159
|
}
|
|
121
160
|
/**
|
|
122
161
|
* Scaffold an AI Launch Kit starter project into targetDir (async wrapper).
|
|
@@ -136,8 +175,14 @@ export function scaffoldSync(opts) {
|
|
|
136
175
|
* its fetched bundle or — when it requires only free modules — from the
|
|
137
176
|
* `site-templates/` tree this package ships.
|
|
138
177
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
178
|
+
* Between 2 and 3, `assertDesignAllowed` (#6760) refuses a design the caller
|
|
179
|
+
* CHOSE (`opts.design`) for a level below Pro, HERE, also before anything is
|
|
180
|
+
* written to disk. A template's own declared design is never gated (#6778
|
|
181
|
+
* option (c)): the template's `requires` already decide its level.
|
|
182
|
+
*
|
|
183
|
+
* And, ahead of all five when `opts.template` (or `opts.shape`, #6754 D5) is
|
|
184
|
+
* set (0): resolve the template and union its `requires` with `opts.modules`,
|
|
185
|
+
* so every step above
|
|
141
186
|
* runs over the EFFECTIVE module set rather than the requested one.
|
|
142
187
|
*
|
|
143
188
|
* `scaffoldSync` itself stays licensing-oblivious on purpose: every existing
|
|
@@ -146,35 +191,134 @@ export function scaffoldSync(opts) {
|
|
|
146
191
|
* with a paid module in `opts.modules` exercises the gate at all.
|
|
147
192
|
*/
|
|
148
193
|
export async function scaffold(opts) {
|
|
194
|
+
// #6683 D9 — refused before anything is fetched or written, like the
|
|
195
|
+
// template and design refusals below. The message never repeats the value.
|
|
196
|
+
if (opts.license !== undefined)
|
|
197
|
+
assertLicenseKeyShape(opts.license);
|
|
198
|
+
const licenseKey = opts.license ?? opts.licenseKey;
|
|
149
199
|
// Resolved first, and by the registry rather than re-validated here: the
|
|
150
200
|
// name already passed `parse-args.ts`, and `resolveTemplate` throws a
|
|
151
|
-
// `TemplateError` for a programmatic caller that skipped the parser.
|
|
152
|
-
|
|
201
|
+
// `TemplateError` for a programmatic caller that skipped the parser. A
|
|
202
|
+
// `shape` resolves to its one Free starter and from there is the template
|
|
203
|
+
// path verbatim (#6754 D5); neither leaves the bare overlay untouched.
|
|
204
|
+
if (opts.template !== undefined && opts.shape !== undefined) {
|
|
205
|
+
throw new TemplateError("pass a template or a shape, not both");
|
|
206
|
+
}
|
|
207
|
+
const template = opts.template !== undefined
|
|
208
|
+
? resolveTemplate(opts.template)
|
|
209
|
+
: opts.shape !== undefined
|
|
210
|
+
? resolveShapeTemplate(opts.shape)
|
|
211
|
+
: undefined;
|
|
212
|
+
// #6638 — the design this scaffold renders: the caller's override, else the
|
|
213
|
+
// template's own. Unset for a scaffold naming neither.
|
|
214
|
+
const design = opts.design ?? template?.design;
|
|
215
|
+
if (design !== undefined && !STARTER_DESIGNS.includes(design)) {
|
|
216
|
+
throw new TemplateError(`unknown design "${design}". Declared: ${STARTER_DESIGNS.join(", ")}`);
|
|
217
|
+
}
|
|
153
218
|
// #5618 D2 — the `extends` chain is resolved in the client registry before
|
|
154
219
|
// any fetch: an unknown parent or a cycle is refused here, with the target
|
|
155
|
-
// still non-existent, like the four refusals below.
|
|
156
|
-
|
|
157
|
-
|
|
220
|
+
// still non-existent, like the four refusals below. The registry is the
|
|
221
|
+
// union of TEMPLATE_MANIFESTS and SHAPE_STARTERS (#6757 D6 row 1): a
|
|
222
|
+
// `--shape` run's resolved template may be a bare-shape starter, whose name
|
|
223
|
+
// (the shape itself) `TEMPLATE_MANIFESTS` alone does not carry.
|
|
224
|
+
if (template !== undefined) {
|
|
225
|
+
resolveTemplateLineage(template.name, {
|
|
226
|
+
...TEMPLATE_MANIFESTS,
|
|
227
|
+
...SHAPE_STARTERS,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
158
230
|
// The effective module set: union(template.requires, parsed --modules),
|
|
159
231
|
// normalized through `normalizeModules` — the single ordering authority
|
|
160
232
|
// (parent record D7). Order-independence falls out rather than being
|
|
161
233
|
// engineered: it returns `RECOGNIZED_MODULES.filter(...)`, declaration-
|
|
162
234
|
// ordered and deduped, so the same SET in any argument order is the same
|
|
163
235
|
// list.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
236
|
+
let modules;
|
|
237
|
+
let bundles;
|
|
238
|
+
// The run's derived level (#6759), for `assertDesignAllowed` below.
|
|
239
|
+
// Undefined on the alias branch and on a `--modules`-keep run (D2/D4 in
|
|
240
|
+
// module-license-gate.ts — the level plays no part in composing either),
|
|
241
|
+
// so a non-`standard` design on either path derives it separately, below.
|
|
242
|
+
let level;
|
|
243
|
+
if (opts.template !== undefined) {
|
|
244
|
+
// Alias run — untouched (NFR-4): the union line and its
|
|
245
|
+
// resolvePaidModules({ …, templateName }) call stay exactly as they were.
|
|
246
|
+
modules = normalizeModules([
|
|
247
|
+
...(template?.requires ?? []),
|
|
248
|
+
...(opts.modules ?? ["marketing"]),
|
|
249
|
+
]);
|
|
250
|
+
const { paid } = classifyModules(modules);
|
|
251
|
+
bundles = await resolvePaidModules({
|
|
252
|
+
paidModules: paid,
|
|
253
|
+
licenseKey,
|
|
254
|
+
...(template !== undefined ? { templateName: template.name } : {}),
|
|
255
|
+
...(opts.moduleRegistryUrl !== undefined
|
|
256
|
+
? { registryUrl: opts.moduleRegistryUrl }
|
|
257
|
+
: {}),
|
|
258
|
+
...(opts.fetchImpl !== undefined ? { fetchImpl: opts.fetchImpl } : {}),
|
|
259
|
+
});
|
|
260
|
+
// #6760 — `resolveModuleSet` never runs on this branch (NFR-4), so no
|
|
261
|
+
// level was derived above. Derive one — from the registry's per-module
|
|
262
|
+
// answers, never a key claim (D2) — only when the caller CHOSE a
|
|
263
|
+
// non-`standard` design alongside the template (`opts.design`). An
|
|
264
|
+
// alias's own declared design is never gated (#6778 option (c)), so a
|
|
265
|
+
// plain `--template minimalism-site` run makes no extra network call and
|
|
266
|
+
// is never refused on its design.
|
|
267
|
+
if (opts.design !== undefined && !FREE_DESIGNS.includes(opts.design)) {
|
|
268
|
+
({ level } = await deriveLevel({
|
|
269
|
+
licenseKey,
|
|
270
|
+
...(opts.moduleRegistryUrl !== undefined
|
|
271
|
+
? { registryUrl: opts.moduleRegistryUrl }
|
|
272
|
+
: {}),
|
|
273
|
+
...(opts.fetchImpl !== undefined ? { fetchImpl: opts.fetchImpl } : {}),
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// Shape and bare runs — the key's level decides (#6759 D6), never a flag,
|
|
279
|
+
// a manifest or a key claim.
|
|
280
|
+
const chosen = await resolveModuleSet({
|
|
281
|
+
named: opts.modules,
|
|
282
|
+
licenseKey,
|
|
283
|
+
...(opts.moduleRegistryUrl !== undefined
|
|
284
|
+
? { registryUrl: opts.moduleRegistryUrl }
|
|
285
|
+
: {}),
|
|
286
|
+
...(opts.fetchImpl !== undefined ? { fetchImpl: opts.fetchImpl } : {}),
|
|
287
|
+
});
|
|
288
|
+
bundles = chosen.bundles;
|
|
289
|
+
level = chosen.level;
|
|
290
|
+
modules =
|
|
291
|
+
template !== undefined
|
|
292
|
+
? normalizeModules([...template.requires, ...chosen.modules])
|
|
293
|
+
: chosen.modules;
|
|
294
|
+
// A paid member of the shape's own starter `requires` not already
|
|
295
|
+
// fetched during the level probe (D6) — every buildable shape's starter
|
|
296
|
+
// requires only `marketing` today, so this is presently a no-op branch.
|
|
297
|
+
if (template !== undefined) {
|
|
298
|
+
const templatePaid = classifyModules(template.requires).paid;
|
|
299
|
+
const stillMissing = templatePaid.filter((m) => !bundles.has(m));
|
|
300
|
+
if (stillMissing.length > 0) {
|
|
301
|
+
const extra = await resolvePaidModules({
|
|
302
|
+
paidModules: stillMissing,
|
|
303
|
+
licenseKey,
|
|
304
|
+
...(opts.moduleRegistryUrl !== undefined
|
|
305
|
+
? { registryUrl: opts.moduleRegistryUrl }
|
|
306
|
+
: {}),
|
|
307
|
+
...(opts.fetchImpl !== undefined
|
|
308
|
+
? { fetchImpl: opts.fetchImpl }
|
|
309
|
+
: {}),
|
|
310
|
+
});
|
|
311
|
+
for (const [k, v] of extra)
|
|
312
|
+
bundles.set(k, v);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// #6760 D4 — after the level is resolved, before any fetch or write below.
|
|
317
|
+
// Only the caller's chosen design is gated (#6778 option (c)); a template's
|
|
318
|
+
// own declared design is not. `level ?? "free"` fails closed: a
|
|
319
|
+
// `--modules`-keep run under-reports its level by design (NFR-2), so a
|
|
320
|
+
// chosen non-`standard` design on that path is refused rather than trusted.
|
|
321
|
+
assertDesignAllowed(opts.design, level ?? "free");
|
|
178
322
|
// The template's OWN bundle, fetched here — before `scaffoldSync` — so the
|
|
179
323
|
// fourth refusal (the template's bundle unpublished, parent record D17 /
|
|
180
324
|
// spec 5481 § 3 DD5 row 4) throws with the target still non-existent, like
|
|
@@ -189,7 +333,7 @@ export async function scaffold(opts) {
|
|
|
189
333
|
const templateBundle = template !== undefined && templateDelivery(template) === "paid"
|
|
190
334
|
? await fetchTemplate({
|
|
191
335
|
templateName: template.name,
|
|
192
|
-
token:
|
|
336
|
+
token: licenseKey ?? process.env["AILK_LICENSE_KEY"] ?? "",
|
|
193
337
|
...(opts.templateRegistryUrl !== undefined
|
|
194
338
|
? { registryUrl: opts.templateRegistryUrl }
|
|
195
339
|
: {}),
|
|
@@ -224,9 +368,11 @@ export async function scaffold(opts) {
|
|
|
224
368
|
...(surfaces !== undefined ? { surfaces } : {}),
|
|
225
369
|
// #5612 D1/D2 — the code registry's own `layout` block, known
|
|
226
370
|
// synchronously (unlike a bundle's `ailk-template.json`, only readable
|
|
227
|
-
// after install below). A template declaring none resolves to
|
|
228
|
-
//
|
|
371
|
+
// after install below). A template declaring none resolves to its
|
|
372
|
+
// design's knobs (#6638), and a `standard` one to the same defaults
|
|
373
|
+
// `scaffoldSync` already writes for a templateless scaffold.
|
|
229
374
|
...(template?.layout !== undefined ? { layout: template.layout } : {}),
|
|
375
|
+
...(design !== undefined ? { design } : {}),
|
|
230
376
|
});
|
|
231
377
|
// Threaded to extractModuleBundle for `package.json` patch targets'
|
|
232
378
|
// `workspace:*` substitution (spec 5418 § 3 D2) — the same version map
|
|
@@ -311,7 +457,7 @@ export async function scaffold(opts) {
|
|
|
311
457
|
ownership,
|
|
312
458
|
})
|
|
313
459
|
: (() => {
|
|
314
|
-
const sourceRoot = join(SITE_TEMPLATES_DIR, template.name);
|
|
460
|
+
const sourceRoot = join(SITE_TEMPLATES_DIR, templateTreeDir(template.name));
|
|
315
461
|
if (!existsSync(sourceRoot)) {
|
|
316
462
|
throw new Error(`template "${template.name}": ${sourceRoot} is missing — the published package must carry site-templates/ in its "files" list`);
|
|
317
463
|
}
|
|
@@ -327,11 +473,73 @@ export async function scaffold(opts) {
|
|
|
327
473
|
});
|
|
328
474
|
})();
|
|
329
475
|
if (installed.layout !== undefined) {
|
|
330
|
-
writeFileSync(join(result.targetDir, SITE_CHROME_PATH), renderSiteChrome(resolveSiteChrome(installed.layout)));
|
|
476
|
+
writeFileSync(join(result.targetDir, SITE_CHROME_PATH), renderSiteChrome(resolveSiteChrome(installed.layout, design)));
|
|
331
477
|
}
|
|
478
|
+
pruneUnrosteredSeeds(result.targetDir, mergeRoster(template, template.requires), result.surfaces, ownership);
|
|
479
|
+
}
|
|
480
|
+
// #6683 D9 — persisted only after every layer landed, and only when the
|
|
481
|
+
// caller passed `license`: a scaffold without it writes nothing new.
|
|
482
|
+
if (opts.license !== undefined) {
|
|
483
|
+
writeLicenseKeyFiles(result.targetDir, opts.license);
|
|
484
|
+
}
|
|
485
|
+
// #6754 D4/D5 — the resolved starter, so the CLI names what it built.
|
|
486
|
+
if (template !== undefined && design !== undefined) {
|
|
487
|
+
return {
|
|
488
|
+
...result,
|
|
489
|
+
starter: { template: template.name, shape: template.shape, design },
|
|
490
|
+
};
|
|
332
491
|
}
|
|
333
492
|
return result;
|
|
334
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* The per-row install of the two SHARED seed layers (#6646 D1, disposition
|
|
496
|
+
* (b)): with every layer landed, remove each `content/en/**.mdx` that the
|
|
497
|
+
* `templates/` snapshot (the overlay — no `ownership` entry) or the `_base`
|
|
498
|
+
* layer wrote and no merged roster row names. Those two layers serve every
|
|
499
|
+
* template, so each carries seeds some templates do not roster (`/pricing`
|
|
500
|
+
* on a services site); a template's own tree and its modules' bundles are
|
|
501
|
+
* never pruned — a seed THEY ship without a row is drift, which the manifest
|
|
502
|
+
* generator's `--check` fails on instead.
|
|
503
|
+
*
|
|
504
|
+
* Merged over the template's own `requires`, as `rosterSurfaces` is: the
|
|
505
|
+
* rows that name shared-layer seeds are the template's own. A seed inside
|
|
506
|
+
* the content directory of a surface this scaffold ENABLES is kept too, so
|
|
507
|
+
* an explicit `--surfaces pricing` on a template that does not roster
|
|
508
|
+
* `/pricing` gets its route and its seed together.
|
|
509
|
+
*/
|
|
510
|
+
function pruneUnrosteredSeeds(targetDir, roster, surfaces, ownership) {
|
|
511
|
+
// `installBundleTree`'s ownership label for the base layer: it installs
|
|
512
|
+
// with `templateRequires: []`, so it records as a template. The overlay
|
|
513
|
+
// (the `templates/` snapshot) records no owner at all.
|
|
514
|
+
const shared = new Set([undefined, `template "${BASE_LAYER_DIR}"`]);
|
|
515
|
+
const enabledDirs = GATEABLE_SURFACES.filter((surface) => surfaces.includes(surface.id)).flatMap((surface) => surface.content.map((dir) => `${dir.replace("<locale>", "en")}/`));
|
|
516
|
+
const root = join(targetDir, "content", "en");
|
|
517
|
+
if (!existsSync(root))
|
|
518
|
+
return;
|
|
519
|
+
const stack = [root];
|
|
520
|
+
while (stack.length > 0) {
|
|
521
|
+
const dir = stack.pop();
|
|
522
|
+
if (dir === undefined)
|
|
523
|
+
break;
|
|
524
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
525
|
+
const abs = join(dir, entry.name);
|
|
526
|
+
if (entry.isDirectory()) {
|
|
527
|
+
stack.push(abs);
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
if (!entry.name.endsWith(".mdx"))
|
|
531
|
+
continue;
|
|
532
|
+
const path = relative(targetDir, abs).split(sep).join("/");
|
|
533
|
+
if (shared.has(ownership.get(path)) &&
|
|
534
|
+
!rosterDeclares(roster, path) &&
|
|
535
|
+
!enabledDirs.some((prefix) => path.startsWith(prefix))) {
|
|
536
|
+
rmSync(abs);
|
|
537
|
+
if (readdirSync(dir).length === 0)
|
|
538
|
+
rmdirSync(dir);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
335
543
|
/**
|
|
336
544
|
* The MODULE-LESS gateable-surface ids a template's merged roster names
|
|
337
545
|
* (#5469 D10): every `GATEABLE_SURFACES` entry no module contributes
|
|
@@ -478,6 +686,57 @@ export function syncRoutesSync(opts) {
|
|
|
478
686
|
versions: readVersionMap(),
|
|
479
687
|
});
|
|
480
688
|
}
|
|
689
|
+
/**
|
|
690
|
+
* Apply a purchased module to an already-scaffolded site in place
|
|
691
|
+
* (`create-ailk add-module`, #6653). The thin package-rooted wrapper around
|
|
692
|
+
* `add-module.ts`'s `applyModuleToScaffold`, the `syncRoutesSync` split:
|
|
693
|
+
*
|
|
694
|
+
* 1. the target must be an existing scaffold — the same check as the sync
|
|
695
|
+
* subcommands above;
|
|
696
|
+
* 2. a free module is refused before any key read or network call — it
|
|
697
|
+
* ships with every scaffold, there is no bundle to add;
|
|
698
|
+
* 3. `resolvePaidModules` — the SAME gate `scaffold()` runs, so a missing
|
|
699
|
+
* key or a key that does not cover the module is refused with the
|
|
700
|
+
* scaffold-time message, before anything is written;
|
|
701
|
+
* 4. the fetched bundle is merged under the plus-config policy.
|
|
702
|
+
*/
|
|
703
|
+
export async function addModule(opts) {
|
|
704
|
+
const targetAbs = resolve(opts.targetDir);
|
|
705
|
+
if (!existsSync(targetAbs)) {
|
|
706
|
+
throw new Error(`add-module target does not exist: ${targetAbs}. Point add-module at an already-scaffolded repo.`);
|
|
707
|
+
}
|
|
708
|
+
if (!statSync(targetAbs).isDirectory()) {
|
|
709
|
+
throw new Error(`add-module target is not a directory: ${targetAbs}`);
|
|
710
|
+
}
|
|
711
|
+
if (!existsSync(join(targetAbs, "architecture.yaml"))) {
|
|
712
|
+
throw new Error(`not a scaffolded repo: no architecture.yaml at ${targetAbs}. Run \`create-ailk <target-dir>\` to scaffold first.`);
|
|
713
|
+
}
|
|
714
|
+
const { paid } = classifyModules([opts.moduleName]);
|
|
715
|
+
if (paid.length === 0) {
|
|
716
|
+
throw new AddModuleRefusedError(`"${opts.moduleName}" ships with every scaffold — there is no module bundle to add`);
|
|
717
|
+
}
|
|
718
|
+
const bundles = await resolvePaidModules({
|
|
719
|
+
paidModules: paid,
|
|
720
|
+
licenseKey: opts.licenseKey,
|
|
721
|
+
...(opts.moduleRegistryUrl !== undefined
|
|
722
|
+
? { registryUrl: opts.moduleRegistryUrl }
|
|
723
|
+
: {}),
|
|
724
|
+
...(opts.fetchImpl !== undefined ? { fetchImpl: opts.fetchImpl } : {}),
|
|
725
|
+
});
|
|
726
|
+
const bundleBytes = bundles.get(opts.moduleName);
|
|
727
|
+
if (bundleBytes === undefined) {
|
|
728
|
+
throw new Error(`module "${opts.moduleName}": no bundle was resolved`);
|
|
729
|
+
}
|
|
730
|
+
return applyModuleToScaffold({
|
|
731
|
+
targetDir: targetAbs,
|
|
732
|
+
moduleName: opts.moduleName,
|
|
733
|
+
bundleBytes,
|
|
734
|
+
versions: readVersionMap(),
|
|
735
|
+
markers: buildScaffoldMarkers(basename(targetAbs)),
|
|
736
|
+
templatesDir: TEMPLATES_DIR,
|
|
737
|
+
siteTemplatesDir: SITE_TEMPLATES_DIR,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
481
740
|
/** Re-exported so the CLI can name the file it wrote without duplicating it. */
|
|
482
741
|
export { CATALOG_TARGET_PATH };
|
|
483
742
|
/**
|
package/dist/site-chrome.d.ts
CHANGED
|
@@ -15,11 +15,17 @@
|
|
|
15
15
|
* `apps/web/lib/site-chrome.ts` every scaffold gets — beside `nav-config.ts`,
|
|
16
16
|
* the same GENERATED-header idiom (`surfaces.ts` `renderNavConfig`).
|
|
17
17
|
*
|
|
18
|
-
* Every field is optional and DEFAULTS to
|
|
19
|
-
*
|
|
20
|
-
* no
|
|
21
|
-
* monorepo's own
|
|
18
|
+
* Every field is optional and DEFAULTS to `full` / `columns` / `false` /
|
|
19
|
+
* `default` — the announcement banner is off unless a template turns it on
|
|
20
|
+
* (#6469). A scaffold naming no template, or a template naming no `layout`
|
|
21
|
+
* block, gets these defaults written, byte-identical to the monorepo's own
|
|
22
|
+
* committed `apps/web/lib/site-chrome.ts`.
|
|
23
|
+
*
|
|
24
|
+
* A template's DESIGN supplies layout knobs too (#6638): `DESIGN_LAYOUTS` in
|
|
25
|
+
* `template-manifest.ts`, read by `resolveSiteChrome`'s optional `design`
|
|
26
|
+
* argument between an explicit `layout` and these defaults.
|
|
22
27
|
*/
|
|
28
|
+
import { type StarterDesign } from "./template-manifest.js";
|
|
23
29
|
/** The `nav` knob's vocabulary. `mark-only` → the layout passes Nav an empty
|
|
24
30
|
* `navItems` (brand mark + the existing actions/theme/locale controls only). */
|
|
25
31
|
export type SiteChromeNav = "full" | "mark-only";
|
|
@@ -47,7 +53,7 @@ export interface ResolvedSiteChrome {
|
|
|
47
53
|
announcementBanner: boolean;
|
|
48
54
|
home: SiteChromeHome;
|
|
49
55
|
}
|
|
50
|
-
/**
|
|
56
|
+
/** Defaults (#5612 D1; banner off since #6469). */
|
|
51
57
|
export declare const DEFAULT_SITE_CHROME: ResolvedSiteChrome;
|
|
52
58
|
/** Template-relative path of the generated site-chrome registry — beside `NAV_CONFIG_PATH`. */
|
|
53
59
|
export declare const SITE_CHROME_PATH = "apps/web/lib/site-chrome.ts";
|
|
@@ -68,8 +74,13 @@ export declare class TemplateLayoutError extends Error {
|
|
|
68
74
|
* @param subject Caller-supplied context for the error message (e.g. `template "foo"`).
|
|
69
75
|
*/
|
|
70
76
|
export declare function validateTemplateLayout(value: unknown, subject: string): TemplateLayout;
|
|
71
|
-
/**
|
|
72
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Fill every field a `TemplateLayout` leaves unset — from `design`'s
|
|
79
|
+
* `DESIGN_LAYOUTS` entry when one is named (#6638), then from
|
|
80
|
+
* `DEFAULT_SITE_CHROME`. The explicit `layout` wins field by field, so a
|
|
81
|
+
* template can wear a design and still override one knob of it.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveSiteChrome(layout?: TemplateLayout, design?: StarterDesign): ResolvedSiteChrome;
|
|
73
84
|
/**
|
|
74
85
|
* Render `apps/web/lib/site-chrome.ts` for a resolved layout — the same
|
|
75
86
|
* GENERATED-header idiom `renderNavConfig` uses. `layout.tsx` imports
|
package/dist/site-chrome.js
CHANGED
|
@@ -15,16 +15,22 @@
|
|
|
15
15
|
* `apps/web/lib/site-chrome.ts` every scaffold gets — beside `nav-config.ts`,
|
|
16
16
|
* the same GENERATED-header idiom (`surfaces.ts` `renderNavConfig`).
|
|
17
17
|
*
|
|
18
|
-
* Every field is optional and DEFAULTS to
|
|
19
|
-
*
|
|
20
|
-
* no
|
|
21
|
-
* monorepo's own
|
|
18
|
+
* Every field is optional and DEFAULTS to `full` / `columns` / `false` /
|
|
19
|
+
* `default` — the announcement banner is off unless a template turns it on
|
|
20
|
+
* (#6469). A scaffold naming no template, or a template naming no `layout`
|
|
21
|
+
* block, gets these defaults written, byte-identical to the monorepo's own
|
|
22
|
+
* committed `apps/web/lib/site-chrome.ts`.
|
|
23
|
+
*
|
|
24
|
+
* A template's DESIGN supplies layout knobs too (#6638): `DESIGN_LAYOUTS` in
|
|
25
|
+
* `template-manifest.ts`, read by `resolveSiteChrome`'s optional `design`
|
|
26
|
+
* argument between an explicit `layout` and these defaults.
|
|
22
27
|
*/
|
|
23
|
-
|
|
28
|
+
import { DESIGN_LAYOUTS, TemplateError, } from "./template-manifest.js";
|
|
29
|
+
/** Defaults (#5612 D1; banner off since #6469). */
|
|
24
30
|
export const DEFAULT_SITE_CHROME = {
|
|
25
31
|
nav: "full",
|
|
26
32
|
footer: "columns",
|
|
27
|
-
announcementBanner:
|
|
33
|
+
announcementBanner: false,
|
|
28
34
|
home: "default",
|
|
29
35
|
};
|
|
30
36
|
/** Template-relative path of the generated site-chrome registry — beside `NAV_CONFIG_PATH`. */
|
|
@@ -85,13 +91,25 @@ export function validateTemplateLayout(value, subject) {
|
|
|
85
91
|
}
|
|
86
92
|
return result;
|
|
87
93
|
}
|
|
88
|
-
/**
|
|
89
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Fill every field a `TemplateLayout` leaves unset — from `design`'s
|
|
96
|
+
* `DESIGN_LAYOUTS` entry when one is named (#6638), then from
|
|
97
|
+
* `DEFAULT_SITE_CHROME`. The explicit `layout` wins field by field, so a
|
|
98
|
+
* template can wear a design and still override one knob of it.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveSiteChrome(layout, design) {
|
|
101
|
+
const fromDesign = design !== undefined ? DESIGN_LAYOUTS[design] : {};
|
|
102
|
+
// A JS caller (or a cast) can reach here with an undeclared design.
|
|
103
|
+
if (fromDesign === undefined) {
|
|
104
|
+
throw new TemplateError(`unknown design "${design}". Declared: ${Object.keys(DESIGN_LAYOUTS).join(", ")}`);
|
|
105
|
+
}
|
|
90
106
|
return {
|
|
91
|
-
nav: layout?.nav ?? DEFAULT_SITE_CHROME.nav,
|
|
92
|
-
footer: layout?.footer ?? DEFAULT_SITE_CHROME.footer,
|
|
93
|
-
announcementBanner: layout?.announcementBanner ??
|
|
94
|
-
|
|
107
|
+
nav: layout?.nav ?? fromDesign.nav ?? DEFAULT_SITE_CHROME.nav,
|
|
108
|
+
footer: layout?.footer ?? fromDesign.footer ?? DEFAULT_SITE_CHROME.footer,
|
|
109
|
+
announcementBanner: layout?.announcementBanner ??
|
|
110
|
+
fromDesign.announcementBanner ??
|
|
111
|
+
DEFAULT_SITE_CHROME.announcementBanner,
|
|
112
|
+
home: layout?.home ?? fromDesign.home ?? DEFAULT_SITE_CHROME.home,
|
|
95
113
|
};
|
|
96
114
|
}
|
|
97
115
|
/**
|
|
@@ -106,8 +124,8 @@ export function renderSiteChrome(resolved) {
|
|
|
106
124
|
//
|
|
107
125
|
// GENERATED by create-ailk from the declared template's \`layout\` block
|
|
108
126
|
// (#5612). A scaffold with no template, or a template with no \`layout\`
|
|
109
|
-
// block, gets
|
|
110
|
-
//
|
|
127
|
+
// block, gets the defaults below (the announcement banner is off unless a
|
|
128
|
+
// template turns it on, #6469). \`apps/web/app/[locale]/layout.tsx\` reads this to decide:
|
|
111
129
|
// - nav: "mark-only" → Nav renders the brand mark + right-hand controls
|
|
112
130
|
// only (no nav links).
|
|
113
131
|
// - footer: "centered" → Footer renders its existing centered variant.
|