create-ailk 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -10
- package/component-catalog.json +798 -49
- package/component-catalog.md +9 -6
- package/dist/add-module.d.ts +20 -0
- package/dist/add-module.js +43 -7
- package/dist/add-route.d.ts +56 -0
- package/dist/add-route.js +286 -0
- package/dist/apply-design-md.d.ts +7 -0
- package/dist/apply-design-md.js +50 -0
- package/dist/apply-design.d.ts +64 -0
- package/dist/apply-design.js +273 -0
- package/dist/claude-md.d.ts +111 -0
- package/dist/claude-md.js +334 -0
- package/dist/cli.js +114 -28
- package/dist/derive-architecture.js +41 -36
- package/dist/design-compile.d.ts +71 -0
- package/dist/design-compile.js +98 -0
- package/dist/design-package.d.ts +83 -0
- package/dist/design-package.js +468 -0
- package/dist/design-presets.d.ts +86 -0
- package/dist/design-presets.js +642 -0
- package/dist/design-scaffold.d.ts +76 -0
- package/dist/design-scaffold.js +220 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/legacy-nav-renderers.d.ts +45 -0
- package/dist/legacy-nav-renderers.js +545 -0
- package/dist/lib/auth-secret-file.d.ts +19 -0
- package/dist/lib/auth-secret-file.js +112 -0
- package/dist/lib/design-checks.d.ts +78 -0
- package/dist/lib/design-checks.js +174 -0
- package/dist/lib/extract-module-bundle.js +5 -1
- package/dist/lib/license-key-files.d.ts +9 -0
- package/dist/lib/license-key-files.js +2 -2
- package/dist/lib/module-license-gate.d.ts +89 -0
- package/dist/lib/module-license-gate.js +171 -12
- package/dist/lib/module-tier.d.ts +45 -16
- package/dist/lib/module-tier.js +76 -0
- package/dist/lib/pro-callout.js +10 -2
- package/dist/lib/render-verdict.d.ts +52 -0
- package/dist/lib/render-verdict.js +77 -0
- package/dist/lib/scaffold-render-sweep.d.ts +105 -0
- package/dist/lib/scaffold-render-sweep.js +236 -0
- package/dist/module-architecture.d.ts +19 -16
- package/dist/module-architecture.js +64 -21
- package/dist/parse-args.d.ts +88 -10
- package/dist/parse-args.js +272 -21
- package/dist/programmatic.d.ts +66 -12
- package/dist/programmatic.js +361 -34
- package/dist/site-chrome.d.ts +19 -9
- package/dist/site-chrome.js +23 -13
- package/dist/site-manifest.d.ts +25 -0
- package/dist/site-manifest.js +254 -0
- package/dist/site-roster.d.ts +41 -0
- package/dist/site-roster.js +149 -11
- package/dist/starter-grid.d.ts +232 -0
- package/dist/starter-grid.js +545 -0
- package/dist/surfaces.d.ts +41 -9
- package/dist/surfaces.js +268 -92
- package/dist/template-manifest.d.ts +65 -29
- package/dist/template-manifest.js +161 -382
- package/dist/template-names.d.ts +14 -12
- package/dist/template-names.js +13 -17
- package/package.json +5 -4
- 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 +0 -1
- package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +0 -1
- 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/PrivacyPage/privacy.mdx +15 -0
- package/site-templates/_base/content/en/UseCase/persona-1.mdx +70 -0
- package/site-templates/_base/content/en/UseCase/persona-2.mdx +70 -0
- package/site-templates/_base/content/en/UseCase/persona-3.mdx +70 -0
- package/site-templates/{minimalism-site/TEMPLATE-MANIFEST.json → aliases/minimalism-site.TEMPLATE-MANIFEST.json} +72 -40
- package/site-templates/designs/minimalism/DESIGN.md +98 -6
- package/site-templates/designs/minimalism/sample/README.md +48 -0
- package/site-templates/designs/standard/DESIGN.md +103 -6
- package/site-templates/marketing-site/DESIGN.md +103 -6
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +144 -47
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +82 -41
- package/site-templates/marketing-site-free/DESIGN.md +103 -6
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +150 -48
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +114 -67
- package/site-templates/marketing-site-free/ailk-template.json +1 -1
- 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/saas-product/DESIGN.md +103 -6
- package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
- package/site-templates/{simple-service → shapes/local-business-service}/TEMPLATE-MANIFEST.json +210 -81
- package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +356 -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/{minimalism-site → shapes/local-business-service}/content/en/PurchasePolicyPage/purchase-policy.mdx +7 -8
- 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 +471 -0
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +354 -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/{minimalism-site → shapes/organization-service}/content/en/ServicesList/services.mdx +3 -4
- package/site-templates/shapes/organization-service/provenance.json +4 -0
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +478 -0
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +353 -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 +171 -0
- package/site-templates/{simple-service → shapes/person-service}/content/en/PurchasePolicyPage/purchase-policy.mdx +10 -11
- 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/rules/architecture.md +7 -0
- package/templates/.claude/skills/README.md +5 -3
- package/templates/.claude/skills/add-auth/references/env-vars.md +22 -15
- package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +3 -2
- package/templates/.claude/skills/add-page/SKILL.md +241 -238
- package/templates/.claude/skills/add-page/references/page-types.md +85 -72
- package/templates/.claude/skills/add-page/scripts/site-pages.mjs +87 -0
- package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +99 -0
- package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +8 -18
- package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +43 -0
- package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +52 -0
- package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +38 -0
- package/templates/.claude/skills/check-site/SKILL.md +23 -0
- package/templates/.claude/skills/fill-page/SKILL.md +26 -7
- package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +1 -1
- 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/setup-deploy/SKILL.md +64 -32
- package/templates/.claude/skills/setup-deploy/references/env-vars-template.md +44 -36
- package/templates/.claude/skills/setup-deploy/references/runbook-template.md +58 -102
- package/templates/.claude/skills/update-page/SKILL.md +117 -0
- package/templates/.claude/skills/update-page/scripts/update-page.ts +640 -0
- package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +31 -0
- package/templates/.claude/skills/upgrade-plan/SKILL.md +12 -8
- package/templates/.github/workflows/ci.yml +4 -0
- package/templates/.prettierignore +1 -0
- package/templates/CLAUDE.md +146 -103
- package/templates/DESIGN.md +103 -6
- package/templates/README.md +63 -43
- package/templates/apps/api/.env.example +2 -1
- package/templates/apps/api/CLAUDE.md +3 -2
- package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +2 -0
- package/templates/apps/api/src/__tests__/server.test.ts +116 -0
- package/templates/apps/api/src/config/__tests__/index.test.ts +115 -14
- package/templates/apps/api/src/config/index.ts +35 -16
- 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/stripe.ts +9 -0
- package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +140 -0
- package/templates/apps/api/src/middleware/auth.ts +54 -0
- package/templates/apps/api/src/openapi/spec.ts +63 -12
- package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +5 -2
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +628 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +222 -24
- 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/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +1 -1
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +5 -1
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +521 -20
- package/templates/apps/api/src/routes/webhooks/stripe.ts +124 -32
- package/templates/apps/api/src/server.ts +35 -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/__tests__/revalidation.test.ts +90 -15
- package/templates/apps/api/src/services/checkout-buyer.ts +72 -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/api/src/services/revalidation.ts +60 -15
- package/templates/apps/mcp/__tests__/parity.test.ts +5 -4
- package/templates/apps/mcp/__tests__/tools/create_project.test.ts +30 -24
- package/templates/apps/mcp/src/tools/create_project.ts +21 -6
- package/templates/apps/mcp/src/tools/purchase.ts +4 -2
- package/templates/apps/web/.env.example +13 -0
- package/templates/apps/web/CLAUDE.md +22 -28
- package/templates/apps/web/app/[locale]/(auth)/layout.tsx +1 -1
- package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +24 -0
- package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +17 -6
- package/templates/apps/web/app/[locale]/[slug]/[detail]/__tests__/page.test.tsx +110 -0
- package/templates/apps/web/app/[locale]/[slug]/[detail]/page.tsx +60 -0
- package/templates/apps/web/app/[locale]/[slug]/page.tsx +1 -1
- package/templates/apps/web/app/[locale]/alternatives/__tests__/page.test.tsx +161 -0
- package/templates/apps/web/app/[locale]/alternatives/page.tsx +104 -0
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +14 -6
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +10 -9
- 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 +227 -84
- 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 +105 -15
- package/templates/apps/web/app/[locale]/contact/site-contact-email.ts +54 -0
- 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]/{use-cases → for}/[slug]/page.tsx +21 -5
- package/templates/apps/web/app/[locale]/for/__tests__/page-renderer-migration.test.tsx +73 -0
- package/templates/apps/web/app/[locale]/{use-cases → for}/page.tsx +8 -7
- package/templates/apps/web/app/[locale]/glossary/page.tsx +1 -1
- package/templates/apps/web/app/[locale]/layout.tsx +65 -17
- 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 +106 -14
- package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +59 -0
- package/templates/apps/web/app/[locale]/{book-a-call → portfolio}/page.tsx +12 -13
- package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +112 -0
- package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +70 -0
- package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +236 -44
- package/templates/apps/web/app/api/revalidate/route.ts +78 -36
- package/templates/apps/web/lib/__tests__/site-brand.test.ts +79 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +104 -11
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +21 -4
- package/templates/apps/web/lib/locale-guard.ts +18 -0
- package/templates/apps/web/lib/meet-placeholder.ts +5 -0
- package/templates/apps/web/lib/nav-config.ts +50 -37
- package/templates/apps/web/lib/site-brand.tsx +13 -9
- package/templates/apps/web/lib/site-identity.ts +14 -0
- package/templates/apps/web/lib/site-logo.tsx +36 -0
- package/templates/apps/web/lib/site-theme.ts +46 -26
- package/templates/apps/web/messages/en.json +45 -5
- package/templates/apps/web/middleware.ts +28 -4
- package/templates/content/_site.mdx +4 -2
- package/templates/content/en/BlogList/blog.mdx +37 -16
- package/templates/content/en/BookCall/book-a-call.mdx +80 -0
- package/templates/content/en/BookCall/onsite-estimate.mdx +56 -0
- package/templates/content/en/BookCall/onsite-service.mdx +56 -0
- package/templates/content/en/BookCall/start-project.mdx +56 -0
- package/templates/content/en/ContactPage/contact.mdx +43 -34
- package/templates/content/en/HomePage/home.mdx +10 -22
- package/templates/content/en/LandingPage/meet.mdx +59 -0
- package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +0 -1
- package/templates/content/en/UseCasesList/{use-cases.mdx → for.mdx} +19 -18
- package/templates/database/CHANGELOG.md +14 -0
- package/templates/database/package.json +1 -1
- package/templates/package.json +2 -1
- package/templates/tools/check-claude-md.ts +128 -0
- package/versions.json +33 -33
- package/site-templates/_base/content/en/BookCall/book-call.mdx +0 -53
- package/site-templates/_base/content/en/UseCase/first-use-case.mdx +0 -23
- package/site-templates/_base/content/en/UseCase/second-use-case.mdx +0 -23
- package/site-templates/_base/content/en/UseCase/third-use-case.mdx +0 -23
- package/site-templates/minimalism-site/DESIGN.md +0 -162
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +0 -470
- package/site-templates/minimalism-site/ailk-template.json +0 -23
- package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +0 -110
- package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +0 -53
- package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +0 -34
- package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +0 -57
- package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +0 -77
- package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +0 -73
- package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +0 -52
- package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +0 -52
- package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +0 -52
- package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +0 -52
- package/site-templates/minimalism-site/flows/referral.flow.json +0 -71
- package/site-templates/minimalism-site/provenance.json +0 -4
- package/site-templates/simple-service/DESIGN.md +0 -162
- package/site-templates/simple-service/TEMPLATE-MANIFEST.md +0 -333
- package/site-templates/simple-service/ailk-template.json +0 -11
- package/site-templates/simple-service/content/en/BookCall/book-call.mdx +0 -53
- package/site-templates/simple-service/content/en/ContactPage/contact.mdx +0 -32
- 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-page/templates/route.tsx.tmpl +0 -28
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +0 -211
- package/templates/apps/web/app/[locale]/contact/__tests__/ContactForm.test.tsx +0 -96
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +0 -72
- package/templates/content/en/SoftwareProduct/product.mdx +0 -175
- /package/site-templates/{minimalism-site → designs/minimalism/sample}/content/en/HomePage/home.mdx +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-1.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-2.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-3.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-4.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-5.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-6.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/hero-backdrop.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-1.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-2.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-3.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/wordmark-placeholder.svg +0 -0
- /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/first-engagement.mdx +0 -0
- /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/second-engagement.mdx +0 -0
- /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/third-engagement.mdx +0 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two pages every starter carries whatever its shape (#6658 D5,
|
|
3
|
+
* `docs/decisions/starter-roster-page-set.md` D4/D7): a glossary and a
|
|
4
|
+
* newsletter signup. Each is a module-less `GATEABLE_SURFACES` entry the
|
|
5
|
+
* roster enables, with its seed in `_base`.
|
|
6
|
+
*
|
|
7
|
+
* The third — `/book-a-call` — was retired by #6897 D10: every scaffold's
|
|
8
|
+
* former `/book-a-call` link now points at `/meet/book-a-call`, served by
|
|
9
|
+
* `FREE_MEET_PLACEHOLDER_ROWS` below (a Free placeholder) or by the
|
|
10
|
+
* scheduling module's own live `/meet/[slug]` page.
|
|
11
|
+
*/
|
|
12
|
+
const SHAPE_INDEPENDENT_ROWS = [
|
|
13
|
+
{ route: "/glossary", content: ["content/en/GlossaryList/glossary.mdx"] },
|
|
14
|
+
{
|
|
15
|
+
route: "/newsletter",
|
|
16
|
+
content: ["content/en/NewsletterSignup/newsletter.mdx"],
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* The Free `/meet` placeholder pages (#6897 D5) — a meeting-types hub
|
|
21
|
+
* (`LandingPage`, served by the generic `[slug]` route) and its four
|
|
22
|
+
* `BookCall` detail seeds (served by the `[slug]/[detail]` route, D2). Both
|
|
23
|
+
* ship in the always-copied overlay, beside `FREE_BLOG_TEASER_ROW`, so a
|
|
24
|
+
* template-less scaffold's Contact tiles (which link `/meet/*` too) reach
|
|
25
|
+
* real pages. The second row uses an explicit `content` list, not
|
|
26
|
+
* `contentDir`, because only a `content`-list row is removed by
|
|
27
|
+
* `planRosterAppend`'s add-module supersede (F4's add-module half,
|
|
28
|
+
* `site-roster.ts`).
|
|
29
|
+
*
|
|
30
|
+
* Every alias that takes the `scheduling` module drops `"/meet"` and
|
|
31
|
+
* `"/meet/[slug]"` (D5) — otherwise `mergeRoster` refuses the duplicate
|
|
32
|
+
* route the module's own rows also contribute. The ROWS go; the SEEDS stay
|
|
33
|
+
* (#6942, operator 2026-09-28, partly reversing D5): until
|
|
34
|
+
* `SCHEDULING_CAL_LINK` is configured the module's pages hand off to the Free
|
|
35
|
+
* placeholder routes, which serve these seeds. `withMeetPlaceholderSeeds`
|
|
36
|
+
* (`site-roster.ts`) folds them onto the module's rows.
|
|
37
|
+
*/
|
|
38
|
+
const FREE_MEET_PLACEHOLDER_ROWS = [
|
|
39
|
+
{ route: "/meet", content: ["content/en/LandingPage/meet.mdx"] },
|
|
40
|
+
{
|
|
41
|
+
route: "/meet/[slug]",
|
|
42
|
+
content: [
|
|
43
|
+
"content/en/BookCall/book-a-call.mdx",
|
|
44
|
+
"content/en/BookCall/onsite-estimate.mdx",
|
|
45
|
+
"content/en/BookCall/start-project.mdx",
|
|
46
|
+
"content/en/BookCall/onsite-service.mdx",
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* The rows every `organization-product` template brings itself — one declared
|
|
52
|
+
* page set, whichever layer carries each seed. Re-derived by #6658 from the
|
|
53
|
+
* standard (`derive-roster.py --entity-type software --offering-type software
|
|
54
|
+
* --primary-goal convert --scale global`, the `--shape organization-product`
|
|
55
|
+
* equivalent), edited only by the deviations the Free manifest's § 3a records
|
|
56
|
+
* with their reasons. With a template named, `scaffold()` keeps a `_base` or
|
|
57
|
+
* overlay seed only when a merged roster row names it (#6646 D1): the roster
|
|
58
|
+
* decides what installs, and the manifest generator's `--check` proves it.
|
|
59
|
+
*
|
|
60
|
+
* Two layers, one roster:
|
|
61
|
+
*
|
|
62
|
+
* - `/`, `/software/[slug]`, `/for`, `/about`, `/faq`, `/contact` and
|
|
63
|
+
* `/purchase-policy` take their content from the overlay
|
|
64
|
+
* (`template-overlay/content/en/**`, copied whole into `templates/` by
|
|
65
|
+
* `build-templates.mjs`). `/features` is the FeaturesList hub over one
|
|
66
|
+
* Feature page per feature at `/features/[slug]` (#6721, reversing the
|
|
67
|
+
* single `/software/product` page of #6658 D3); both ride the `features`
|
|
68
|
+
* surface the roster enables.
|
|
69
|
+
* `/for` lists the three UseCase pages at `/for/[slug]`
|
|
70
|
+
* (#6658 D4).
|
|
71
|
+
* - `/pricing`, `/privacy`, `/terms`, `/glossary`, `/newsletter`,
|
|
72
|
+
* and the three UseCase pages take their content from the
|
|
73
|
+
* base layer (`site-templates/_base/content/**`, #5618 D1), which every
|
|
74
|
+
* template reaches by declaring `extends` — installed before the module
|
|
75
|
+
* bundles and the template's own tree, so a template may override a base
|
|
76
|
+
* page by shipping the same path. Their surfaces are module-less by
|
|
77
|
+
* construction (parent § D16, #6658 D5): a template enables them by
|
|
78
|
+
* NAMING them in its roster — `scaffold()` selects their
|
|
79
|
+
* `GATEABLE_SURFACES` entries from the merged roster's routes (#5469 D10).
|
|
80
|
+
*
|
|
81
|
+
* `/software`, `/sign-in` and `/sign-up` carry no `content`: they are code
|
|
82
|
+
* routes (the SoftwareProduct listing, the SignInCard island, the sign-up
|
|
83
|
+
* form), like the API-backed rows the scheduling module contributes — listed
|
|
84
|
+
* so the manifest is a complete install record, where the generator marks
|
|
85
|
+
* them `kind: route` (#6646 D2).
|
|
86
|
+
*
|
|
87
|
+
* `/purchase-policy` is the product-shape purchase policy (#6646 D3): its
|
|
88
|
+
* overlay seed carries returns, shipping and refunds sections — the overlay,
|
|
89
|
+
* not `_base`, because the route is core and a scaffold naming no template
|
|
90
|
+
* serves it too. A service-shape template overrides that seed with its own
|
|
91
|
+
* cancellation and refunds file.
|
|
92
|
+
*
|
|
93
|
+
* `/blog` is deliberately NOT here (#5469 D3): the docs-blog module
|
|
94
|
+
* contributes its own `/blog` row, so a base row would make `mergeRoster`
|
|
95
|
+
* refuse every template that takes that module. The teaser row is an
|
|
96
|
+
* `organization-product` shape row instead (#6753 D3), which the two aliases
|
|
97
|
+
* taking docs-blog drop.
|
|
98
|
+
*/
|
|
99
|
+
const TEMPLATE_BASE_ROSTER = [
|
|
100
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
101
|
+
// #6721 — the product's features: a FeaturesList hub over one Feature page
|
|
102
|
+
// per feature (replaces the single /software/product page, #6658 D3).
|
|
103
|
+
{ route: "/features", content: ["content/en/FeaturesList/features.mdx"] },
|
|
104
|
+
{ route: "/features/[slug]", contentDir: "content/en/Feature" },
|
|
105
|
+
{
|
|
106
|
+
// #6878 D7 — the persona hub, renamed from /use-cases.
|
|
107
|
+
route: "/for",
|
|
108
|
+
content: ["content/en/UseCasesList/for.mdx"],
|
|
109
|
+
},
|
|
110
|
+
{ route: "/for/[slug]", contentDir: "content/en/UseCase" },
|
|
111
|
+
{ route: "/pricing", content: ["content/en/Pricing/pricing.mdx"] },
|
|
112
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
113
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
114
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
115
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
116
|
+
{ route: "/sign-in" },
|
|
117
|
+
{ route: "/sign-up" },
|
|
118
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
119
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
120
|
+
{
|
|
121
|
+
route: "/purchase-policy",
|
|
122
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
/**
|
|
126
|
+
* The Free `/blog` teaser (#5469 D3) — one static BlogList page (schema `Blog`
|
|
127
|
+
* with an empty `ItemList`; the correct page type, not a LandingPage) that
|
|
128
|
+
* says what the Pro docs-blog module gives you. It is served by the generic
|
|
129
|
+
* `[slug]` route — which probes `LandingPage` first, then `BlogList` — over
|
|
130
|
+
* `content/en/BlogList/blog.mdx`, which ships in the always-copied overlay. `/blog` degrades by DIRECTORY PRECEDENCE, not
|
|
131
|
+
* by a module gate: in a keyed docs-blog scaffold the module's own
|
|
132
|
+
* `blog/[[...slug]]/page.tsx` directory exists and Next.js resolves the static
|
|
133
|
+
* segment first, so the teaser file is inert; keyless, no `blog/` directory
|
|
134
|
+
* exists and the teaser renders. An `organization-product` shape row
|
|
135
|
+
* (#6753 D3): the aliases taking docs-blog drop it, so on `marketing-site`
|
|
136
|
+
* the docs-blog contribution claims the route.
|
|
137
|
+
*/
|
|
138
|
+
const FREE_BLOG_TEASER_ROW = {
|
|
139
|
+
route: "/blog",
|
|
140
|
+
content: ["content/en/BlogList/blog.mdx"],
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* The rows for the `signal-collectors` bundle's six sample pages (#6646
|
|
144
|
+
* disposition (a)) — the project listing, its two project pages and the
|
|
145
|
+
* three thank-you pages its `installMap` lands. The module contributes no
|
|
146
|
+
* row for any of these routes (`module-architecture.ts`'s installMap
|
|
147
|
+
* comment), so a template that takes the module declares them, and the
|
|
148
|
+
* roster names every page the scaffold installs. `/projects` is a
|
|
149
|
+
* module-less `GATEABLE_SURFACES` entry, so naming it here also copies the
|
|
150
|
+
* route directory the samples render through (`rosterSurfaces`).
|
|
151
|
+
*/
|
|
152
|
+
const SIGNAL_COLLECTORS_SAMPLE_ROWS = [
|
|
153
|
+
{ route: "/projects", content: ["content/en/ProjectsList/projects.mdx"] },
|
|
154
|
+
{ route: "/projects/[slug]", contentDir: "content/en/Project" },
|
|
155
|
+
{ route: "/thanks/[slug]", contentDir: "content/en/ThankYouPage" },
|
|
156
|
+
];
|
|
157
|
+
/**
|
|
158
|
+
* The portfolio pages (#6687) — before/after project comparisons: a
|
|
159
|
+
* PortfolioList hub on the /alternatives stack and one PortfolioItem page per
|
|
160
|
+
* comparison, each one `before-after` section carrying its header band and
|
|
161
|
+
* pager. They belong to the SHAPE, Free included (roadmap § 4, operator
|
|
162
|
+
* 2026-09-25, reversing #6687's "Pro and up"): every shape roster below
|
|
163
|
+
* carries them, and an alias sheds them only by an explicit `drop`. The seeds
|
|
164
|
+
* live in the `_base` layer under `content/en/PortfolioItem/`; the detail
|
|
165
|
+
* row's `contentDir` installs them (#6646 D1), exactly as `/for/[slug]`
|
|
166
|
+
* serves `content/en/UseCase`.
|
|
167
|
+
*/
|
|
168
|
+
// NO_HAND_IMPLEMENT_OK: /build-starter operator-directed live pass (#6687).
|
|
169
|
+
const PORTFOLIO_ROWS = [
|
|
170
|
+
{ route: "/portfolio", content: ["content/en/PortfolioList/portfolio.mdx"] },
|
|
171
|
+
{ route: "/portfolio/[slug]", contentDir: "content/en/PortfolioItem" },
|
|
172
|
+
];
|
|
173
|
+
/**
|
|
174
|
+
* `minimalism-site`'s two OWN rows (#5589, shrunk from its own 17-row roster
|
|
175
|
+
* by #6757 once the `organization-service` shape carried a standard roster of
|
|
176
|
+
* its own): the deck's two `LandingPage` slugs, positioned by `insert` (D7)
|
|
177
|
+
* at the two points this alias interleaves them into the shape's row order
|
|
178
|
+
* (§ 1.2) — `/reports` before `/about`, `/referral` before `/faq`. Neither
|
|
179
|
+
* carries a `GATEABLE_SURFACES` entry: both are single-segment slugs served
|
|
180
|
+
* by the generic `[slug]` route (#5469 D2), the same mechanism Free's
|
|
181
|
+
* `/how-it-works` used.
|
|
182
|
+
*/
|
|
183
|
+
const REPORTS_ROW = {
|
|
184
|
+
route: "/reports",
|
|
185
|
+
content: ["content/en/ReportsList/reports.mdx"],
|
|
186
|
+
};
|
|
187
|
+
const REFERRAL_ROW = {
|
|
188
|
+
route: "/referral",
|
|
189
|
+
content: ["content/en/LandingPage/referral.mdx"],
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* The signal-collectors module's report/referral sample rows (spec 6892 D3):
|
|
193
|
+
* `/reports`, a `ReportsList` hub over the module's four `ReportPage` seeds,
|
|
194
|
+
* and `/referral`, a sample flow landing page. `marketing-site` and
|
|
195
|
+
* `saas-product` add these before `/portfolio`, alongside
|
|
196
|
+
* `SIGNAL_COLLECTORS_SAMPLE_ROWS`; `minimalism-site` keeps its own two
|
|
197
|
+
* `insert` groups instead (its pre-existing row order, D1).
|
|
198
|
+
*/
|
|
199
|
+
const SIGNAL_COLLECTORS_REPORT_ROWS = [
|
|
200
|
+
REPORTS_ROW,
|
|
201
|
+
REFERRAL_ROW,
|
|
202
|
+
];
|
|
203
|
+
/**
|
|
204
|
+
* `organization-service`'s own rows (#6757 D1), derived from
|
|
205
|
+
* `derive-roster.py --shape organization-service --primary-goal generate-leads
|
|
206
|
+
* --registry packages/schema/src/registry/entries.ts` at harness commit
|
|
207
|
+
* `7bdaf148e1b0e639cd90a80008955e55cc4aa2b5`, edited only by the deviations
|
|
208
|
+
* `site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md` § 3a
|
|
209
|
+
* records with their reasons. Row order matches `minimalism-site`'s (D3), so
|
|
210
|
+
* that alias's `differences` are additions and drops only.
|
|
211
|
+
*/
|
|
212
|
+
const ORGANIZATION_SERVICE_ROWS = [
|
|
213
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
214
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
215
|
+
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
216
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
217
|
+
// #6878 D7 — every shape carries the /for family now, service shapes
|
|
218
|
+
// included: the seeds are shape-neutral (D7), so no per-shape override is
|
|
219
|
+
// needed.
|
|
220
|
+
{
|
|
221
|
+
route: "/for",
|
|
222
|
+
content: ["content/en/UseCasesList/for.mdx"],
|
|
223
|
+
},
|
|
224
|
+
{ route: "/for/[slug]", contentDir: "content/en/UseCase" },
|
|
225
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
226
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
227
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
228
|
+
{ route: "/sign-in" },
|
|
229
|
+
{ route: "/sign-up" },
|
|
230
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
231
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
232
|
+
{
|
|
233
|
+
route: "/purchase-policy",
|
|
234
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
235
|
+
},
|
|
236
|
+
];
|
|
237
|
+
/**
|
|
238
|
+
* `local-business-service`'s own rows (#6757 D1), derived the same way with
|
|
239
|
+
* `--shape local-business-service`. It has no `--template` alias of its own
|
|
240
|
+
* since #6789 retired the one alias that composed it; `--shape` is its only entry.
|
|
241
|
+
*/
|
|
242
|
+
const LOCAL_BUSINESS_SERVICE_ROWS = [
|
|
243
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
244
|
+
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
245
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
246
|
+
// #6878 D7 — every shape carries the /for family now (D7 shape-neutral seeds).
|
|
247
|
+
{
|
|
248
|
+
route: "/for",
|
|
249
|
+
content: ["content/en/UseCasesList/for.mdx"],
|
|
250
|
+
},
|
|
251
|
+
{ route: "/for/[slug]", contentDir: "content/en/UseCase" },
|
|
252
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
253
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
254
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
255
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
256
|
+
{ route: "/sign-in" },
|
|
257
|
+
{ route: "/sign-up" },
|
|
258
|
+
{
|
|
259
|
+
route: "/purchase-policy",
|
|
260
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
261
|
+
},
|
|
262
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
263
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
264
|
+
];
|
|
265
|
+
/**
|
|
266
|
+
* `person-service`'s own rows (#6758 D1, D3), derived from
|
|
267
|
+
* `derive-roster.py --shape person-service --primary-goal generate-leads
|
|
268
|
+
* --registry packages/schema/src/registry/entries.ts` at harness commit
|
|
269
|
+
* `7bdaf148e1b0e639cd90a80008955e55cc4aa2b5` (the vendored equivalent:
|
|
270
|
+
* `--entity-type person --offering-type services --primary-goal
|
|
271
|
+
* generate-leads --scale global`), edited only by the deviations
|
|
272
|
+
* `site-templates/shapes/person-service/TEMPLATE-MANIFEST.md` § 3a records
|
|
273
|
+
* with their reasons. Row order matches `local-business-service`'s (D3):
|
|
274
|
+
* services before about, because a consultant is hired for an engagement
|
|
275
|
+
* first.
|
|
276
|
+
*/
|
|
277
|
+
const PERSON_SERVICE_ROWS = [
|
|
278
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
279
|
+
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
280
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
281
|
+
// #6878 D7 — every shape carries the /for family now (D7 shape-neutral seeds).
|
|
282
|
+
{
|
|
283
|
+
route: "/for",
|
|
284
|
+
content: ["content/en/UseCasesList/for.mdx"],
|
|
285
|
+
},
|
|
286
|
+
{ route: "/for/[slug]", contentDir: "content/en/UseCase" },
|
|
287
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
288
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
289
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
290
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
291
|
+
{ route: "/sign-in" },
|
|
292
|
+
{ route: "/sign-up" },
|
|
293
|
+
{
|
|
294
|
+
route: "/purchase-policy",
|
|
295
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
296
|
+
},
|
|
297
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
298
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
299
|
+
];
|
|
300
|
+
/**
|
|
301
|
+
* Each buildable shape's standard roster (#6753 D3) — the rows an alias starts
|
|
302
|
+
* from before its `differences` apply.
|
|
303
|
+
*
|
|
304
|
+
* `organization-product` is today's base roster, the `/blog` teaser and the
|
|
305
|
+
* portfolio pair. `organization-service`, `local-business-service` (#6757)
|
|
306
|
+
* and `person-service` (#6758, roadmap § 6 Phase 2) are each their own rows,
|
|
307
|
+
* the `/blog` teaser and the portfolio pair. Every shape's own rows carry
|
|
308
|
+
* `/sign-in` and `/sign-up` (#6797): the locale layout's header links both on
|
|
309
|
+
* every shape, so the roster of record lists them as code routes.
|
|
310
|
+
*/
|
|
311
|
+
export const SHAPE_ROSTERS = Object.freeze({
|
|
312
|
+
"organization-product": [
|
|
313
|
+
...TEMPLATE_BASE_ROSTER,
|
|
314
|
+
FREE_BLOG_TEASER_ROW,
|
|
315
|
+
...FREE_MEET_PLACEHOLDER_ROWS,
|
|
316
|
+
...PORTFOLIO_ROWS,
|
|
317
|
+
],
|
|
318
|
+
"organization-service": [
|
|
319
|
+
...ORGANIZATION_SERVICE_ROWS,
|
|
320
|
+
FREE_BLOG_TEASER_ROW,
|
|
321
|
+
...FREE_MEET_PLACEHOLDER_ROWS,
|
|
322
|
+
...PORTFOLIO_ROWS,
|
|
323
|
+
],
|
|
324
|
+
"local-business-service": [
|
|
325
|
+
...LOCAL_BUSINESS_SERVICE_ROWS,
|
|
326
|
+
FREE_BLOG_TEASER_ROW,
|
|
327
|
+
...FREE_MEET_PLACEHOLDER_ROWS,
|
|
328
|
+
...PORTFOLIO_ROWS,
|
|
329
|
+
],
|
|
330
|
+
"person-service": [
|
|
331
|
+
...PERSON_SERVICE_ROWS,
|
|
332
|
+
FREE_BLOG_TEASER_ROW,
|
|
333
|
+
...FREE_MEET_PLACEHOLDER_ROWS,
|
|
334
|
+
...PORTFOLIO_ROWS,
|
|
335
|
+
],
|
|
336
|
+
});
|
|
337
|
+
/**
|
|
338
|
+
* The `--template` names and the grid coordinates each stands for (#6753) —
|
|
339
|
+
* the one table `TEMPLATE_MANIFESTS` and `RECOGNIZED_TEMPLATES` derive from,
|
|
340
|
+
* in the declaration order both keep. The plain name is the Pro one: it is
|
|
341
|
+
* the flagship and the demo (Sam, 2026-09-14, parent § D12).
|
|
342
|
+
*
|
|
343
|
+
* `workspace` appears in no module list. It is a Pro module, but an authed app
|
|
344
|
+
* surface contributing no PUBLIC page to a marketing site, and `modules` names
|
|
345
|
+
* what the roster uses (parent § D15). A Pro key unlocks it regardless of any
|
|
346
|
+
* template.
|
|
347
|
+
*
|
|
348
|
+
* `commerce` is a per-site add-on available at any level, so no alias exists
|
|
349
|
+
* FOR it (parent § D13); it still contributes rows to whichever alias takes
|
|
350
|
+
* it, through `mergeRoster`.
|
|
351
|
+
*
|
|
352
|
+
* Frozen (#5507): the registry composed from this table is also the issuer's
|
|
353
|
+
* authorization allowlist (spec 5480 § C7). A test needing a different table
|
|
354
|
+
* passes its own to `resolveTemplate(name, aliases)` rather than mutating
|
|
355
|
+
* this one.
|
|
356
|
+
*/
|
|
357
|
+
export const ALIASES = Object.freeze({
|
|
358
|
+
/**
|
|
359
|
+
* The Free template, and the mechanism's own proof (parent § D11): it
|
|
360
|
+
* requires only `marketing`, so the keyless merge path is exercised by a
|
|
361
|
+
* template we ship anyway rather than by a throwaway fixture. The bare
|
|
362
|
+
* `organization-product` shape — no differences at all.
|
|
363
|
+
*/
|
|
364
|
+
"marketing-site-free": {
|
|
365
|
+
shape: "organization-product",
|
|
366
|
+
design: "standard",
|
|
367
|
+
modules: ["marketing"],
|
|
368
|
+
categories: ["accounting", "legal", "technology"],
|
|
369
|
+
// The demo site carries the "Get started with this template" banner
|
|
370
|
+
// (operator ruling 2026-09-23); every other layout knob keeps its default.
|
|
371
|
+
layout: { announcementBanner: true },
|
|
372
|
+
},
|
|
373
|
+
/**
|
|
374
|
+
* The Pro flagship. Its module list is OFFERINGS § 4 offering 3's tiers line
|
|
375
|
+
* — "docs, scheduling and flows modules" — where "flows" is
|
|
376
|
+
* `signal-collectors` (`MODULE_SURFACES` maps it to `["flows"]`). It drops
|
|
377
|
+
* the shape's `/blog` teaser because docs-blog contributes the real `/blog`,
|
|
378
|
+
* and adds the signal-collectors sample rows ahead of the portfolio pair.
|
|
379
|
+
*/
|
|
380
|
+
"marketing-site": {
|
|
381
|
+
shape: "organization-product",
|
|
382
|
+
design: "standard",
|
|
383
|
+
modules: ["marketing", "docs-blog", "scheduling", "signal-collectors"],
|
|
384
|
+
// The flagship is the general-purpose template: it carries the whole
|
|
385
|
+
// registry, so every group tile on the hub has at least one template.
|
|
386
|
+
categories: [
|
|
387
|
+
"accounting",
|
|
388
|
+
"legal",
|
|
389
|
+
"consulting",
|
|
390
|
+
"hvac",
|
|
391
|
+
"roofing",
|
|
392
|
+
"plumbing",
|
|
393
|
+
"electrical",
|
|
394
|
+
"landscaping",
|
|
395
|
+
"auto-repair",
|
|
396
|
+
"real-estate",
|
|
397
|
+
"technology",
|
|
398
|
+
"medical-specialty",
|
|
399
|
+
],
|
|
400
|
+
differences: {
|
|
401
|
+
drop: ["/blog", "/meet", "/meet/[slug]"],
|
|
402
|
+
add: [...SIGNAL_COLLECTORS_SAMPLE_ROWS, ...SIGNAL_COLLECTORS_REPORT_ROWS],
|
|
403
|
+
before: "/portfolio",
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
/**
|
|
407
|
+
* Pro Plus — the Pro list plus `multi-tenant`, which is correctly in the
|
|
408
|
+
* list because it DOES contribute pages (the org and workspace surfaces).
|
|
409
|
+
* Its `pageContributions` is nonetheless unset today, deferred to its own
|
|
410
|
+
* instance, so this template's merged roster carries the same contributed
|
|
411
|
+
* rows as `marketing-site`'s and no more. That is a module which has
|
|
412
|
+
* declared no rows yet — visible in the diff — not a merge that dropped
|
|
413
|
+
* declared rows.
|
|
414
|
+
*/
|
|
415
|
+
"saas-product": {
|
|
416
|
+
shape: "organization-product",
|
|
417
|
+
design: "standard",
|
|
418
|
+
modules: [
|
|
419
|
+
"marketing",
|
|
420
|
+
"docs-blog",
|
|
421
|
+
"scheduling",
|
|
422
|
+
"signal-collectors",
|
|
423
|
+
"multi-tenant",
|
|
424
|
+
],
|
|
425
|
+
categories: ["technology", "medical-specialty"],
|
|
426
|
+
differences: {
|
|
427
|
+
drop: ["/blog", "/meet", "/meet/[slug]"],
|
|
428
|
+
add: [...SIGNAL_COLLECTORS_SAMPLE_ROWS, ...SIGNAL_COLLECTORS_REPORT_ROWS],
|
|
429
|
+
before: "/portfolio",
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
/**
|
|
433
|
+
* The second Pro template (#5589) — the reports-first, scroll-snap deck
|
|
434
|
+
* site. NOT `marketing-site` plus a module: its `modules` omit `docs-blog`,
|
|
435
|
+
* so the two Pro templates are siblings under `_base` (#5618 D2), never a
|
|
436
|
+
* lineage. Level still derives from `modules`: `scheduling` and
|
|
437
|
+
* `signal-collectors` are paid, so `templateDelivery` returns `"paid"`
|
|
438
|
+
* exactly as it does for `marketing-site`.
|
|
439
|
+
*
|
|
440
|
+
* It composes the `organization-service` shape roster (#6757) rather than
|
|
441
|
+
* the organization-product one: the deck home replaces the document-scroll
|
|
442
|
+
* home, and `/how-it-works`, the product page, `/pricing` and `/sign-in`
|
|
443
|
+
* are not pages this site has. The roster is what the
|
|
444
|
+
* template IS, so an unrostered page has neither a route directory
|
|
445
|
+
* (`rosterSurfaces`) nor its `_base`/overlay seed (#6646 D1).
|
|
446
|
+
*
|
|
447
|
+
* It declares NO `layout` block (#6638): the deck home, mark-only nav and
|
|
448
|
+
* centered footer are the `minimalism` design's own `layout` (its
|
|
449
|
+
* `DESIGN.md`, resolved by `resolveDesign` off `design:` — #6813 D4) — the
|
|
450
|
+
* look any shape can wear. This alias ships no tree of its own (`ownTree:
|
|
451
|
+
* false`, spec 6892 D1); its GENERATED roster record (no narrative `.md`,
|
|
452
|
+
* D5) lives at `site-templates/aliases/minimalism-site.TEMPLATE-MANIFEST.json`.
|
|
453
|
+
*
|
|
454
|
+
* `/reports` (a `ReportsList` hub over `ReportPage`) and `/referral` (a
|
|
455
|
+
* flow landing page) are signal-collectors module samples (spec 6892 D3);
|
|
456
|
+
* neither carries a `GATEABLE_SURFACES` entry: `/referral` is a
|
|
457
|
+
* single-segment `LandingPage` slug served by the generic `[slug]` route
|
|
458
|
+
* (#5469 D2), the same mechanism Free's `/how-it-works` uses, and `/reports`
|
|
459
|
+
* is its own routes-map row. `/reports/[slug]` (the reader) is the
|
|
460
|
+
* signal-collectors module's own contributed row.
|
|
461
|
+
*
|
|
462
|
+
* `/services/[slug]` declares its seed DIRECTORY as `contentDir`
|
|
463
|
+
* (`content/en/Service`, as `routes-map.ts` records it). The three
|
|
464
|
+
* samples ride the template tree unmapped, landing at that directory.
|
|
465
|
+
*
|
|
466
|
+
* Since #6757, `organization-service` carries a real standard roster
|
|
467
|
+
* (D1), so this alias's `differences` is additions and drops only: it
|
|
468
|
+
* drops the `/blog` teaser (a Pro alias does not upsell its own level,
|
|
469
|
+
* D8), the portfolio pair (the reports are the proof, not a
|
|
470
|
+
* portfolio) and the two auth code routes the shape rosters (#6797 —
|
|
471
|
+
* this site has no `/sign-in`, above), adds the signal-collectors
|
|
472
|
+
* samples, and INSERTS its two own
|
|
473
|
+
* rows — `/reports` before `/about`, `/referral` before `/faq` (D7) — to
|
|
474
|
+
* reproduce its pre-#6757 row order (§ 1.2) exactly.
|
|
475
|
+
*/
|
|
476
|
+
"minimalism-site": {
|
|
477
|
+
shape: "organization-service",
|
|
478
|
+
design: "minimalism",
|
|
479
|
+
modules: ["marketing", "scheduling", "signal-collectors"],
|
|
480
|
+
categories: ["real-estate", "technology", "legal"],
|
|
481
|
+
// Spec 6892 D1 — this alias ships no `site-templates/minimalism-site/`
|
|
482
|
+
// tree of its own: it resolves purely from the grid. Its seed layer is
|
|
483
|
+
// its shape's tree (`templateTreeDir`), its deck home + SVGs are a
|
|
484
|
+
// sample the `minimalism` design installs (D4), and its `/reports` +
|
|
485
|
+
// `/referral` rows are signal-collectors module samples (D3).
|
|
486
|
+
ownTree: false,
|
|
487
|
+
differences: {
|
|
488
|
+
drop: [
|
|
489
|
+
"/sign-in",
|
|
490
|
+
"/sign-up",
|
|
491
|
+
"/blog",
|
|
492
|
+
"/meet",
|
|
493
|
+
"/meet/[slug]",
|
|
494
|
+
"/portfolio",
|
|
495
|
+
"/portfolio/[slug]",
|
|
496
|
+
],
|
|
497
|
+
add: SIGNAL_COLLECTORS_SAMPLE_ROWS,
|
|
498
|
+
insert: [
|
|
499
|
+
{ before: "/about", rows: [REPORTS_ROW] },
|
|
500
|
+
{ before: "/faq", rows: [REFERRAL_ROW] },
|
|
501
|
+
],
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
/**
|
|
506
|
+
* The coordinates a keyless `--shape S` builds (#6757 D5) — the composed
|
|
507
|
+
* FREE manifest per shape, for a shape with no `--template` alias of its
|
|
508
|
+
* own. Frozen and `Partial`; `organization-product` needs none — its
|
|
509
|
+
* keyless tree is `marketing-site-free`'s (#6754 AC-2).
|
|
510
|
+
*
|
|
511
|
+
* No `differences` (a bare shape is its standard roster, D1) and no
|
|
512
|
+
* `layout`. Every category is a leaf of `packages/schema/src/categories.ts`,
|
|
513
|
+
* as `TemplateManifest.categories` requires. `person-service`'s single
|
|
514
|
+
* `consulting` category is the operator's disposition (2026-09-26,
|
|
515
|
+
* ai-launch-kit-internal#6758): the leaf did not exist when #6758's spec was
|
|
516
|
+
* written, and adding it replaced that spec's `["accounting", "legal",
|
|
517
|
+
* "technology"]` author-pick stand-in.
|
|
518
|
+
*/
|
|
519
|
+
export const SHAPE_STARTER_ALIASES = Object.freeze({
|
|
520
|
+
"organization-service": {
|
|
521
|
+
shape: "organization-service",
|
|
522
|
+
design: "standard",
|
|
523
|
+
modules: ["marketing"],
|
|
524
|
+
categories: ["accounting", "legal", "real-estate"],
|
|
525
|
+
},
|
|
526
|
+
"local-business-service": {
|
|
527
|
+
shape: "local-business-service",
|
|
528
|
+
design: "standard",
|
|
529
|
+
modules: ["marketing"],
|
|
530
|
+
categories: [
|
|
531
|
+
"hvac",
|
|
532
|
+
"roofing",
|
|
533
|
+
"plumbing",
|
|
534
|
+
"electrical",
|
|
535
|
+
"landscaping",
|
|
536
|
+
"auto-repair",
|
|
537
|
+
],
|
|
538
|
+
},
|
|
539
|
+
"person-service": {
|
|
540
|
+
shape: "person-service",
|
|
541
|
+
design: "standard",
|
|
542
|
+
modules: ["marketing"],
|
|
543
|
+
categories: ["consulting"],
|
|
544
|
+
},
|
|
545
|
+
});
|
package/dist/surfaces.d.ts
CHANGED
|
@@ -181,6 +181,33 @@ export declare const ROUTE_DEPENDENCIES: Readonly<Record<string, readonly string
|
|
|
181
181
|
export declare const ROUTE_MESSAGE_NAMESPACES: Readonly<Record<string, readonly string[]>>;
|
|
182
182
|
/** Template-relative path of the generated site-nav registry. */
|
|
183
183
|
export declare const NAV_CONFIG_PATH = "apps/web/lib/nav-config.ts";
|
|
184
|
+
/**
|
|
185
|
+
* Verify a rendered nav's self-hashing stamp (#6908 D1/F1–F2): `"valid"` when
|
|
186
|
+
* the first line's hash matches every byte after it, `"invalid"` when a
|
|
187
|
+
* stamp line is present but the hash fails (an edited, still-stamped nav),
|
|
188
|
+
* `"absent"` when there is no stamp line at all. A stamp that verifies proves
|
|
189
|
+
* the file unedited whatever generator wrote it — the check needs only the
|
|
190
|
+
* file, never the generator's code.
|
|
191
|
+
*/
|
|
192
|
+
export declare function readNavConfigStamp(text: string): "valid" | "invalid" | "absent";
|
|
193
|
+
/**
|
|
194
|
+
* Every byte after a nav's stamp line, or `text` unchanged when it carries
|
|
195
|
+
* none. The one place the D1 stamp-line shape is matched outside
|
|
196
|
+
* `readNavConfigStamp` itself, so a test simulating an edit below the stamp
|
|
197
|
+
* (or a bare pre-D1 body) never re-derives `NAV_STAMP_RE`'s pattern by hand.
|
|
198
|
+
*/
|
|
199
|
+
export declare function stripNavConfigStamp(text: string): string;
|
|
200
|
+
/** Options for `renderNavConfig` (#6878 D6). */
|
|
201
|
+
export interface RenderNavConfigOptions {
|
|
202
|
+
/**
|
|
203
|
+
* Service page slugs — the basenames, minus `.mdx`, of a site's
|
|
204
|
+
* `content/en/Service/*.mdx` — for the Services flyout column on a
|
|
205
|
+
* service shape. Sorted, then cut to the first three. Absent/empty →
|
|
206
|
+
* the offering column emits no Services links even when the `services`
|
|
207
|
+
* surface is on (there is nothing to link yet).
|
|
208
|
+
*/
|
|
209
|
+
serviceSlugs?: readonly string[];
|
|
210
|
+
}
|
|
184
211
|
/**
|
|
185
212
|
* Render `apps/web/lib/nav-config.ts` for an enabled surface set.
|
|
186
213
|
*
|
|
@@ -191,14 +218,19 @@ export declare const NAV_CONFIG_PATH = "apps/web/lib/nav-config.ts";
|
|
|
191
218
|
* surface set for the same reason the route tree does.
|
|
192
219
|
*
|
|
193
220
|
* The base items are the Free marketing-site chrome (#5469 D5, the approved
|
|
194
|
-
* chrome diff recorded on that card, re-pointed by #6658 D8):
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
* the docs-blog module serves it).
|
|
199
|
-
*
|
|
200
|
-
* roster enables it, #5469 D10), so the nav still never links a page
|
|
201
|
-
* scaffold does not carry.
|
|
221
|
+
* chrome diff recorded on that card, re-pointed by #6658 D8, then by #6878 D6):
|
|
222
|
+
* ONE flyout rule for every shape — an offering column (Features on product
|
|
223
|
+
* shapes, Services on service shapes) beside a Customers column linking the
|
|
224
|
+
* /for persona pages — then Blog, Pricing and About. `/blog` is always linked
|
|
225
|
+
* (the teaser or the docs-blog module serves it). Pricing and every other
|
|
226
|
+
* gateable surface: each item is emitted only when its surface is enabled (a
|
|
227
|
+
* template roster enables it, #5469 D10), so the nav still never links a page
|
|
228
|
+
* the scaffold does not carry. Portfolio is never a flyout link (D6): on a
|
|
229
|
+
* service shape it is a plain top-level link directly after the Services
|
|
230
|
+
* flyout, and every shape's footer Site pages column links it (#6895), both
|
|
231
|
+
* under the `portfolio` surface's gate. No empty flyout is ever emitted: with
|
|
232
|
+
* neither column non-empty, no flyout item is emitted at all (closes #6766's
|
|
233
|
+
* AC-1).
|
|
202
234
|
*
|
|
203
235
|
* Only gateable surfaces carrying a `navLabelKey` are linked after the base
|
|
204
236
|
* items, because a nav entry needs a translated label. Emitting an entry whose
|
|
@@ -212,4 +244,4 @@ export declare const NAV_CONFIG_PATH = "apps/web/lib/nav-config.ts";
|
|
|
212
244
|
* Deterministic: gateable entries follow GATEABLE_SURFACES order (alphabetical
|
|
213
245
|
* by id), after the fixed base items.
|
|
214
246
|
*/
|
|
215
|
-
export declare function renderNavConfig(enabled: string[]): string;
|
|
247
|
+
export declare function renderNavConfig(enabled: string[], options?: RenderNavConfigOptions): string;
|