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
package/dist/surfaces.js
CHANGED
|
@@ -81,13 +81,6 @@ export const CORE_ROUTE_DIRS = [
|
|
|
81
81
|
// scaffold carrying it and no content is byte-for-byte a scaffold with one
|
|
82
82
|
// more 404, nothing else.
|
|
83
83
|
`${ROUTE_ROOT}/[slug]`,
|
|
84
|
-
// #6658 D3 — the product's own detail page (`/software/product`, a
|
|
85
|
-
// SoftwareProduct → SoftwareApplication), which replaced the /features
|
|
86
|
-
// stand-in. Core for the same reason [slug] is: its content
|
|
87
|
-
// (`content/en/SoftwareProduct/product.mdx`) is in the always-copied overlay
|
|
88
|
-
// and the generated nav always links it, so every scaffold — template or
|
|
89
|
-
// not — must carry the route.
|
|
90
|
-
`${ROUTE_ROOT}/software`,
|
|
91
84
|
// #6084 D12 (the operator's shape-2 disposition) — the checkout return
|
|
92
85
|
// pair. The launchers pointing at them (`apps/mcp/src/tools/purchase.ts`,
|
|
93
86
|
// `apps/web/.../dev/purchase/purchase.actions.ts`) are ALREADY
|
|
@@ -180,6 +173,13 @@ export const GATEABLE_SURFACES = [
|
|
|
180
173
|
routes: [`${ROUTE_ROOT}/events`],
|
|
181
174
|
content: ["content/<locale>/EventsList", "content/<locale>/Event"],
|
|
182
175
|
},
|
|
176
|
+
{
|
|
177
|
+
// #6721 — the product's feature pages: a FeaturesList hub over one
|
|
178
|
+
// Feature page per feature. The Free roster enables it by its rows.
|
|
179
|
+
id: "features",
|
|
180
|
+
routes: [`${ROUTE_ROOT}/features`],
|
|
181
|
+
content: ["content/<locale>/FeaturesList", "content/<locale>/Feature"],
|
|
182
|
+
},
|
|
183
183
|
{
|
|
184
184
|
// API-backed (the flow engine); no MDX of its own.
|
|
185
185
|
id: "flows",
|
|
@@ -240,6 +240,11 @@ export const GATEABLE_SURFACES = [
|
|
|
240
240
|
routes: [`${ROUTE_ROOT}/partners`],
|
|
241
241
|
content: ["content/<locale>/PartnersList", "content/<locale>/Partner"],
|
|
242
242
|
},
|
|
243
|
+
{
|
|
244
|
+
id: "portfolio",
|
|
245
|
+
routes: [`${ROUTE_ROOT}/portfolio`],
|
|
246
|
+
content: ["content/<locale>/PortfolioList", "content/<locale>/PortfolioItem"],
|
|
247
|
+
},
|
|
243
248
|
{
|
|
244
249
|
// Module-LESS by construction (#5479 D16): no MODULE_SURFACES value names
|
|
245
250
|
// it, so a site template may enable it by roster alone. Same for
|
|
@@ -276,6 +281,13 @@ export const GATEABLE_SURFACES = [
|
|
|
276
281
|
routes: [`${ROUTE_ROOT}/services`],
|
|
277
282
|
content: ["content/<locale>/ServicesList", "content/<locale>/Service"],
|
|
278
283
|
},
|
|
284
|
+
{
|
|
285
|
+
// #6721 — the product's own page (#6658 D3), a gateable surface again now
|
|
286
|
+
// that the Free roster links /features instead of /software/product.
|
|
287
|
+
id: "software",
|
|
288
|
+
routes: [`${ROUTE_ROOT}/software`],
|
|
289
|
+
content: ["content/<locale>/SoftwareProduct"],
|
|
290
|
+
},
|
|
279
291
|
{
|
|
280
292
|
id: "tech-articles",
|
|
281
293
|
routes: [`${ROUTE_ROOT}/tech-articles`],
|
|
@@ -319,7 +331,10 @@ export const SURFACE_ALIASES = {
|
|
|
319
331
|
* so a site scaffolded with `--surfaces software` keeps working: its route
|
|
320
332
|
* is copied regardless.
|
|
321
333
|
*/
|
|
322
|
-
|
|
334
|
+
// #6721 — `software` is a gateable surface again (the Free roster now carries
|
|
335
|
+
// /features + /features/[slug] instead); the set is kept, empty, so the
|
|
336
|
+
// accept-and-drop read sites stay in place for the next promotion.
|
|
337
|
+
export const CORE_PROMOTED_SURFACES = new Set([]);
|
|
323
338
|
/** Canonical id for a `--surfaces` value, resolving a retired alias. */
|
|
324
339
|
function canonicalizeSurface(s) {
|
|
325
340
|
return SURFACE_ALIASES[s] ?? s;
|
|
@@ -509,6 +524,9 @@ export const ROUTE_SINCE = {
|
|
|
509
524
|
downloads: "0.0.0",
|
|
510
525
|
events: "0.0.0",
|
|
511
526
|
"events/[slug]": "0.0.0",
|
|
527
|
+
// #6721 — the feature pages, a new route pair at today's line.
|
|
528
|
+
features: "0.27.0",
|
|
529
|
+
"features/[slug]": "0.27.0",
|
|
512
530
|
faq: "0.0.0",
|
|
513
531
|
"flows/[slug]": "0.0.0",
|
|
514
532
|
"flows/[slug]/results/[payload]": "0.14.0",
|
|
@@ -531,6 +549,9 @@ export const ROUTE_SINCE = {
|
|
|
531
549
|
// #5479 — three genuinely new route directories, so they attach at today's
|
|
532
550
|
// fixed-group version rather than the "predates the manifest" 0.0.0 above,
|
|
533
551
|
// the same rule #5048 ("projects/apply") and #5014 ("(authed)") applied.
|
|
552
|
+
// #6687 — the before/after portfolio, a new route pair at today's line.
|
|
553
|
+
portfolio: "0.27.0",
|
|
554
|
+
"portfolio/[slug]": "0.27.0",
|
|
534
555
|
pricing: "0.22.0",
|
|
535
556
|
privacy: "0.22.0",
|
|
536
557
|
products: "0.0.0",
|
|
@@ -750,10 +771,10 @@ export const NAV_CONFIG_PATH = "apps/web/lib/nav-config.ts";
|
|
|
750
771
|
*
|
|
751
772
|
* The base items are the Free marketing-site chrome (#5469 D5, the approved
|
|
752
773
|
* chrome diff recorded on that card, re-pointed by #6658 D8):
|
|
753
|
-
* a Product flyout
|
|
754
|
-
* and About.
|
|
755
|
-
*
|
|
756
|
-
*
|
|
774
|
+
* a Product flyout in two columns (Features · Use Cases, #6721), then Blog,
|
|
775
|
+
* Pricing and About. The feature and use-case links ride the `features` and
|
|
776
|
+
* `use-cases` surfaces; `/blog` is always linked (the teaser or the docs-blog
|
|
777
|
+
* module serves it). Pricing is gateable
|
|
757
778
|
* surfaces: each item is emitted only when its surface is enabled (a template
|
|
758
779
|
* roster enables it, #5469 D10), so the nav still never links a page the
|
|
759
780
|
* scaffold does not carry.
|
|
@@ -781,49 +802,77 @@ export function renderNavConfig(enabled) {
|
|
|
781
802
|
s.id !== "blog" &&
|
|
782
803
|
s.id !== "use-cases");
|
|
783
804
|
const useCases = on.has("use-cases");
|
|
805
|
+
const features = on.has("features");
|
|
806
|
+
// #6721 (operator ruling 2026-09-25): the Product flyout is two columns —
|
|
807
|
+
// Features and Use Cases — each a heading over three label-only links. The
|
|
808
|
+
// `groups` render the desktop panel; `features` carries the same links for
|
|
809
|
+
// the mobile disclosure and the active-path match. "Use cases" left the top
|
|
810
|
+
// nav (it lives in the flyout and its own footer column).
|
|
811
|
+
const featureLinks = features
|
|
812
|
+
? [
|
|
813
|
+
' { labelKey: "feature1", path: "/features/feature-1" },',
|
|
814
|
+
' { labelKey: "feature2", path: "/features/feature-2" },',
|
|
815
|
+
' { labelKey: "feature3", path: "/features/feature-3" },',
|
|
816
|
+
]
|
|
817
|
+
: [];
|
|
818
|
+
const useCaseLinks = useCases
|
|
819
|
+
? [
|
|
820
|
+
' { labelKey: "useCase1", path: "/use-cases/persona-1" },',
|
|
821
|
+
' { labelKey: "useCase2", path: "/use-cases/persona-2" },',
|
|
822
|
+
' { labelKey: "useCase3", path: "/use-cases/persona-3" },',
|
|
823
|
+
]
|
|
824
|
+
: [];
|
|
825
|
+
const indent = (line) => ` ${line}`;
|
|
826
|
+
const group = (headingKey, links) => links.length === 0
|
|
827
|
+
? []
|
|
828
|
+
: [
|
|
829
|
+
" {",
|
|
830
|
+
` headingKey: "${headingKey}",`,
|
|
831
|
+
" items: [",
|
|
832
|
+
...links.map(indent),
|
|
833
|
+
" ],",
|
|
834
|
+
" },",
|
|
835
|
+
];
|
|
784
836
|
const entries = [
|
|
785
837
|
" {",
|
|
786
838
|
' labelKey: "product",',
|
|
787
839
|
" flyout: {",
|
|
788
|
-
// SOFT_LOCK_OK: #6508 — width "panel" (D4/D5): a fixed 640px
|
|
789
|
-
// grid, replacing the "list"/"trigger" one-column menu. `presentation` is
|
|
790
|
-
// omitted — it defaults to "grid" (D5). The `docs` action is dropped (it
|
|
791
|
-
// duplicated the first feature's /how-it-works destination, § 1.4).
|
|
840
|
+
// SOFT_LOCK_OK: #6508 — width "panel" (D4/D5): a fixed 640px panel.
|
|
792
841
|
' width: "panel",',
|
|
793
842
|
" features: [",
|
|
794
|
-
...
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
843
|
+
...featureLinks,
|
|
844
|
+
...useCaseLinks,
|
|
845
|
+
" ],",
|
|
846
|
+
" groups: [",
|
|
847
|
+
...group("flyoutFeaturesHeading", featureLinks),
|
|
848
|
+
...group("flyoutUseCasesHeading", useCaseLinks),
|
|
799
849
|
" ],",
|
|
800
850
|
" actions: [],",
|
|
801
851
|
" },",
|
|
802
852
|
" },",
|
|
803
|
-
// Operator ruling 2026-09-
|
|
853
|
+
// Operator ruling 2026-09-25: Product · Blog · Pricing · About.
|
|
804
854
|
// `/blog` is always linked — the `blog` surface serves the real route, and
|
|
805
855
|
// with it off the `[slug]` route serves the overlay's module page.
|
|
806
|
-
...(useCases ? [' { labelKey: "useCases", path: "/use-cases" },'] : []),
|
|
807
856
|
' { labelKey: "blog", path: "/blog" },',
|
|
808
857
|
...(on.has("pricing") ? [' { labelKey: "pricing", path: "/pricing" },'] : []),
|
|
809
858
|
' { labelKey: "about", path: "/about" },',
|
|
810
859
|
...linked.map((s) => ` { labelKey: "${s.navLabelKey}", path: "/${s.id}" },`),
|
|
811
860
|
];
|
|
812
|
-
// The footer's column groups (operator
|
|
813
|
-
//
|
|
814
|
-
//
|
|
815
|
-
//
|
|
816
|
-
//
|
|
817
|
-
// Glossary and Newsletter (#6658 D8) each
|
|
861
|
+
// The footer's column groups (operator rulings 2026-09-23 + 2026-09-25):
|
|
862
|
+
// Site pages, Features, Use Cases, Resources. Pricing rides the same
|
|
863
|
+
// `pricing` gate as the header item; `/blog` is always linked (above). The
|
|
864
|
+
// Features column links the three feature pages and the /features hub; the
|
|
865
|
+
// Use Cases column the three use cases and the /use-cases hub — each rides
|
|
866
|
+
// its surface's gate. Book a call, Glossary and Newsletter (#6658 D8) each
|
|
867
|
+
// ride their own surface's gate.
|
|
818
868
|
const footerEntries = [
|
|
819
869
|
" {",
|
|
820
870
|
' headingKey: "footerSitePagesHeading",',
|
|
821
871
|
" items: [",
|
|
822
|
-
' { labelKey: "features", path: "/
|
|
872
|
+
...(features ? [' { labelKey: "features", path: "/features" },'] : []),
|
|
823
873
|
...(on.has("pricing")
|
|
824
874
|
? [' { labelKey: "pricing", path: "/pricing" },']
|
|
825
875
|
: []),
|
|
826
|
-
...(useCases ? [' { labelKey: "useCases", path: "/use-cases" },'] : []),
|
|
827
876
|
' { labelKey: "about", path: "/about" },',
|
|
828
877
|
' { labelKey: "contact", path: "/contact" },',
|
|
829
878
|
...(on.has("book-a-call")
|
|
@@ -831,17 +880,28 @@ export function renderNavConfig(enabled) {
|
|
|
831
880
|
: []),
|
|
832
881
|
" ],",
|
|
833
882
|
" },",
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
883
|
+
...(features
|
|
884
|
+
? [
|
|
885
|
+
" {",
|
|
886
|
+
' headingKey: "footerFeaturesHeading",',
|
|
887
|
+
" items: [",
|
|
888
|
+
...featureLinks.map((l) => l.slice(2)),
|
|
889
|
+
' { labelKey: "allFeatures", path: "/features" },',
|
|
890
|
+
" ],",
|
|
891
|
+
" },",
|
|
892
|
+
]
|
|
893
|
+
: []),
|
|
894
|
+
...(useCases
|
|
895
|
+
? [
|
|
896
|
+
" {",
|
|
897
|
+
' headingKey: "footerUseCasesHeading",',
|
|
898
|
+
" items: [",
|
|
899
|
+
...useCaseLinks.map((l) => l.slice(2)),
|
|
900
|
+
' { labelKey: "allUseCases", path: "/use-cases" },',
|
|
901
|
+
" ],",
|
|
902
|
+
" },",
|
|
903
|
+
]
|
|
904
|
+
: []),
|
|
845
905
|
" {",
|
|
846
906
|
' headingKey: "footerResourcesHeading",',
|
|
847
907
|
" items: [",
|
|
@@ -878,7 +938,6 @@ export function renderNavConfig(enabled) {
|
|
|
878
938
|
// \`apps/web/messages/<locale>.json\`. Paths are locale-agnostic — Nav prefixes
|
|
879
939
|
// them with the active locale at render.
|
|
880
940
|
${navItemImport}
|
|
881
|
-
import { HelpCircle, Layers, Sparkles } from "lucide-react";
|
|
882
941
|
|
|
883
942
|
export const navItems: NavItem[] = [
|
|
884
943
|
${entries.join("\n")}
|
|
@@ -18,6 +18,7 @@ import type { CategorySlug } from "@working-theory/schema/categories";
|
|
|
18
18
|
import { type PageRosterRow } from "./module-architecture.js";
|
|
19
19
|
import type { ModuleName } from "./parse-args.js";
|
|
20
20
|
import type { TemplateLayout } from "./site-chrome.js";
|
|
21
|
+
import { type BuildableShape, type TemplateAlias } from "./starter-grid.js";
|
|
21
22
|
/**
|
|
22
23
|
* The closed **shape** enum (starter-template contract § The three axes,
|
|
23
24
|
* operator-disposed 2026-09-24) — `<primary node>-<offering node>` in
|
|
@@ -155,21 +156,10 @@ export declare class TemplateError extends Error {
|
|
|
155
156
|
constructor(message: string);
|
|
156
157
|
}
|
|
157
158
|
/**
|
|
158
|
-
* The
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* `workspace` appears in none of them. It is a Pro module, but an authed app
|
|
163
|
-
* surface contributing no PUBLIC page to a marketing site, and `requires`
|
|
164
|
-
* names what the roster uses (parent § D15). A Pro key unlocks it regardless
|
|
165
|
-
* of any template. `ModuleName` could express it either way — `workspace` is
|
|
166
|
-
* one of the seven `RECOGNIZED_MODULES` names; it is simply not one any
|
|
167
|
-
* template's fixed `requires` list names.
|
|
168
|
-
*
|
|
169
|
-
* `commerce` is likewise in none of them: it is a per-site add-on available at
|
|
170
|
-
* any level, so a template for it would contradict the offering model and
|
|
171
|
-
* multiply the set combinatorially (parent § D13). It still contributes rows
|
|
172
|
-
* to whichever template takes it, through `mergeRoster` below.
|
|
159
|
+
* The declared templates, each composed once at load from its `ALIASES` row
|
|
160
|
+
* (#6753) — no manifest here is hand-typed, so a template's shape, design,
|
|
161
|
+
* modules and roster have one authority: `starter-grid.ts`. Declaration order
|
|
162
|
+
* is `ALIASES`'s, which is `RECOGNIZED_TEMPLATES`'s.
|
|
173
163
|
*
|
|
174
164
|
* Frozen (#5507): this registry is also the issuer's authorization allowlist
|
|
175
165
|
* (spec 5480 § C7) — a mutable global there could be monkey-patched at
|
|
@@ -177,8 +167,37 @@ export declare class TemplateError extends Error {
|
|
|
177
167
|
* fixture rather than mutating this one.
|
|
178
168
|
*/
|
|
179
169
|
export declare const TEMPLATE_MANIFESTS: Readonly<Record<string, TemplateManifest>>;
|
|
180
|
-
/**
|
|
181
|
-
|
|
170
|
+
/**
|
|
171
|
+
* The composed FREE manifest per shape with no `--template` alias of its own
|
|
172
|
+
* (#6757 D5) — the coordinates a keyless `--shape S` builds. `Object.freeze`d,
|
|
173
|
+
* composed once at load by the same module-private `composeManifest` over
|
|
174
|
+
* `SHAPE_STARTER_ALIASES`, each manifest's `name` the shape. Data holding
|
|
175
|
+
* composed manifests, the status D5 gives `TEMPLATE_MANIFESTS`;
|
|
176
|
+
* `resolveTemplate` stays the only exported function that yields a
|
|
177
|
+
* template's roster, and its behavior is unchanged — it does NOT resolve a
|
|
178
|
+
* shape name (NFR-3, the issuer allowlist stays `TEMPLATE_MANIFESTS`-only).
|
|
179
|
+
*/
|
|
180
|
+
export declare const SHAPE_STARTERS: Readonly<Partial<Record<BuildableShape, TemplateManifest>>>;
|
|
181
|
+
/**
|
|
182
|
+
* Where a starter's files live under `site-templates/` (#6757 D5) — the one
|
|
183
|
+
* place that says so. A `SHAPE_STARTERS` key (a bare-shape starter with no
|
|
184
|
+
* `--template` alias) lives at `shapes/<name>`, out of the template showcase
|
|
185
|
+
* (§ 1.6); every other name (a declared `--template` alias) is unchanged.
|
|
186
|
+
*/
|
|
187
|
+
export declare function templateTreeDir(name: string): string;
|
|
188
|
+
/**
|
|
189
|
+
* Look up a declared template — the one exported function that yields a
|
|
190
|
+
* template's roster (#6753 AC-1); `TEMPLATE_MANIFESTS`, the frozen record it
|
|
191
|
+
* reads, holds only manifests composed from `ALIASES`.
|
|
192
|
+
*
|
|
193
|
+
* With no `aliases`, returns the frozen `TEMPLATE_MANIFESTS` entry itself.
|
|
194
|
+
* With an injected alias table — the `resolveTemplateLineage` precedent
|
|
195
|
+
* (#5507) — composes `aliases[name]` against the shipped shape rosters, so a
|
|
196
|
+
* test exercises the composer's refusals without touching the shipped table.
|
|
197
|
+
*
|
|
198
|
+
* @throws TemplateError on an undeclared name, or a malformed injected alias.
|
|
199
|
+
*/
|
|
200
|
+
export declare function resolveTemplate(name: string, aliases?: Readonly<Record<string, TemplateAlias>>): TemplateManifest;
|
|
182
201
|
/**
|
|
183
202
|
* Resolve a template's `extends` chain — `[name, …ancestors, "_base"]` — in
|
|
184
203
|
* the client registry, before any fetch (#5618 D2). `_base` is the only
|