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
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `create-ailk license set <key|-> [dir]` — put a licence key into an existing
|
|
3
|
+
* scaffold and, when it is Vercel-linked, into production (#6683 § 3 D9).
|
|
4
|
+
*
|
|
5
|
+
* The one-liner a buyer runs is `pnpm create ailk@latest license set <key>`:
|
|
6
|
+
* `create-ailk` is the public CLI they already have (§ 1.8).
|
|
7
|
+
*
|
|
8
|
+
* 1. The target (default: cwd) must contain `architecture.yaml` — the
|
|
9
|
+
* `sync-routes` precondition — else exit 1 with nothing written.
|
|
10
|
+
* 2. `writeLicenseKeyFiles` — `ailk.key` + `apps/api/.env`, both 0600 and
|
|
11
|
+
* gitignored; the same writer `--license` uses.
|
|
12
|
+
* 3. For each of `<dir>`, `<dir>/apps/api`, `<dir>/apps/web` holding
|
|
13
|
+
* `.vercel/project.json`, with that directory as `cwd`:
|
|
14
|
+
* a. print the linked `projectId` about to change (SEC-13);
|
|
15
|
+
* b. list `ailk.key` and `.env` in its `.vercelignore` — a CLI deploy
|
|
16
|
+
* uploads the local tree, which `.gitignore` does not govern (SEC-10);
|
|
17
|
+
* c. `vercel env rm AILK_LICENSE_KEY production --yes` (failure
|
|
18
|
+
* tolerated: the variable may not exist yet);
|
|
19
|
+
* d. `vercel env add AILK_LICENSE_KEY production`, the key on STDIN;
|
|
20
|
+
* e. `vercel deploy --prod --yes`.
|
|
21
|
+
*
|
|
22
|
+
* The key is never an argv element of a spawned process and never appears in
|
|
23
|
+
* an error (SEC-11). `vercel` missing → exit 1 naming what was written and the
|
|
24
|
+
* exact manual commands; a failed `env add` after `env rm` → exit 1 saying the
|
|
25
|
+
* production variable is now UNSET, with the command that finishes the job.
|
|
26
|
+
* No Vercel link → exit 0 after the local write.
|
|
27
|
+
*
|
|
28
|
+
* Pure module (no `import.meta.url`): every effect on the outside world —
|
|
29
|
+
* output, stdin, the process runner — is injected, so jest drives it directly.
|
|
30
|
+
*/
|
|
31
|
+
import { spawnSync } from "node:child_process";
|
|
32
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
33
|
+
import { join, relative, resolve } from "node:path";
|
|
34
|
+
import { LICENSE_ENV_FILE, LICENSE_ENV_VAR, LICENSE_KEY_FILE, assertLicenseKeyShape, writeLicenseKeyFiles, } from "./lib/license-key-files.js";
|
|
35
|
+
export const LICENSE_SET_HELP = `create-ailk license set — put your licence key into an existing site.
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
pnpm create ailk@latest license set <key> [<target-dir>]
|
|
39
|
+
pnpm create ailk@latest license set - [<target-dir>] < key.txt
|
|
40
|
+
|
|
41
|
+
Arguments:
|
|
42
|
+
<key> Your licence key, or \`-\` to read it from stdin
|
|
43
|
+
(keeps it out of your shell history).
|
|
44
|
+
<target-dir> An already-scaffolded repo (contains
|
|
45
|
+
architecture.yaml). Defaults to the current dir.
|
|
46
|
+
|
|
47
|
+
Writes the key to ailk.key and apps/api/.env (owner-only, gitignored). When the
|
|
48
|
+
site (or apps/api, or apps/web) is linked to Vercel, it also replaces the
|
|
49
|
+
production AILK_LICENSE_KEY variable and redeploys.
|
|
50
|
+
`;
|
|
51
|
+
const LINK_DIRS = [".", join("apps", "api"), join("apps", "web")];
|
|
52
|
+
const VERCELIGNORE_LINES = [LICENSE_KEY_FILE, ".env"];
|
|
53
|
+
const ENV_RM = ["env", "rm", LICENSE_ENV_VAR, "production", "--yes"];
|
|
54
|
+
const ENV_ADD = ["env", "add", LICENSE_ENV_VAR, "production"];
|
|
55
|
+
const DEPLOY = ["deploy", "--prod", "--yes"];
|
|
56
|
+
/** `spawnSync`, never through a shell; stdin piped only when there is input. */
|
|
57
|
+
export const defaultRunner = (args, options) => {
|
|
58
|
+
const res = spawnSync("vercel", [...args], {
|
|
59
|
+
cwd: options.cwd,
|
|
60
|
+
shell: false,
|
|
61
|
+
stdio: [options.input !== undefined ? "pipe" : "inherit", "inherit", "inherit"],
|
|
62
|
+
...(options.input !== undefined ? { input: options.input } : {}),
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
status: res.status,
|
|
66
|
+
...(res.error !== undefined
|
|
67
|
+
? { error: res.error }
|
|
68
|
+
: {}),
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
class LicenseSetError extends Error {
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Hand-parsed rather than through `node:util` `parseArgs`: its errors quote
|
|
75
|
+
* the offending token, and the token here may be the key.
|
|
76
|
+
*/
|
|
77
|
+
function parseLicenseSetArgs(argv) {
|
|
78
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
79
|
+
return { help: true, key: undefined, target: undefined };
|
|
80
|
+
}
|
|
81
|
+
if (argv.length > 2) {
|
|
82
|
+
throw new LicenseSetError(`expected <key|-> and at most one target directory, got ${argv.length} arguments`);
|
|
83
|
+
}
|
|
84
|
+
return { help: false, key: argv[0], target: argv[1] };
|
|
85
|
+
}
|
|
86
|
+
/** Append whichever of `lines` the file does not already list. */
|
|
87
|
+
function ensureVercelIgnore(dir) {
|
|
88
|
+
const path = join(dir, ".vercelignore");
|
|
89
|
+
const text = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
90
|
+
const present = new Set(text.split("\n").map((l) => l.trim()));
|
|
91
|
+
const missing = VERCELIGNORE_LINES.filter((l) => !present.has(l) && !present.has(`/${l}`));
|
|
92
|
+
if (missing.length === 0)
|
|
93
|
+
return;
|
|
94
|
+
const sep = text.length === 0 || text.endsWith("\n") ? "" : "\n";
|
|
95
|
+
writeFileSync(path, `${text}${sep}${missing.join("\n")}\n`);
|
|
96
|
+
}
|
|
97
|
+
function readProjectId(dir) {
|
|
98
|
+
try {
|
|
99
|
+
const raw = JSON.parse(readFileSync(join(dir, ".vercel", "project.json"), "utf8"));
|
|
100
|
+
if (typeof raw.projectId === "string" && raw.projectId.length > 0) {
|
|
101
|
+
return raw.projectId;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// fall through
|
|
106
|
+
}
|
|
107
|
+
throw new LicenseSetError(`${join(dir, ".vercel", "project.json")} has no readable projectId; run \`vercel link\` there, then re-run.`);
|
|
108
|
+
}
|
|
109
|
+
/** The exact commands that finish the push by hand, from `dir`. */
|
|
110
|
+
function manualCommands(dir, keyFile, from) {
|
|
111
|
+
const keyRel = relative(dir, keyFile) || LICENSE_KEY_FILE;
|
|
112
|
+
const lines = [` cd ${dir}`];
|
|
113
|
+
if (from === "rm")
|
|
114
|
+
lines.push(` vercel ${ENV_RM.join(" ")}`);
|
|
115
|
+
lines.push(` tr -d '\\n' < ${keyRel} | vercel ${ENV_ADD.join(" ")}`);
|
|
116
|
+
lines.push(` vercel ${DEPLOY.join(" ")}`);
|
|
117
|
+
return lines.join("\n");
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Run `license set` with `argv` = everything after the `license set` words.
|
|
121
|
+
* Returns the process exit code; never throws for an expected failure.
|
|
122
|
+
*/
|
|
123
|
+
export function runLicenseSet(argv, io) {
|
|
124
|
+
const runner = io.runner ?? defaultRunner;
|
|
125
|
+
const fail = (message) => {
|
|
126
|
+
io.stderr(`[create-ailk] license set: ${message}\n`);
|
|
127
|
+
return 1;
|
|
128
|
+
};
|
|
129
|
+
let args;
|
|
130
|
+
try {
|
|
131
|
+
args = parseLicenseSetArgs(argv);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
return fail(`${err.message}\n\n${LICENSE_SET_HELP}`);
|
|
135
|
+
}
|
|
136
|
+
if (args.help) {
|
|
137
|
+
io.stdout(LICENSE_SET_HELP);
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
if (args.key === undefined) {
|
|
141
|
+
return fail(`missing <key>.\n\n${LICENSE_SET_HELP}`);
|
|
142
|
+
}
|
|
143
|
+
const key = args.key === "-" ? io.readStdin().trim() : args.key;
|
|
144
|
+
try {
|
|
145
|
+
assertLicenseKeyShape(key);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
return fail(err.message);
|
|
149
|
+
}
|
|
150
|
+
const target = resolve(io.cwd, args.target ?? ".");
|
|
151
|
+
if (!existsSync(join(target, "architecture.yaml"))) {
|
|
152
|
+
return fail(`not a scaffolded repo: no architecture.yaml at ${target}. Run it from your site's root, or pass the site's directory.`);
|
|
153
|
+
}
|
|
154
|
+
writeLicenseKeyFiles(target, key);
|
|
155
|
+
const keyFile = join(target, LICENSE_KEY_FILE);
|
|
156
|
+
const written = `Wrote ${LICENSE_KEY_FILE} and ${LICENSE_ENV_FILE.split("\\").join("/")} in ${target}`;
|
|
157
|
+
io.stdout(`[create-ailk] ${written} (owner-only, gitignored).\n`);
|
|
158
|
+
const linked = LINK_DIRS.map((d) => join(target, d)).filter((d) => existsSync(join(d, ".vercel", "project.json")));
|
|
159
|
+
if (linked.length === 0) {
|
|
160
|
+
io.stdout("[create-ailk] No Vercel link found (.vercel/project.json); nothing pushed. Set AILK_LICENSE_KEY on your host yourself if you deploy elsewhere.\n");
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
for (const dir of linked) {
|
|
164
|
+
let projectId;
|
|
165
|
+
try {
|
|
166
|
+
projectId = readProjectId(dir);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
return fail(err.message);
|
|
170
|
+
}
|
|
171
|
+
io.stdout(`[create-ailk] Updating ${LICENSE_ENV_VAR} (production) on Vercel project ${projectId}, linked at ${dir}\n`);
|
|
172
|
+
ensureVercelIgnore(dir);
|
|
173
|
+
const rm = runner(ENV_RM, { cwd: dir });
|
|
174
|
+
if (rm.error?.code === "ENOENT") {
|
|
175
|
+
return fail(`the vercel CLI was not found. ${written}; nothing was pushed. Install it (npm i -g vercel), or finish by hand:\n${manualCommands(dir, keyFile, "rm")}`);
|
|
176
|
+
}
|
|
177
|
+
// `rm` may fail because the variable never existed — tolerated — but then
|
|
178
|
+
// it removed nothing, and the message below must not say it did.
|
|
179
|
+
const removed = rm.error === undefined && rm.status === 0;
|
|
180
|
+
const add = runner(ENV_ADD, { cwd: dir, input: key });
|
|
181
|
+
if (add.error !== undefined || add.status !== 0) {
|
|
182
|
+
const state = removed
|
|
183
|
+
? `The production variable ${LICENSE_ENV_VAR} is now UNSET there (the old value was removed).`
|
|
184
|
+
: `The production variable ${LICENSE_ENV_VAR} was not changed (removing the old value also failed).`;
|
|
185
|
+
return fail(`\`vercel ${ENV_ADD.join(" ")}\` failed on project ${projectId}. ${state} Finish with:\n${manualCommands(dir, keyFile, removed ? "add" : "rm")}`);
|
|
186
|
+
}
|
|
187
|
+
const deploy = runner(DEPLOY, { cwd: dir });
|
|
188
|
+
if (deploy.error !== undefined || deploy.status !== 0) {
|
|
189
|
+
return fail(`\`vercel ${DEPLOY.join(" ")}\` failed on project ${projectId}. ${LICENSE_ENV_VAR} is set in production; redeploy with:\n cd ${dir}\n vercel ${DEPLOY.join(" ")}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
io.stdout("[create-ailk] Licence key set and production redeployed.\n");
|
|
193
|
+
return 0;
|
|
194
|
+
}
|
|
@@ -61,6 +61,14 @@ export interface PageRosterRow {
|
|
|
61
61
|
* (`/meet` renders from the scheduling API, not from an MDX file).
|
|
62
62
|
*/
|
|
63
63
|
content?: readonly string[];
|
|
64
|
+
/**
|
|
65
|
+
* Scaffold-relative seed DIRECTORY a dynamic detail row serves, e.g.
|
|
66
|
+
* `content/en/Service` under `/services/[slug]` (#6646 disposition (a)).
|
|
67
|
+
* `content` names files; a detail route whose seeds are a whole directory
|
|
68
|
+
* declares the directory instead. Every `.mdx` under it is a declared page,
|
|
69
|
+
* so it installs; a seed no row names does not.
|
|
70
|
+
*/
|
|
71
|
+
contentDir?: string;
|
|
64
72
|
}
|
|
65
73
|
/**
|
|
66
74
|
* The architecture fragment one module contributes.
|
|
@@ -144,6 +152,8 @@ export interface ModuleSlice {
|
|
|
144
152
|
* `ownedFiles` names which files in THIS monorepo physically belong to the
|
|
145
153
|
* module; `pageContributions` names which PAGES the module brings to a
|
|
146
154
|
* template's roster. `template-manifest.ts`'s `mergeRoster` reads it.
|
|
155
|
+
* A row's `contentDir` names seeds a TEMPLATE supplies, not the module:
|
|
156
|
+
* the module's bundle stages only `content` files (#6646).
|
|
147
157
|
*
|
|
148
158
|
* A contribution never carries route CODE. How the route code reaches a
|
|
149
159
|
* scaffold is a property of the module, not of the contribution (parent
|
|
@@ -399,3 +409,13 @@ export declare function normalizeModules(modules: string[]): ModuleName[];
|
|
|
399
409
|
export declare function coOwnedModuleDestinations(): ReadonlySet<string>;
|
|
400
410
|
export declare const EXCLUDE_TEMPLATE_DIRS: readonly string[];
|
|
401
411
|
export declare function paidModuleTemplateExclusions(snapshotRoots: readonly string[], repoRoot: string): string[];
|
|
412
|
+
/** The scaffold's architecture linter, relative to the site root (#6649). */
|
|
413
|
+
export declare const ARCHITECTURE_LINT_PATH = "tools/lint-architecture.ts";
|
|
414
|
+
/**
|
|
415
|
+
* What a scaffold needs so its `architecture.yaml` is enforced rather than
|
|
416
|
+
* declared (#6649): the linter, the `architecture` + `preflight` root scripts
|
|
417
|
+
* that run it, and a `.claude/settings.json` PostToolUse hook on Edit|Write
|
|
418
|
+
* that runs it in-session. Returns one line per missing piece — empty means
|
|
419
|
+
* all present. `verify-scaffold.mjs` fails on a non-empty result.
|
|
420
|
+
*/
|
|
421
|
+
export declare function missingArchitectureEnforcement(siteDir: string): string[];
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
* `architecture.yaml` template files — a fixed template IS the drift this
|
|
22
22
|
* removes.
|
|
23
23
|
*/
|
|
24
|
-
import {
|
|
24
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
25
|
+
import { join, sep } from "node:path";
|
|
25
26
|
import { importClosure } from "./lib/import-graph.js";
|
|
26
27
|
import { PAID_MODULES } from "./lib/module-tier.js";
|
|
27
28
|
import { RECOGNIZED_MODULES } from "./parse-args.js";
|
|
@@ -149,6 +150,15 @@ const ASSET_STORE_FILES = [
|
|
|
149
150
|
"apps/api/src/routes/assets/manage.ts",
|
|
150
151
|
"apps/api/src/lib/asset-store.ts",
|
|
151
152
|
];
|
|
153
|
+
/**
|
|
154
|
+
* The auth-adapter exception (#587 in the AILK repo's own architecture.yaml):
|
|
155
|
+
* the base apps/web hands Better Auth its Prisma client from
|
|
156
|
+
* `lib/prisma-for-auth.ts`, whatever modules are selected. Every slice that
|
|
157
|
+
* contributes `webImports` — and so makes apps/web's allowlist non-empty —
|
|
158
|
+
* names it, so no module set yields an allowlist the scaffold's own
|
|
159
|
+
* tools/lint-architecture.ts fails on (#6649).
|
|
160
|
+
*/
|
|
161
|
+
const WEB_AUTH_ADAPTER_IMPORT = "database";
|
|
152
162
|
/**
|
|
153
163
|
* The per-module slices. Authored for every `RECOGNIZED_MODULES` value; only
|
|
154
164
|
* `marketing` (the default) is validated end-to-end against a golden.
|
|
@@ -157,6 +167,7 @@ export const MODULE_SLICES = {
|
|
|
157
167
|
// ── marketing — thin presentation module (the default) ───────────────────
|
|
158
168
|
marketing: {
|
|
159
169
|
webImports: [
|
|
170
|
+
WEB_AUTH_ADAPTER_IMPORT,
|
|
160
171
|
"packages/content-adapters",
|
|
161
172
|
"packages/jsonld",
|
|
162
173
|
"packages/metadata",
|
|
@@ -236,7 +247,7 @@ export const MODULE_SLICES = {
|
|
|
236
247
|
},
|
|
237
248
|
// ── docs-blog — Pro module: both fumadocs surfaces (D-46) ────────────────
|
|
238
249
|
"docs-blog": {
|
|
239
|
-
webImports: ["packages/fumadocs-schema"],
|
|
250
|
+
webImports: [WEB_AUTH_ADAPTER_IMPORT, "packages/fumadocs-schema"],
|
|
240
251
|
packages: {
|
|
241
252
|
"fumadocs-schema": {
|
|
242
253
|
description: "Fumadocs ↔ schema.org bridge — BlogList / DocsPage JSON-LD from Fumadocs MDX",
|
|
@@ -376,7 +387,10 @@ export const MODULE_SLICES = {
|
|
|
376
387
|
path: ["scripts"],
|
|
377
388
|
entries: {
|
|
378
389
|
prebuild: "fumadocs-mdx",
|
|
379
|
-
pretypecheck
|
|
390
|
+
// `pretype-check`, not `pretypecheck`: pnpm runs `pre<name>`
|
|
391
|
+
// only before a script named `<name>`, and the scaffold's is
|
|
392
|
+
// `type-check` (#6680).
|
|
393
|
+
"pretype-check": "fumadocs-mdx",
|
|
380
394
|
pretest: "fumadocs-mdx",
|
|
381
395
|
},
|
|
382
396
|
},
|
|
@@ -795,7 +809,7 @@ export const MODULE_SLICES = {
|
|
|
795
809
|
// dependency under `node_modules/`, never as a `packages/admin-ui`
|
|
796
810
|
// source sibling; the `patches` entry below is what puts it in the
|
|
797
811
|
// buyer's apps/web/package.json.
|
|
798
|
-
webImports: ["packages/admin-ui"],
|
|
812
|
+
webImports: [WEB_AUTH_ADAPTER_IMPORT, "packages/admin-ui"],
|
|
799
813
|
packages: {
|
|
800
814
|
"admin-ui": {
|
|
801
815
|
description: "Shared Admin-settings components — the settings shell plus the General / Site / Team panels, presentational only (data + save callbacks as props)",
|
|
@@ -892,12 +906,9 @@ export const MODULE_SLICES = {
|
|
|
892
906
|
// all, and no scheduling value is ever published to the browser as a
|
|
893
907
|
// `NEXT_PUBLIC_` variable.
|
|
894
908
|
//
|
|
895
|
-
//
|
|
896
|
-
//
|
|
897
|
-
//
|
|
898
|
-
// `apps/` and `database/`, so `tools/` is absent. The rules are declarative
|
|
899
|
-
// there until the scaffold ships its linter; they ARE enforced in the AILK
|
|
900
|
-
// repo, whose own architecture.yaml carries the same four.
|
|
909
|
+
// A scaffolded site enforces these with its own `tools/lint-architecture.ts`
|
|
910
|
+
// (template-overlay/, #6649) via `pnpm architecture`; the AILK repo's own
|
|
911
|
+
// architecture.yaml carries the same four.
|
|
901
912
|
//
|
|
902
913
|
// The `api` block is a VERBATIM copy of multi-tenant's, deliberately. Two
|
|
903
914
|
// reasons: `deriveArchitecture` merges app blocks with `Object.assign`, so
|
|
@@ -1434,8 +1445,10 @@ export const MODULE_SLICES = {
|
|
|
1434
1445
|
{ route: "/flows/[slug]/results/[payload]" },
|
|
1435
1446
|
// #5562 — the report reader. Unlike the three rows above, this row's
|
|
1436
1447
|
// code IS this module's own `ownedFiles` (see the note beside it), so
|
|
1437
|
-
// the contribution and the delivery shape carrying it agree here.
|
|
1438
|
-
|
|
1448
|
+
// the contribution and the delivery shape carrying it agree here. Its
|
|
1449
|
+
// seeds are a directory a template supplies (minimalism-site's four
|
|
1450
|
+
// reports), so the row declares that directory (#6646).
|
|
1451
|
+
{ route: "/reports/[slug]", contentDir: "content/en/ReportPage" },
|
|
1439
1452
|
],
|
|
1440
1453
|
// installMap (#5618 D6.3) — the module's ten sample files, moved here out
|
|
1441
1454
|
// of `site-templates/marketing-site/` so the module OWNS its samples
|
|
@@ -1451,13 +1464,13 @@ export const MODULE_SLICES = {
|
|
|
1451
1464
|
//
|
|
1452
1465
|
// Four entries are real renames (the flow and waitlist seeds the API
|
|
1453
1466
|
// reads, and the report PDF under apps/web/public/); the six MDX entries
|
|
1454
|
-
// are self-addressed
|
|
1455
|
-
// `/
|
|
1456
|
-
//
|
|
1457
|
-
//
|
|
1458
|
-
// the
|
|
1459
|
-
//
|
|
1460
|
-
//
|
|
1467
|
+
// are self-addressed. Their `/projects`, `/projects/[slug]` and
|
|
1468
|
+
// `/thanks/[slug]` rows are declared by the templates that install them
|
|
1469
|
+
// (`template-manifest.ts`'s signal-collectors sample rows, #6646), not
|
|
1470
|
+
// here — a module contribution would change the enabled-surface set and
|
|
1471
|
+
// so the Pro scaffold's file set (spec 5618 § 7 finding 7).
|
|
1472
|
+
// `generate-sample-report.py` keeps its root-level destination
|
|
1473
|
+
// (finding 1 — AC7 forbids changing the Pro file set).
|
|
1461
1474
|
installMap: {
|
|
1462
1475
|
"packages/create-ailk/module-templates/signal-collectors/content/en/ProjectsList/projects.mdx": "content/en/ProjectsList/projects.mdx",
|
|
1463
1476
|
"packages/create-ailk/module-templates/signal-collectors/content/en/Project/fit-check-funnel.mdx": "content/en/Project/fit-check-funnel.mdx",
|
|
@@ -1801,3 +1814,48 @@ export function paidModuleTemplateExclusions(snapshotRoots, repoRoot) {
|
|
|
1801
1814
|
// question with the same resolution this answer was computed with (#5701).
|
|
1802
1815
|
return [...importClosure(repoRoot, [...roots], seeds)].sort();
|
|
1803
1816
|
}
|
|
1817
|
+
/** The scaffold's architecture linter, relative to the site root (#6649). */
|
|
1818
|
+
export const ARCHITECTURE_LINT_PATH = "tools/lint-architecture.ts";
|
|
1819
|
+
/**
|
|
1820
|
+
* What a scaffold needs so its `architecture.yaml` is enforced rather than
|
|
1821
|
+
* declared (#6649): the linter, the `architecture` + `preflight` root scripts
|
|
1822
|
+
* that run it, and a `.claude/settings.json` PostToolUse hook on Edit|Write
|
|
1823
|
+
* that runs it in-session. Returns one line per missing piece — empty means
|
|
1824
|
+
* all present. `verify-scaffold.mjs` fails on a non-empty result.
|
|
1825
|
+
*/
|
|
1826
|
+
export function missingArchitectureEnforcement(siteDir) {
|
|
1827
|
+
const missing = [];
|
|
1828
|
+
if (!existsSync(join(siteDir, ARCHITECTURE_LINT_PATH))) {
|
|
1829
|
+
missing.push(ARCHITECTURE_LINT_PATH);
|
|
1830
|
+
}
|
|
1831
|
+
const readJson = (rel) => {
|
|
1832
|
+
const p = join(siteDir, rel);
|
|
1833
|
+
if (!existsSync(p))
|
|
1834
|
+
return undefined;
|
|
1835
|
+
try {
|
|
1836
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
1837
|
+
}
|
|
1838
|
+
catch {
|
|
1839
|
+
return undefined;
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
const scripts = readJson("package.json")
|
|
1843
|
+
?.scripts ?? {};
|
|
1844
|
+
if (!scripts.architecture?.includes(ARCHITECTURE_LINT_PATH)) {
|
|
1845
|
+
missing.push(`package.json scripts.architecture (runs ${ARCHITECTURE_LINT_PATH})`);
|
|
1846
|
+
}
|
|
1847
|
+
if (!scripts.preflight?.includes("pnpm architecture")) {
|
|
1848
|
+
missing.push("package.json scripts.preflight (runs pnpm architecture)");
|
|
1849
|
+
}
|
|
1850
|
+
const postToolUse = readJson(".claude/settings.json")?.hooks?.PostToolUse ?? [];
|
|
1851
|
+
const hooked = postToolUse.some((entry) => {
|
|
1852
|
+
const tools = (entry.matcher ?? "").split("|");
|
|
1853
|
+
return (tools.includes("Edit") &&
|
|
1854
|
+
tools.includes("Write") &&
|
|
1855
|
+
(entry.hooks ?? []).some((h) => /\bpnpm\b.*\barchitecture\b/.test(h.command ?? "")));
|
|
1856
|
+
});
|
|
1857
|
+
if (!hooked) {
|
|
1858
|
+
missing.push(".claude/settings.json PostToolUse hook on Edit|Write (runs pnpm architecture)");
|
|
1859
|
+
}
|
|
1860
|
+
return missing;
|
|
1861
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/parse-args.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ScaffoldOptions } from "./programmatic.js";
|
|
1
2
|
/**
|
|
2
3
|
* The recognized module vocabulary for the `--modules` selector.
|
|
3
4
|
*
|
|
@@ -9,23 +10,52 @@
|
|
|
9
10
|
*/
|
|
10
11
|
export declare const RECOGNIZED_MODULES: readonly ["marketing", "docs-blog", "multi-tenant", "workspace", "scheduling", "signal-collectors", "commerce"];
|
|
11
12
|
export type ModuleName = (typeof RECOGNIZED_MODULES)[number];
|
|
13
|
+
/**
|
|
14
|
+
* Shapes a starter can be built from today (`--shape`, #6754 D1).
|
|
15
|
+
*
|
|
16
|
+
* Declared HERE rather than imported from `template-manifest.ts` for the
|
|
17
|
+
* reason `RECOGNIZED_MODULES` is: importing the registry closes the runtime
|
|
18
|
+
* cycle `template-names.ts`'s header records. `parse-args.test.ts` pins this
|
|
19
|
+
* list, `RESERVED_SHAPES` and `RECOGNIZED_DESIGNS` to their authorities
|
|
20
|
+
* (`STARTER_SHAPES`, `STARTER_DESIGNS`, `SHAPE_ROSTERS`).
|
|
21
|
+
*/
|
|
22
|
+
export declare const RECOGNIZED_SHAPES: readonly ["organization-product", "organization-service", "local-business-service", "person-service"];
|
|
23
|
+
export type ShapeName = (typeof RECOGNIZED_SHAPES)[number];
|
|
24
|
+
/** Shapes the contract names but no release builds yet. */
|
|
25
|
+
export declare const RESERVED_SHAPES: readonly ["local-business-product"];
|
|
26
|
+
/** The `--design` vocabulary (#6754 D1) — `STARTER_DESIGNS`, pinned by test. */
|
|
27
|
+
export declare const RECOGNIZED_DESIGNS: readonly ["standard", "minimalism"];
|
|
28
|
+
export type DesignName = (typeof RECOGNIZED_DESIGNS)[number];
|
|
12
29
|
export interface CliOptions {
|
|
13
30
|
/** Positional target directory (the dir to scaffold into). Optional only
|
|
14
31
|
* when `help` or `version` is set. */
|
|
15
32
|
target: string | undefined;
|
|
16
33
|
/**
|
|
17
34
|
* The site template to install (`--template`), validated against
|
|
18
|
-
* `RECOGNIZED_TEMPLATES` at parse time. Undefined when the flag is absent
|
|
19
|
-
*
|
|
20
|
-
*
|
|
35
|
+
* `RECOGNIZED_TEMPLATES` at parse time. Undefined when the flag is absent.
|
|
36
|
+
* The CLI never scaffolds a run naming neither a template nor a shape
|
|
37
|
+
* (#6754 D2 — refusal R1, or the shape prompt on a terminal).
|
|
21
38
|
*/
|
|
22
39
|
template: string | undefined;
|
|
40
|
+
/** The starter's shape (`--shape`, #6754), normalized. Never set with `template`. */
|
|
41
|
+
shape?: ShapeName;
|
|
42
|
+
/** The starter's design (`--design`, #6754). Never set with `template`. */
|
|
43
|
+
design?: DesignName;
|
|
44
|
+
/**
|
|
45
|
+
* True when a scaffold run named neither `--shape` nor `--template` on a
|
|
46
|
+
* terminal: `resolveCliShape` must ask before anything is scaffolded.
|
|
47
|
+
*/
|
|
48
|
+
needsShapePrompt: boolean;
|
|
23
49
|
install: boolean;
|
|
24
50
|
help: boolean;
|
|
25
51
|
version: boolean;
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Selected modules (recognized: marketing, docs-blog, multi-tenant,
|
|
54
|
+
* scheduling). `undefined` when `--modules` is absent — the key's level
|
|
55
|
+
* decides (#6759 D3); never read as `['marketing']` here. An empty or
|
|
56
|
+
* all-empty `--modules` value still names the Free set (`parseModules`).
|
|
57
|
+
*/
|
|
58
|
+
modules: string[] | undefined;
|
|
29
59
|
/** Explicitly requested route surfaces (`--surfaces`). Empty when the flag is
|
|
30
60
|
* absent — the module set alone then decides (see surfaces.ts
|
|
31
61
|
* `resolveSurfaces`). Validated, lowercased, deduped and sorted. */
|
|
@@ -47,20 +77,65 @@ export interface CliOptions {
|
|
|
47
77
|
* value is validated through `parseModules` at parse time; cli.ts re-parses
|
|
48
78
|
* it to the module list. Undefined when the flag is absent (scaffold mode). */
|
|
49
79
|
syncArchitecture: string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* The licence key (`--license <key>`, #6683 D9), shape-checked at parse
|
|
82
|
+
* time. When set, `scaffold()` fetches paid bundles with it and writes it
|
|
83
|
+
* into the new scaffold (`ailk.key` + `apps/api/.env`). Absent when the
|
|
84
|
+
* flag is.
|
|
85
|
+
*/
|
|
86
|
+
license?: string;
|
|
50
87
|
}
|
|
51
88
|
export declare class ParseError extends Error {
|
|
52
89
|
constructor(message: string);
|
|
53
90
|
}
|
|
91
|
+
/** The caller's terminal state (#6754 D2). */
|
|
92
|
+
export interface ParseEnv {
|
|
93
|
+
/** A human can answer a prompt: `process.stdin.isTTY === true` in cli.ts. */
|
|
94
|
+
interactive: boolean;
|
|
95
|
+
}
|
|
54
96
|
export declare const helpText: string;
|
|
55
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Parse `create-ailk` argv. `env.interactive` defaults to false —
|
|
99
|
+
* fail-closed: a caller that does not assert a human is present gets refusal
|
|
100
|
+
* R1, never a prompt it cannot answer (#6754 D2).
|
|
101
|
+
*/
|
|
102
|
+
export declare function parseCliArgs(argv: string[], env?: ParseEnv): CliOptions;
|
|
103
|
+
/** The streams the shape prompt reads and writes (a `PassThrough` pair in tests). */
|
|
104
|
+
export interface PromptIo {
|
|
105
|
+
input: NodeJS.ReadableStream;
|
|
106
|
+
output: NodeJS.WritableStream;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ask once for a shape (#6754 D3): a number 1–4 or a shape name. A bad answer
|
|
110
|
+
* re-asks, naming what was wrong; the third bad answer, or a closed input,
|
|
111
|
+
* throws. There is no default — an empty line is a bad answer.
|
|
112
|
+
*/
|
|
113
|
+
export declare function promptForShape(io: PromptIo): Promise<ShapeName>;
|
|
114
|
+
/**
|
|
115
|
+
* Fill `opts.shape` by prompting when, and only when, `needsShapePrompt` is
|
|
116
|
+
* set (#6754 D3). Help, version, sync and every run naming a shape or a
|
|
117
|
+
* template come back unchanged, with nothing written to `io.output`.
|
|
118
|
+
*/
|
|
119
|
+
export declare function resolveCliShape(opts: CliOptions, io: PromptIo): Promise<CliOptions>;
|
|
120
|
+
/**
|
|
121
|
+
* The one mapping from parsed flags to `scaffold()` options (#6754 D4).
|
|
122
|
+
* `template`, `shape`, `design` and `license` are each spread only when set,
|
|
123
|
+
* so a `--template` run hands `scaffold()` the object it did before #6754.
|
|
124
|
+
*
|
|
125
|
+
* @throws ParseError when the shape prompt is unresolved or the target is
|
|
126
|
+
* unset — an unresolved prompt must never fall through to the bare overlay.
|
|
127
|
+
*/
|
|
128
|
+
export declare function toScaffoldOptions(opts: CliOptions): ScaffoldOptions;
|
|
56
129
|
/**
|
|
57
130
|
* Parse a module CSV (the `--modules` or `--sync-architecture` value) into a
|
|
58
131
|
* validated, normalized string[].
|
|
59
132
|
*
|
|
60
133
|
* Splits on `,`, trims and lowercases each entry, drops empties, and validates
|
|
61
|
-
* each against RECOGNIZED_MODULES.
|
|
62
|
-
*
|
|
134
|
+
* each against RECOGNIZED_MODULES. Takes a PRESENT value only — an ABSENT
|
|
135
|
+
* `--modules` flag is `undefined` (#6759 D3: the key's level decides) and
|
|
136
|
+
* never reaches this function; an all-empty value (`--modules ""`,
|
|
137
|
+
* `--modules ,`) still names the Free set, spelled inline here.
|
|
63
138
|
*
|
|
64
139
|
* @throws ParseError on an unrecognized module value, naming the recognized set.
|
|
65
140
|
*/
|
|
66
|
-
export declare function parseModules(raw: string
|
|
141
|
+
export declare function parseModules(raw: string): string[];
|