create-ailk 0.7.0 → 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 +44 -10
- package/component-catalog.json +520 -5
- package/component-catalog.md +9 -6
- package/dist/cli.js +22 -24
- package/dist/lib/extract-module-bundle.js +5 -1
- 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.js +10 -2
- package/dist/parse-args.d.ts +78 -10
- package/dist/parse-args.js +204 -14
- package/dist/programmatic.d.ts +39 -9
- package/dist/programmatic.js +163 -25
- package/dist/site-roster.js +11 -6
- package/dist/starter-grid.d.ts +216 -0
- package/dist/starter-grid.js +449 -0
- package/dist/surfaces.d.ts +4 -4
- package/dist/surfaces.js +102 -43
- package/dist/template-manifest.d.ts +36 -17
- package/dist/template-manifest.js +121 -367
- package/dist/template-names.d.ts +14 -12
- package/dist/template-names.js +13 -17
- package/package.json +3 -3
- package/site-templates/_base/content/en/BookCall/book-call.mdx +0 -1
- 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 +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/standard/DESIGN.md +5 -0
- package/site-templates/marketing-site/DESIGN.md +5 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +89 -25
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +35 -14
- package/site-templates/marketing-site-free/DESIGN.md +5 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +95 -29
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +74 -44
- 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/TEMPLATE-MANIFEST.md +17 -29
- package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +0 -1
- package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +0 -1
- package/site-templates/saas-product/DESIGN.md +5 -0
- package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
- package/site-templates/{simple-service → shapes/local-business-service}/TEMPLATE-MANIFEST.json +96 -76
- 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/{simple-service → 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 +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/skills/README.md +3 -2
- package/templates/.claude/skills/add-page/references/page-types.md +4 -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/setup-deploy/SKILL.md +64 -32
- package/templates/.claude/skills/setup-deploy/references/env-vars-template.md +19 -28
- package/templates/.claude/skills/setup-deploy/references/runbook-template.md +58 -102
- package/templates/DESIGN.md +5 -0
- package/templates/README.md +46 -38
- package/templates/apps/api/CLAUDE.md +3 -2
- 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/openapi/spec.ts +63 -12
- 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 +7 -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__/parity.test.ts +5 -4
- package/templates/apps/mcp/src/tools/create_project.ts +21 -6
- 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]/layout.tsx +37 -5
- 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]/portfolio/page.tsx +49 -0
- package/templates/apps/web/app/[locale]/use-cases/[slug]/page.tsx +18 -3
- package/templates/apps/web/lib/nav-config.ts +48 -36
- package/templates/apps/web/lib/site-identity.ts +14 -0
- package/templates/apps/web/messages/en.json +28 -2
- package/templates/content/_site.mdx +4 -2
- package/templates/content/en/BlogList/blog.mdx +37 -16
- package/templates/content/en/ContactPage/contact.mdx +14 -44
- package/templates/content/en/HomePage/home.mdx +8 -16
- package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +0 -1
- package/templates/content/en/UseCasesList/use-cases.mdx +6 -6
- package/templates/database/CHANGELOG.md +7 -0
- package/templates/database/package.json +1 -1
- package/versions.json +33 -33
- 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/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/apps/web/app/[locale]/contact/ContactForm.tsx +0 -211
- package/templates/apps/web/app/[locale]/contact/__tests__/ContactForm.test.tsx +0 -96
- package/templates/content/en/SoftwareProduct/product.mdx +0 -175
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The three pages every starter carries whatever its shape (#6658 D5,
|
|
3
|
+
* `docs/decisions/starter-roster-page-set.md` D4/D7): a glossary, a newsletter
|
|
4
|
+
* signup and a book-a-call page. Each is a module-less `GATEABLE_SURFACES`
|
|
5
|
+
* entry the roster enables, with its seed in `_base`. A template carrying the
|
|
6
|
+
* scheduling module overrides `BookCall/book-call.mdx` in its own tree, so the
|
|
7
|
+
* call to action opens `/meet` rather than `/contact`.
|
|
8
|
+
*/
|
|
9
|
+
const SHAPE_INDEPENDENT_ROWS = [
|
|
10
|
+
{ route: "/glossary", content: ["content/en/GlossaryList/glossary.mdx"] },
|
|
11
|
+
{
|
|
12
|
+
route: "/newsletter",
|
|
13
|
+
content: ["content/en/NewsletterSignup/newsletter.mdx"],
|
|
14
|
+
},
|
|
15
|
+
{ route: "/book-a-call", content: ["content/en/BookCall/book-call.mdx"] },
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* The rows every `organization-product` template brings itself — one declared
|
|
19
|
+
* page set, whichever layer carries each seed. Re-derived by #6658 from the
|
|
20
|
+
* standard (`derive-roster.py --entity-type software --offering-type software
|
|
21
|
+
* --primary-goal convert --scale global`, the `--shape organization-product`
|
|
22
|
+
* equivalent), edited only by the deviations the Free manifest's § 3a records
|
|
23
|
+
* with their reasons. With a template named, `scaffold()` keeps a `_base` or
|
|
24
|
+
* overlay seed only when a merged roster row names it (#6646 D1): the roster
|
|
25
|
+
* decides what installs, and the manifest generator's `--check` proves it.
|
|
26
|
+
*
|
|
27
|
+
* Two layers, one roster:
|
|
28
|
+
*
|
|
29
|
+
* - `/`, `/software/[slug]`, `/use-cases`, `/about`, `/faq`, `/contact` and
|
|
30
|
+
* `/purchase-policy` take their content from the overlay
|
|
31
|
+
* (`template-overlay/content/en/**`, copied whole into `templates/` by
|
|
32
|
+
* `build-templates.mjs`). `/features` is the FeaturesList hub over one
|
|
33
|
+
* Feature page per feature at `/features/[slug]` (#6721, reversing the
|
|
34
|
+
* single `/software/product` page of #6658 D3); both ride the `features`
|
|
35
|
+
* surface the roster enables.
|
|
36
|
+
* `/use-cases` lists the three UseCase pages at `/use-cases/[slug]`
|
|
37
|
+
* (#6658 D4).
|
|
38
|
+
* - `/pricing`, `/privacy`, `/terms`, `/glossary`, `/newsletter`,
|
|
39
|
+
* `/book-a-call` and the three UseCase pages take their content from the
|
|
40
|
+
* base layer (`site-templates/_base/content/**`, #5618 D1), which every
|
|
41
|
+
* template reaches by declaring `extends` — installed before the module
|
|
42
|
+
* bundles and the template's own tree, so a template may override a base
|
|
43
|
+
* page by shipping the same path. Their surfaces are module-less by
|
|
44
|
+
* construction (parent § D16, #6658 D5): a template enables them by
|
|
45
|
+
* NAMING them in its roster — `scaffold()` selects their
|
|
46
|
+
* `GATEABLE_SURFACES` entries from the merged roster's routes (#5469 D10).
|
|
47
|
+
*
|
|
48
|
+
* `/software`, `/sign-in` and `/sign-up` carry no `content`: they are code
|
|
49
|
+
* routes (the SoftwareProduct listing, the SignInCard island, the sign-up
|
|
50
|
+
* form), like the API-backed rows the scheduling module contributes — listed
|
|
51
|
+
* so the manifest is a complete install record, where the generator marks
|
|
52
|
+
* them `kind: route` (#6646 D2).
|
|
53
|
+
*
|
|
54
|
+
* `/purchase-policy` is the product-shape purchase policy (#6646 D3): its
|
|
55
|
+
* overlay seed carries returns, shipping and refunds sections — the overlay,
|
|
56
|
+
* not `_base`, because the route is core and a scaffold naming no template
|
|
57
|
+
* serves it too. A service-shape template overrides that seed with its own
|
|
58
|
+
* cancellation and refunds file.
|
|
59
|
+
*
|
|
60
|
+
* `/blog` is deliberately NOT here (#5469 D3): the docs-blog module
|
|
61
|
+
* contributes its own `/blog` row, so a base row would make `mergeRoster`
|
|
62
|
+
* refuse every template that takes that module. The teaser row is an
|
|
63
|
+
* `organization-product` shape row instead (#6753 D3), which the two aliases
|
|
64
|
+
* taking docs-blog drop.
|
|
65
|
+
*/
|
|
66
|
+
const TEMPLATE_BASE_ROSTER = [
|
|
67
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
68
|
+
// #6721 — the product's features: a FeaturesList hub over one Feature page
|
|
69
|
+
// per feature (replaces the single /software/product page, #6658 D3).
|
|
70
|
+
{ route: "/features", content: ["content/en/FeaturesList/features.mdx"] },
|
|
71
|
+
{ route: "/features/[slug]", contentDir: "content/en/Feature" },
|
|
72
|
+
{
|
|
73
|
+
route: "/use-cases",
|
|
74
|
+
content: ["content/en/UseCasesList/use-cases.mdx"],
|
|
75
|
+
},
|
|
76
|
+
{ route: "/use-cases/[slug]", contentDir: "content/en/UseCase" },
|
|
77
|
+
{ route: "/pricing", content: ["content/en/Pricing/pricing.mdx"] },
|
|
78
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
79
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
80
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
81
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
82
|
+
{ route: "/sign-in" },
|
|
83
|
+
{ route: "/sign-up" },
|
|
84
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
85
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
86
|
+
{
|
|
87
|
+
route: "/purchase-policy",
|
|
88
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
/**
|
|
92
|
+
* The Free `/blog` teaser (#5469 D3) — one static BlogList page (schema `Blog`
|
|
93
|
+
* with an empty `ItemList`; the correct page type, not a LandingPage) that
|
|
94
|
+
* says what the Pro docs-blog module gives you. It is served by the generic
|
|
95
|
+
* `[slug]` route — which probes `LandingPage` first, then `BlogList` — over
|
|
96
|
+
* `content/en/BlogList/blog.mdx`, which ships in the always-copied overlay. `/blog` degrades by DIRECTORY PRECEDENCE, not
|
|
97
|
+
* by a module gate: in a keyed docs-blog scaffold the module's own
|
|
98
|
+
* `blog/[[...slug]]/page.tsx` directory exists and Next.js resolves the static
|
|
99
|
+
* segment first, so the teaser file is inert; keyless, no `blog/` directory
|
|
100
|
+
* exists and the teaser renders. An `organization-product` shape row
|
|
101
|
+
* (#6753 D3): the aliases taking docs-blog drop it, so on `marketing-site`
|
|
102
|
+
* the docs-blog contribution claims the route.
|
|
103
|
+
*/
|
|
104
|
+
const FREE_BLOG_TEASER_ROW = {
|
|
105
|
+
route: "/blog",
|
|
106
|
+
content: ["content/en/BlogList/blog.mdx"],
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* The rows for the `signal-collectors` bundle's six sample pages (#6646
|
|
110
|
+
* disposition (a)) — the project listing, its two project pages and the
|
|
111
|
+
* three thank-you pages its `installMap` lands. The module contributes no
|
|
112
|
+
* row for any of these routes (`module-architecture.ts`'s installMap
|
|
113
|
+
* comment), so a template that takes the module declares them, and the
|
|
114
|
+
* roster names every page the scaffold installs. `/projects` is a
|
|
115
|
+
* module-less `GATEABLE_SURFACES` entry, so naming it here also copies the
|
|
116
|
+
* route directory the samples render through (`rosterSurfaces`).
|
|
117
|
+
*/
|
|
118
|
+
const SIGNAL_COLLECTORS_SAMPLE_ROWS = [
|
|
119
|
+
{ route: "/projects", content: ["content/en/ProjectsList/projects.mdx"] },
|
|
120
|
+
{ route: "/projects/[slug]", contentDir: "content/en/Project" },
|
|
121
|
+
{ route: "/thanks/[slug]", contentDir: "content/en/ThankYouPage" },
|
|
122
|
+
];
|
|
123
|
+
/**
|
|
124
|
+
* The portfolio pages (#6687) — before/after project comparisons: a
|
|
125
|
+
* PortfolioList hub on the /alternatives stack and one PortfolioItem page per
|
|
126
|
+
* comparison, each one `before-after` section carrying its header band and
|
|
127
|
+
* pager. They belong to the SHAPE, Free included (roadmap § 4, operator
|
|
128
|
+
* 2026-09-25, reversing #6687's "Pro and up"): every shape roster below
|
|
129
|
+
* carries them, and an alias sheds them only by an explicit `drop`. The seeds
|
|
130
|
+
* live in the `_base` layer under `content/en/PortfolioItem/`; the detail
|
|
131
|
+
* row's `contentDir` installs them (#6646 D1), exactly as `/use-cases/[slug]`
|
|
132
|
+
* serves `content/en/UseCase`.
|
|
133
|
+
*/
|
|
134
|
+
// NO_HAND_IMPLEMENT_OK: /build-starter operator-directed live pass (#6687).
|
|
135
|
+
const PORTFOLIO_ROWS = [
|
|
136
|
+
{ route: "/portfolio", content: ["content/en/PortfolioList/portfolio.mdx"] },
|
|
137
|
+
{ route: "/portfolio/[slug]", contentDir: "content/en/PortfolioItem" },
|
|
138
|
+
];
|
|
139
|
+
/**
|
|
140
|
+
* `minimalism-site`'s two OWN rows (#5589, shrunk from its own 17-row roster
|
|
141
|
+
* by #6757 once the `organization-service` shape carried a standard roster of
|
|
142
|
+
* its own): the deck's two `LandingPage` slugs, positioned by `insert` (D7)
|
|
143
|
+
* at the two points this alias interleaves them into the shape's row order
|
|
144
|
+
* (§ 1.2) — `/reports` before `/about`, `/referral` before `/faq`. Neither
|
|
145
|
+
* carries a `GATEABLE_SURFACES` entry: both are single-segment slugs served
|
|
146
|
+
* by the generic `[slug]` route (#5469 D2), the same mechanism Free's
|
|
147
|
+
* `/how-it-works` used.
|
|
148
|
+
*/
|
|
149
|
+
const REPORTS_ROW = {
|
|
150
|
+
route: "/reports",
|
|
151
|
+
content: ["content/en/LandingPage/reports.mdx"],
|
|
152
|
+
};
|
|
153
|
+
const REFERRAL_ROW = {
|
|
154
|
+
route: "/referral",
|
|
155
|
+
content: ["content/en/LandingPage/referral.mdx"],
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* `organization-service`'s own rows (#6757 D1), derived from
|
|
159
|
+
* `derive-roster.py --shape organization-service --primary-goal generate-leads
|
|
160
|
+
* --registry packages/schema/src/registry/entries.ts` at harness commit
|
|
161
|
+
* `7bdaf148e1b0e639cd90a80008955e55cc4aa2b5`, edited only by the deviations
|
|
162
|
+
* `site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md` § 3a
|
|
163
|
+
* records with their reasons. Row order matches `minimalism-site`'s (D3), so
|
|
164
|
+
* that alias's `differences` are additions and drops only.
|
|
165
|
+
*/
|
|
166
|
+
const ORGANIZATION_SERVICE_ROWS = [
|
|
167
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
168
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
169
|
+
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
170
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
171
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
172
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
173
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
174
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
175
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
176
|
+
{
|
|
177
|
+
route: "/purchase-policy",
|
|
178
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
/**
|
|
182
|
+
* `local-business-service`'s own rows (#6757 D1), derived the same way with
|
|
183
|
+
* `--shape local-business-service`. It has no `--template` alias of its own
|
|
184
|
+
* since #6789 retired the one alias that composed it; `--shape` is its only entry.
|
|
185
|
+
*/
|
|
186
|
+
const LOCAL_BUSINESS_SERVICE_ROWS = [
|
|
187
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
188
|
+
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
189
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
190
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
191
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
192
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
193
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
194
|
+
{
|
|
195
|
+
route: "/purchase-policy",
|
|
196
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
197
|
+
},
|
|
198
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
199
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
200
|
+
];
|
|
201
|
+
/**
|
|
202
|
+
* `person-service`'s own rows (#6758 D1, D3), derived from
|
|
203
|
+
* `derive-roster.py --shape person-service --primary-goal generate-leads
|
|
204
|
+
* --registry packages/schema/src/registry/entries.ts` at harness commit
|
|
205
|
+
* `7bdaf148e1b0e639cd90a80008955e55cc4aa2b5` (the vendored equivalent:
|
|
206
|
+
* `--entity-type person --offering-type services --primary-goal
|
|
207
|
+
* generate-leads --scale global`), edited only by the deviations
|
|
208
|
+
* `site-templates/shapes/person-service/TEMPLATE-MANIFEST.md` § 3a records
|
|
209
|
+
* with their reasons. Row order matches `local-business-service`'s (D3):
|
|
210
|
+
* services before about, because a consultant is hired for an engagement
|
|
211
|
+
* first.
|
|
212
|
+
*/
|
|
213
|
+
const PERSON_SERVICE_ROWS = [
|
|
214
|
+
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
215
|
+
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
216
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
217
|
+
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
218
|
+
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
219
|
+
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
220
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
221
|
+
{
|
|
222
|
+
route: "/purchase-policy",
|
|
223
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
224
|
+
},
|
|
225
|
+
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
226
|
+
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
227
|
+
];
|
|
228
|
+
/**
|
|
229
|
+
* Each buildable shape's standard roster (#6753 D3) — the rows an alias starts
|
|
230
|
+
* from before its `differences` apply.
|
|
231
|
+
*
|
|
232
|
+
* `organization-product` is today's base roster, the `/blog` teaser and the
|
|
233
|
+
* portfolio pair. `organization-service`, `local-business-service` (#6757)
|
|
234
|
+
* and `person-service` (#6758, roadmap § 6 Phase 2) are each their own rows,
|
|
235
|
+
* the `/blog` teaser and the portfolio pair.
|
|
236
|
+
*/
|
|
237
|
+
export const SHAPE_ROSTERS = Object.freeze({
|
|
238
|
+
"organization-product": [
|
|
239
|
+
...TEMPLATE_BASE_ROSTER,
|
|
240
|
+
FREE_BLOG_TEASER_ROW,
|
|
241
|
+
...PORTFOLIO_ROWS,
|
|
242
|
+
],
|
|
243
|
+
"organization-service": [
|
|
244
|
+
...ORGANIZATION_SERVICE_ROWS,
|
|
245
|
+
FREE_BLOG_TEASER_ROW,
|
|
246
|
+
...PORTFOLIO_ROWS,
|
|
247
|
+
],
|
|
248
|
+
"local-business-service": [
|
|
249
|
+
...LOCAL_BUSINESS_SERVICE_ROWS,
|
|
250
|
+
FREE_BLOG_TEASER_ROW,
|
|
251
|
+
...PORTFOLIO_ROWS,
|
|
252
|
+
],
|
|
253
|
+
"person-service": [
|
|
254
|
+
...PERSON_SERVICE_ROWS,
|
|
255
|
+
FREE_BLOG_TEASER_ROW,
|
|
256
|
+
...PORTFOLIO_ROWS,
|
|
257
|
+
],
|
|
258
|
+
});
|
|
259
|
+
/**
|
|
260
|
+
* The `--template` names and the grid coordinates each stands for (#6753) —
|
|
261
|
+
* the one table `TEMPLATE_MANIFESTS` and `RECOGNIZED_TEMPLATES` derive from,
|
|
262
|
+
* in the declaration order both keep. The plain name is the Pro one: it is
|
|
263
|
+
* the flagship and the demo (Sam, 2026-09-14, parent § D12).
|
|
264
|
+
*
|
|
265
|
+
* `workspace` appears in no module list. It is a Pro module, but an authed app
|
|
266
|
+
* surface contributing no PUBLIC page to a marketing site, and `modules` names
|
|
267
|
+
* what the roster uses (parent § D15). A Pro key unlocks it regardless of any
|
|
268
|
+
* template.
|
|
269
|
+
*
|
|
270
|
+
* `commerce` is a per-site add-on available at any level, so no alias exists
|
|
271
|
+
* FOR it (parent § D13); it still contributes rows to whichever alias takes
|
|
272
|
+
* it, through `mergeRoster`.
|
|
273
|
+
*
|
|
274
|
+
* Frozen (#5507): the registry composed from this table is also the issuer's
|
|
275
|
+
* authorization allowlist (spec 5480 § C7). A test needing a different table
|
|
276
|
+
* passes its own to `resolveTemplate(name, aliases)` rather than mutating
|
|
277
|
+
* this one.
|
|
278
|
+
*/
|
|
279
|
+
export const ALIASES = Object.freeze({
|
|
280
|
+
/**
|
|
281
|
+
* The Free template, and the mechanism's own proof (parent § D11): it
|
|
282
|
+
* requires only `marketing`, so the keyless merge path is exercised by a
|
|
283
|
+
* template we ship anyway rather than by a throwaway fixture. The bare
|
|
284
|
+
* `organization-product` shape — no differences at all.
|
|
285
|
+
*/
|
|
286
|
+
"marketing-site-free": {
|
|
287
|
+
shape: "organization-product",
|
|
288
|
+
design: "standard",
|
|
289
|
+
modules: ["marketing"],
|
|
290
|
+
categories: ["accounting", "legal", "technology"],
|
|
291
|
+
// The demo site carries the "Get started with this template" banner
|
|
292
|
+
// (operator ruling 2026-09-23); every other layout knob keeps its default.
|
|
293
|
+
layout: { announcementBanner: true },
|
|
294
|
+
},
|
|
295
|
+
/**
|
|
296
|
+
* The Pro flagship. Its module list is OFFERINGS § 4 offering 3's tiers line
|
|
297
|
+
* — "docs, scheduling and flows modules" — where "flows" is
|
|
298
|
+
* `signal-collectors` (`MODULE_SURFACES` maps it to `["flows"]`). It drops
|
|
299
|
+
* the shape's `/blog` teaser because docs-blog contributes the real `/blog`,
|
|
300
|
+
* and adds the signal-collectors sample rows ahead of the portfolio pair.
|
|
301
|
+
*/
|
|
302
|
+
"marketing-site": {
|
|
303
|
+
shape: "organization-product",
|
|
304
|
+
design: "standard",
|
|
305
|
+
modules: ["marketing", "docs-blog", "scheduling", "signal-collectors"],
|
|
306
|
+
// The flagship is the general-purpose template: it carries the whole
|
|
307
|
+
// registry, so every group tile on the hub has at least one template.
|
|
308
|
+
categories: [
|
|
309
|
+
"accounting",
|
|
310
|
+
"legal",
|
|
311
|
+
"consulting",
|
|
312
|
+
"hvac",
|
|
313
|
+
"roofing",
|
|
314
|
+
"plumbing",
|
|
315
|
+
"electrical",
|
|
316
|
+
"landscaping",
|
|
317
|
+
"auto-repair",
|
|
318
|
+
"real-estate",
|
|
319
|
+
"technology",
|
|
320
|
+
"medical-specialty",
|
|
321
|
+
],
|
|
322
|
+
differences: {
|
|
323
|
+
drop: ["/blog"],
|
|
324
|
+
add: SIGNAL_COLLECTORS_SAMPLE_ROWS,
|
|
325
|
+
before: "/portfolio",
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
/**
|
|
329
|
+
* Pro Plus — the Pro list plus `multi-tenant`, which is correctly in the
|
|
330
|
+
* list because it DOES contribute pages (the org and workspace surfaces).
|
|
331
|
+
* Its `pageContributions` is nonetheless unset today, deferred to its own
|
|
332
|
+
* instance, so this template's merged roster carries the same contributed
|
|
333
|
+
* rows as `marketing-site`'s and no more. That is a module which has
|
|
334
|
+
* declared no rows yet — visible in the diff — not a merge that dropped
|
|
335
|
+
* declared rows.
|
|
336
|
+
*/
|
|
337
|
+
"saas-product": {
|
|
338
|
+
shape: "organization-product",
|
|
339
|
+
design: "standard",
|
|
340
|
+
modules: [
|
|
341
|
+
"marketing",
|
|
342
|
+
"docs-blog",
|
|
343
|
+
"scheduling",
|
|
344
|
+
"signal-collectors",
|
|
345
|
+
"multi-tenant",
|
|
346
|
+
],
|
|
347
|
+
categories: ["technology", "medical-specialty"],
|
|
348
|
+
differences: {
|
|
349
|
+
drop: ["/blog"],
|
|
350
|
+
add: SIGNAL_COLLECTORS_SAMPLE_ROWS,
|
|
351
|
+
before: "/portfolio",
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
/**
|
|
355
|
+
* The second Pro template (#5589) — the reports-first, scroll-snap deck
|
|
356
|
+
* site. NOT `marketing-site` plus a module: its `modules` omit `docs-blog`,
|
|
357
|
+
* so the two Pro templates are siblings under `_base` (#5618 D2), never a
|
|
358
|
+
* lineage. Level still derives from `modules`: `scheduling` and
|
|
359
|
+
* `signal-collectors` are paid, so `templateDelivery` returns `"paid"`
|
|
360
|
+
* exactly as it does for `marketing-site`.
|
|
361
|
+
*
|
|
362
|
+
* It composes the `organization-service` shape roster (#6757) rather than
|
|
363
|
+
* the organization-product one: the deck home replaces the document-scroll
|
|
364
|
+
* home, and `/how-it-works`, the product page, `/pricing` and `/sign-in`
|
|
365
|
+
* are not pages this site has. The roster is what the
|
|
366
|
+
* template IS, so an unrostered page has neither a route directory
|
|
367
|
+
* (`rosterSurfaces`) nor its `_base`/overlay seed (#6646 D1).
|
|
368
|
+
*
|
|
369
|
+
* It declares NO `layout` block (#6638): the deck home, mark-only nav and
|
|
370
|
+
* centered footer are the `minimalism` design's, supplied by
|
|
371
|
+
* `DESIGN_LAYOUTS` from `design:` — the look any shape can wear. The
|
|
372
|
+
* roster rows the `organization-service` shape does not derive
|
|
373
|
+
* (`/reports`, `/referral`) are recorded with their reasons in this
|
|
374
|
+
* template's TEMPLATE-MANIFEST.md § 3a.
|
|
375
|
+
*
|
|
376
|
+
* `/reports` and `/referral` carry no `GATEABLE_SURFACES` entry and need
|
|
377
|
+
* none: both are single-segment `LandingPage` slugs served by the generic
|
|
378
|
+
* `[slug]` route (#5469 D2), the same mechanism Free's `/how-it-works`
|
|
379
|
+
* uses. `/reports/[slug]` (the reader) is the signal-collectors module's
|
|
380
|
+
* own contributed row.
|
|
381
|
+
*
|
|
382
|
+
* `/services/[slug]` declares its seed DIRECTORY as `contentDir`
|
|
383
|
+
* (`content/en/Service`, as `routes-map.ts` records it). The three
|
|
384
|
+
* samples ride the template tree unmapped, landing at that directory.
|
|
385
|
+
*
|
|
386
|
+
* Since #6757, `organization-service` carries a real standard roster
|
|
387
|
+
* (D1), so this alias's `differences` is additions and drops only: it
|
|
388
|
+
* drops the `/blog` teaser (a Pro alias does not upsell its own level,
|
|
389
|
+
* D8) and the portfolio pair (the reports are the proof, not a
|
|
390
|
+
* portfolio), adds the signal-collectors samples, and INSERTS its two own
|
|
391
|
+
* rows — `/reports` before `/about`, `/referral` before `/faq` (D7) — to
|
|
392
|
+
* reproduce its pre-#6757 row order (§ 1.2) exactly.
|
|
393
|
+
*/
|
|
394
|
+
"minimalism-site": {
|
|
395
|
+
shape: "organization-service",
|
|
396
|
+
design: "minimalism",
|
|
397
|
+
modules: ["marketing", "scheduling", "signal-collectors"],
|
|
398
|
+
categories: ["real-estate", "technology", "legal"],
|
|
399
|
+
differences: {
|
|
400
|
+
drop: ["/blog", "/portfolio", "/portfolio/[slug]"],
|
|
401
|
+
add: SIGNAL_COLLECTORS_SAMPLE_ROWS,
|
|
402
|
+
insert: [
|
|
403
|
+
{ before: "/about", rows: [REPORTS_ROW] },
|
|
404
|
+
{ before: "/faq", rows: [REFERRAL_ROW] },
|
|
405
|
+
],
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
/**
|
|
410
|
+
* The coordinates a keyless `--shape S` builds (#6757 D5) — the composed
|
|
411
|
+
* FREE manifest per shape, for a shape with no `--template` alias of its
|
|
412
|
+
* own. Frozen and `Partial`; `organization-product` needs none — its
|
|
413
|
+
* keyless tree is `marketing-site-free`'s (#6754 AC-2).
|
|
414
|
+
*
|
|
415
|
+
* No `differences` (a bare shape is its standard roster, D1) and no
|
|
416
|
+
* `layout`. Every category is a leaf of `packages/schema/src/categories.ts`,
|
|
417
|
+
* as `TemplateManifest.categories` requires. `person-service`'s single
|
|
418
|
+
* `consulting` category is the operator's disposition (2026-09-26,
|
|
419
|
+
* ai-launch-kit-internal#6758): the leaf did not exist when #6758's spec was
|
|
420
|
+
* written, and adding it replaced that spec's `["accounting", "legal",
|
|
421
|
+
* "technology"]` author-pick stand-in.
|
|
422
|
+
*/
|
|
423
|
+
export const SHAPE_STARTER_ALIASES = Object.freeze({
|
|
424
|
+
"organization-service": {
|
|
425
|
+
shape: "organization-service",
|
|
426
|
+
design: "standard",
|
|
427
|
+
modules: ["marketing"],
|
|
428
|
+
categories: ["accounting", "legal", "real-estate"],
|
|
429
|
+
},
|
|
430
|
+
"local-business-service": {
|
|
431
|
+
shape: "local-business-service",
|
|
432
|
+
design: "standard",
|
|
433
|
+
modules: ["marketing"],
|
|
434
|
+
categories: [
|
|
435
|
+
"hvac",
|
|
436
|
+
"roofing",
|
|
437
|
+
"plumbing",
|
|
438
|
+
"electrical",
|
|
439
|
+
"landscaping",
|
|
440
|
+
"auto-repair",
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
"person-service": {
|
|
444
|
+
shape: "person-service",
|
|
445
|
+
design: "standard",
|
|
446
|
+
modules: ["marketing"],
|
|
447
|
+
categories: ["consulting"],
|
|
448
|
+
},
|
|
449
|
+
});
|
package/dist/surfaces.d.ts
CHANGED
|
@@ -192,10 +192,10 @@ export declare const NAV_CONFIG_PATH = "apps/web/lib/nav-config.ts";
|
|
|
192
192
|
*
|
|
193
193
|
* The base items are the Free marketing-site chrome (#5469 D5, the approved
|
|
194
194
|
* chrome diff recorded on that card, re-pointed by #6658 D8):
|
|
195
|
-
* a Product flyout
|
|
196
|
-
* and About.
|
|
197
|
-
*
|
|
198
|
-
*
|
|
195
|
+
* a Product flyout in two columns (Features · Use Cases, #6721), then Blog,
|
|
196
|
+
* Pricing and About. The feature and use-case links ride the `features` and
|
|
197
|
+
* `use-cases` surfaces; `/blog` is always linked (the teaser or the docs-blog
|
|
198
|
+
* module serves it). Pricing is gateable
|
|
199
199
|
* surfaces: each item is emitted only when its surface is enabled (a template
|
|
200
200
|
* roster enables it, #5469 D10), so the nav still never links a page the
|
|
201
201
|
* scaffold does not carry.
|