create-ailk 0.6.0 → 0.7.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 -5
- package/component-catalog.json +146 -21
- package/component-catalog.md +9 -6
- package/dist/add-module-core.d.ts +22 -0
- package/dist/add-module-core.js +50 -0
- package/dist/add-module.d.ts +89 -0
- package/dist/add-module.js +334 -0
- package/dist/category-profile.d.ts +126 -0
- package/dist/category-profile.js +262 -0
- package/dist/cli.js +124 -13
- package/dist/copy.d.ts +14 -0
- package/dist/copy.js +38 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -1
- package/dist/lib/extract-module-bundle.d.ts +76 -2
- package/dist/lib/extract-module-bundle.js +219 -8
- package/dist/lib/license-key-files.d.ts +15 -0
- package/dist/lib/license-key-files.js +102 -0
- package/dist/lib/module-license-gate.d.ts +6 -1
- package/dist/lib/module-license-gate.js +6 -1
- package/dist/lib/pro-callout.d.ts +16 -10
- package/dist/lib/pro-callout.js +27 -4
- package/dist/license-set.d.ts +34 -0
- package/dist/license-set.js +194 -0
- package/dist/module-architecture.d.ts +20 -0
- package/dist/module-architecture.js +77 -19
- package/dist/modules/commerce/0.6.0.tar.gz +0 -0
- package/dist/modules/commerce/0.6.1.tar.gz +0 -0
- package/dist/modules/docs-blog/0.6.0.tar.gz +0 -0
- package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
- package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
- package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
- package/dist/modules/multi-tenant/0.6.0.tar.gz +0 -0
- package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
- package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
- package/dist/modules/scheduling/0.6.0.tar.gz +0 -0
- package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
- package/dist/modules/signal-collectors/0.6.0.tar.gz +0 -0
- package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
- package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
- package/dist/modules/workspace/0.6.0.tar.gz +0 -0
- package/dist/modules/workspace/0.6.1.tar.gz +0 -0
- package/dist/parse-args.d.ts +7 -0
- package/dist/parse-args.js +23 -1
- package/dist/programmatic.d.ts +46 -0
- package/dist/programmatic.js +144 -19
- package/dist/site-chrome.d.ts +18 -7
- package/dist/site-chrome.js +32 -14
- package/dist/site-roster.d.ts +127 -0
- package/dist/site-roster.js +494 -0
- package/dist/surfaces.d.ts +20 -7
- package/dist/surfaces.js +149 -28
- package/dist/sync-routes.d.ts +9 -0
- package/dist/sync-routes.js +2 -2
- package/dist/template-manifest.d.ts +58 -2
- package/dist/template-manifest.js +196 -69
- package/package.json +6 -4
- package/site-templates/_base/content/en/BookCall/book-call.mdx +53 -0
- package/site-templates/_base/content/en/GlossaryList/glossary.mdx +66 -0
- package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +68 -0
- package/site-templates/_base/content/en/Pricing/pricing.mdx +71 -62
- package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +2 -3
- package/site-templates/_base/content/en/TermsPage/terms.mdx +2 -3
- package/site-templates/_base/content/en/UseCase/first-use-case.mdx +23 -0
- package/site-templates/_base/content/en/UseCase/second-use-case.mdx +23 -0
- package/site-templates/_base/content/en/UseCase/third-use-case.mdx +23 -0
- package/site-templates/designs/minimalism/DESIGN.md +162 -0
- package/site-templates/designs/standard/DESIGN.md +162 -0
- package/site-templates/marketing-site/DESIGN.md +162 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +312 -57
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +209 -90
- package/site-templates/marketing-site/ailk-template.json +1 -0
- package/site-templates/marketing-site-free/DESIGN.md +162 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +260 -66
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +294 -114
- package/site-templates/marketing-site-free/ailk-template.json +3 -2
- package/site-templates/minimalism-site/DESIGN.md +162 -0
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +246 -19
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +185 -51
- package/site-templates/minimalism-site/ailk-template.json +3 -2
- package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +53 -0
- package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +3 -37
- package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +124 -0
- package/site-templates/saas-product/DESIGN.md +162 -0
- package/site-templates/simple-service/DESIGN.md +162 -0
- package/site-templates/simple-service/TEMPLATE-MANIFEST.json +135 -26
- package/site-templates/simple-service/TEMPLATE-MANIFEST.md +114 -59
- package/site-templates/simple-service/ailk-template.json +4 -3
- package/site-templates/simple-service/content/en/BookCall/book-call.mdx +53 -0
- package/site-templates/simple-service/content/en/ContactPage/contact.mdx +1 -36
- package/site-templates/simple-service/content/en/PurchasePolicyPage/purchase-policy.mdx +124 -0
- package/templates/.claude/settings.json +15 -0
- package/templates/.claude/skills/README.md +8 -8
- package/templates/.claude/skills/{scaffold-auth → add-auth}/SKILL.md +7 -7
- package/templates/.claude/skills/{scaffold-auth → add-auth}/references/env-vars.md +2 -2
- package/templates/.claude/skills/{scaffold-auth → add-auth}/references/oauth-app-setup.md +3 -3
- package/templates/.claude/skills/{scaffold-page → add-page}/SKILL.md +76 -62
- package/templates/.claude/skills/add-page/references/page-types.md +111 -0
- package/templates/.claude/skills/{scaffold-page → add-page}/templates/content.mdx.tmpl +4 -4
- package/templates/.claude/skills/{scaffold-page → add-page}/templates/route.tsx.tmpl +1 -1
- package/templates/.claude/skills/{audit-site → check-site}/SKILL.md +16 -17
- package/templates/.claude/skills/{audit-site → check-site}/references/common-errors.md +3 -3
- package/templates/.claude/skills/{audit-site → check-site}/references/findings-glossary.md +16 -14
- package/templates/.claude/skills/{audit-site → check-site}/references/severity-levels.md +1 -1
- package/templates/.claude/skills/fill-page/SKILL.md +180 -0
- package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +80 -0
- package/templates/.claude/skills/fill-page/references/section-sources.md +41 -0
- package/templates/.claude/skills/{provision-config → setup-deploy}/SKILL.md +8 -8
- package/templates/.claude/skills/{provision-config → setup-deploy}/references/env-vars-template.md +2 -2
- package/templates/.claude/skills/{provision-config → setup-deploy}/references/runbook-template.md +8 -8
- package/templates/.claude/skills/{provision-config → setup-deploy}/references/vercel-json-template.md +1 -1
- package/templates/.claude/skills/upgrade-plan/SKILL.md +117 -0
- package/templates/.claude/skills/upgrade-plan/references/options.md +24 -0
- package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +527 -0
- package/templates/.github/workflows/ci.yml +5 -0
- package/templates/CLAUDE.md +10 -5
- package/templates/DESIGN.md +162 -0
- package/templates/README.md +134 -38
- package/templates/apps/api/.env.example +2 -1
- package/templates/apps/api/package.json +1 -1
- package/templates/apps/api/src/config/__tests__/index.test.ts +37 -2
- package/templates/apps/api/src/config/index.ts +19 -6
- package/templates/apps/api/src/lib/license-key-store.ts +45 -0
- package/templates/apps/api/src/lib/site.ts +5 -3
- package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +97 -0
- package/templates/apps/api/src/middleware/auth.ts +9 -0
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +127 -5
- package/templates/apps/api/src/routes/content/get-page.ts +86 -2
- package/templates/apps/api/src/server.ts +6 -0
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +75 -1
- package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +57 -9
- package/templates/apps/mcp/package.json +2 -1
- package/templates/apps/mcp/src/index.ts +7 -0
- package/templates/apps/mcp/src/lib/audit-single-page.ts +36 -10
- package/templates/apps/mcp/src/lib/license-key-store.ts +45 -0
- package/templates/apps/web/PRODUCT.md +86 -0
- package/templates/apps/web/__tests__/setup.ts +18 -0
- package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +10 -2
- package/templates/apps/web/app/[locale]/(auth)/layout.tsx +2 -2
- package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +10 -4
- package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +22 -14
- package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +26 -18
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +12 -4
- package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +35 -4
- package/templates/apps/web/app/[locale]/[slug]/page.tsx +49 -9
- package/templates/apps/web/app/[locale]/book-a-call/page.tsx +50 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +94 -33
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +53 -23
- package/templates/apps/web/app/[locale]/contact/__tests__/ContactForm.test.tsx +96 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +84 -2
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +5 -6
- package/templates/apps/web/app/[locale]/contact/page.tsx +25 -7
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +4 -5
- package/templates/apps/web/app/[locale]/glossary/page.tsx +50 -0
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/how-to/page.tsx +25 -15
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/layout.tsx +113 -51
- package/templates/apps/web/app/[locale]/newsletter/page.tsx +50 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +4 -5
- package/templates/apps/web/app/[locale]/{shipping → purchase-policy}/page.tsx +15 -10
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +4 -5
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +14 -1
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/software/page.tsx +25 -15
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/tech-articles/page.tsx +25 -15
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/use-cases/[slug]/page.tsx +48 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +3 -4
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +15 -2
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/whitepapers/page.tsx +25 -15
- package/templates/apps/web/app/error-fallback.tsx +17 -45
- package/templates/apps/web/app/not-found.tsx +14 -38
- package/templates/apps/web/app/og/route.tsx +6 -0
- package/templates/apps/web/eslint.config.mjs +3 -0
- package/templates/apps/web/instrumentation.ts +14 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +135 -20
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +38 -0
- package/templates/apps/web/lib/license-key-store.ts +52 -0
- package/templates/apps/web/lib/nav-config.ts +64 -12
- package/templates/apps/web/lib/prisma-for-auth.ts +9 -6
- package/templates/apps/web/lib/site-brand.tsx +4 -8
- package/templates/apps/web/lib/site-chrome.ts +3 -3
- package/templates/apps/web/lib/site-identity.ts +134 -0
- package/templates/apps/web/lib/site-theme.ts +11 -0
- package/templates/apps/web/messages/en.json +52 -37
- package/templates/apps/web/middleware.ts +1 -1
- package/templates/apps/web/public/android-chrome-192x192.png +0 -0
- package/templates/apps/web/public/android-chrome-512x512.png +0 -0
- package/templates/apps/web/public/apple-touch-icon.png +0 -0
- package/templates/apps/web/public/favicon-16x16.png +0 -0
- package/templates/apps/web/public/favicon-32x32.png +0 -0
- package/templates/apps/web/public/favicon.ico +0 -0
- package/templates/apps/web/public/favicon.svg +3 -3
- package/templates/apps/web/public/logomark.svg +6 -3
- package/templates/apps/web/public/logos/ai-launch-kit-light.svg +4 -0
- package/templates/apps/web/public/logos/ai-launch-kit.svg +4 -0
- package/templates/apps/web/public/logos/atomic-agent-light.svg +4 -0
- package/templates/apps/web/public/logos/atomic-agent.svg +4 -0
- package/templates/apps/web/public/logos/salessmyth-light.svg +4 -0
- package/templates/apps/web/public/logos/salessmyth.svg +4 -0
- package/templates/apps/web/public/site.webmanifest +4 -4
- package/templates/apps/web/public/wordmark-light.svg +4 -0
- package/templates/apps/web/public/wordmark.svg +3 -3
- package/templates/apps/web/security-headers.config.ts +5 -1
- package/templates/apps/web/src/lib/commerce-sections.ts +35 -3
- package/templates/content/_site.mdx +41 -3
- package/templates/content/en/AboutPage/about.mdx +150 -144
- package/templates/content/en/BlogList/blog.mdx +105 -0
- package/templates/content/en/ContactPage/contact.mdx +44 -85
- package/templates/content/en/FAQPage/faq.mdx +86 -57
- package/templates/content/en/HomePage/home.mdx +276 -217
- package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +182 -0
- package/templates/content/en/SoftwareProduct/product.mdx +175 -0
- package/templates/content/en/UseCasesList/use-cases.mdx +170 -0
- package/templates/database/CHANGELOG.md +14 -0
- package/templates/database/package.json +3 -2
- package/templates/package.json +3 -1
- package/templates/tools/lint-architecture.ts +315 -0
- package/templates/tools/tsconfig.json +14 -0
- package/versions.json +33 -33
- package/templates/.claude/skills/add-schema/SKILL.md +0 -277
- package/templates/.claude/skills/add-schema/references/conflict-handling.md +0 -200
- package/templates/.claude/skills/add-schema/references/file-finding.md +0 -123
- package/templates/.claude/skills/add-schema/references/schema-types.md +0 -234
- package/templates/.claude/skills/scaffold-page/references/page-types.md +0 -169
- package/templates/.claude/skills/suggest-site-pages/SKILL.md +0 -242
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +0 -287
- package/templates/apps/web/app/[locale]/cancellation/page.tsx +0 -44
- package/templates/apps/web/app/[locale]/returns/page.tsx +0 -44
- package/templates/apps/web/public/logo-dark.svg +0 -21
- package/templates/apps/web/public/logo-light.svg +0 -21
- package/templates/content/en/CancellationPolicyPage/cancellation.mdx +0 -108
- package/templates/content/en/LandingPage/blog.mdx +0 -83
- package/templates/content/en/LandingPage/features.mdx +0 -103
- package/templates/content/en/LandingPage/how-it-works.mdx +0 -143
- package/templates/content/en/ReturnsPolicyPage/returns.mdx +0 -108
- package/templates/content/en/ShippingPolicyPage/shipping.mdx +0 -108
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
import { classifyModules } from "./lib/module-tier.js";
|
|
2
2
|
import { MODULE_SLICES, normalizeModules, } from "./module-architecture.js";
|
|
3
|
+
/**
|
|
4
|
+
* The closed **shape** enum (starter-template contract § The three axes,
|
|
5
|
+
* operator-disposed 2026-09-24) — `<primary node>-<offering node>` in
|
|
6
|
+
* schema.org terms, kebab-cased. Declared beside `TemplateManifest`, the same
|
|
7
|
+
* pattern `ModuleName` uses in `parse-args.ts`: a `readonly [...] as const`
|
|
8
|
+
* array plus its derived literal-union type, so an unrecognized value fails
|
|
9
|
+
* type-check rather than a runtime validation.
|
|
10
|
+
*/
|
|
11
|
+
export const STARTER_SHAPES = [
|
|
12
|
+
"organization-product",
|
|
13
|
+
"organization-service",
|
|
14
|
+
"local-business-service",
|
|
15
|
+
"local-business-product",
|
|
16
|
+
"person-service",
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* The closed **design** enum (same contract section) — the look applied to
|
|
20
|
+
* any shape; orthogonal to it by construction.
|
|
21
|
+
*/
|
|
22
|
+
export const STARTER_DESIGNS = ["standard", "minimalism"];
|
|
23
|
+
/**
|
|
24
|
+
* Each design's layout knobs (#6638) — the part of a design that is chrome,
|
|
25
|
+
* so a template names `design:` instead of re-typing a `layout` block, and any
|
|
26
|
+
* shape can wear any design. `resolveSiteChrome(layout, design)` reads it:
|
|
27
|
+
* an explicit `TemplateManifest.layout` wins field by field, then this, then
|
|
28
|
+
* `DEFAULT_SITE_CHROME`. `standard` declares nothing — it IS the defaults, so
|
|
29
|
+
* spelling them out here would be a second copy of them to drift. A plain
|
|
30
|
+
* object, not a file: this module touches no disk. The design's documented
|
|
31
|
+
* look lives in `site-templates/designs/<design>/DESIGN.md`.
|
|
32
|
+
*/
|
|
33
|
+
export const DESIGN_LAYOUTS = {
|
|
34
|
+
standard: {},
|
|
35
|
+
minimalism: {
|
|
36
|
+
nav: "mark-only",
|
|
37
|
+
footer: "centered",
|
|
38
|
+
announcementBanner: false,
|
|
39
|
+
home: "deck",
|
|
40
|
+
},
|
|
41
|
+
};
|
|
3
42
|
/**
|
|
4
43
|
* The base layer's directory under `site-templates/` (#5618 D1) — the seed
|
|
5
44
|
* files every template reaches by declaring `extends`, installed by
|
|
@@ -12,6 +51,16 @@ import { MODULE_SLICES, normalizeModules, } from "./module-architecture.js";
|
|
|
12
51
|
* the directory-scanning tests key their skip on.
|
|
13
52
|
*/
|
|
14
53
|
export const BASE_LAYER_DIR = "_base";
|
|
54
|
+
/**
|
|
55
|
+
* Whether a merged roster declares one scaffold-relative content file
|
|
56
|
+
* (#6646 D1): named by a row's `content`, or under a row's `contentDir`.
|
|
57
|
+
* The one predicate the scaffold's per-row install and the manifest
|
|
58
|
+
* generator's install-diff both read, so the two cannot disagree.
|
|
59
|
+
*/
|
|
60
|
+
export function rosterDeclares(roster, path) {
|
|
61
|
+
return roster.some((row) => (row.content ?? []).includes(path) ||
|
|
62
|
+
(row.contentDir !== undefined && path.startsWith(`${row.contentDir}/`)));
|
|
63
|
+
}
|
|
15
64
|
/** Thrown on an undeclared template name or a route claimed twice. Mirrors `SurfaceError`'s shape. */
|
|
16
65
|
export class TemplateError extends Error {
|
|
17
66
|
constructor(message) {
|
|
@@ -20,32 +69,62 @@ export class TemplateError extends Error {
|
|
|
20
69
|
}
|
|
21
70
|
}
|
|
22
71
|
/**
|
|
23
|
-
* The
|
|
24
|
-
*
|
|
72
|
+
* The three pages every starter carries whatever its shape (#6658 D5,
|
|
73
|
+
* `docs/decisions/starter-roster-page-set.md` D4/D7): a glossary, a newsletter
|
|
74
|
+
* signup and a book-a-call page. Each is a module-less `GATEABLE_SURFACES`
|
|
75
|
+
* entry the roster enables, with its seed in `_base`. A template carrying the
|
|
76
|
+
* scheduling module overrides `BookCall/book-call.mdx` in its own tree, so the
|
|
77
|
+
* call to action opens `/meet` rather than `/contact`.
|
|
78
|
+
*/
|
|
79
|
+
const SHAPE_INDEPENDENT_ROWS = [
|
|
80
|
+
{ route: "/glossary", content: ["content/en/GlossaryList/glossary.mdx"] },
|
|
81
|
+
{
|
|
82
|
+
route: "/newsletter",
|
|
83
|
+
content: ["content/en/NewsletterSignup/newsletter.mdx"],
|
|
84
|
+
},
|
|
85
|
+
{ route: "/book-a-call", content: ["content/en/BookCall/book-call.mdx"] },
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* The rows every `organization-product` template brings itself — one declared
|
|
89
|
+
* page set, whichever layer carries each seed. Re-derived by #6658 from the
|
|
90
|
+
* standard (`derive-roster.py --entity-type software --offering-type software
|
|
91
|
+
* --primary-goal convert --scale global`, the `--shape organization-product`
|
|
92
|
+
* equivalent), edited only by the deviations the Free manifest's § 3a records
|
|
93
|
+
* with their reasons. With a template named, `scaffold()` keeps a `_base` or
|
|
94
|
+
* overlay seed only when a merged roster row names it (#6646 D1): the roster
|
|
95
|
+
* decides what installs, and the manifest generator's `--check` proves it.
|
|
96
|
+
*
|
|
97
|
+
* Two layers, one roster:
|
|
25
98
|
*
|
|
26
|
-
*
|
|
99
|
+
* - `/`, `/software/[slug]`, `/use-cases`, `/about`, `/faq`, `/contact` and
|
|
100
|
+
* `/purchase-policy` take their content from the overlay
|
|
101
|
+
* (`template-overlay/content/en/**`, copied whole into `templates/` by
|
|
102
|
+
* `build-templates.mjs`). `/software/[slug]` is the product's own detail
|
|
103
|
+
* page (`/software/product`, a SoftwareProduct), which replaced the
|
|
104
|
+
* `/features` stand-in (#6658 D3); its route is core, like `/about`.
|
|
105
|
+
* `/use-cases` lists the three UseCase pages at `/use-cases/[slug]`
|
|
106
|
+
* (#6658 D4).
|
|
107
|
+
* - `/pricing`, `/privacy`, `/terms`, `/glossary`, `/newsletter`,
|
|
108
|
+
* `/book-a-call` and the three UseCase pages take their content from the
|
|
109
|
+
* base layer (`site-templates/_base/content/**`, #5618 D1), which every
|
|
110
|
+
* template reaches by declaring `extends` — installed before the module
|
|
111
|
+
* bundles and the template's own tree, so a template may override a base
|
|
112
|
+
* page by shipping the same path. Their surfaces are module-less by
|
|
113
|
+
* construction (parent § D16, #6658 D5): a template enables them by
|
|
114
|
+
* NAMING them in its roster — `scaffold()` selects their
|
|
115
|
+
* `GATEABLE_SURFACES` entries from the merged roster's routes (#5469 D10).
|
|
27
116
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* #5469 D2). They are declared here anyway, so the manifest a template
|
|
34
|
-
* publishes (`build-template-manifest.mjs`) lists the whole page set and
|
|
35
|
-
* the roster is what a template IS, not merely what it adds.
|
|
36
|
-
* - `/pricing`, `/privacy` and `/terms` are module-less by construction
|
|
37
|
-
* (parent § D16): no module owns these surfaces, their route files live in
|
|
38
|
-
* `apps/web` and are snapshotted into the starter like every other route,
|
|
39
|
-
* and a template enables them by NAMING them in its roster — `scaffold()`
|
|
40
|
-
* selects their `GATEABLE_SURFACES` entries from the merged roster's
|
|
41
|
-
* routes (#5469 D10). Their seed content ships ONCE, in the base layer
|
|
42
|
-
* (`site-templates/_base/content/**`, #5618 D1), which every template
|
|
43
|
-
* reaches by declaring `extends` — installed before the module bundles
|
|
44
|
-
* and the template's own tree, so a template may override a base page
|
|
45
|
-
* by shipping the same path.
|
|
117
|
+
* `/software`, `/sign-in` and `/sign-up` carry no `content`: they are code
|
|
118
|
+
* routes (the SoftwareProduct listing, the SignInCard island, the sign-up
|
|
119
|
+
* form), like the API-backed rows the scheduling module contributes — listed
|
|
120
|
+
* so the manifest is a complete install record, where the generator marks
|
|
121
|
+
* them `kind: route` (#6646 D2).
|
|
46
122
|
*
|
|
47
|
-
* `/
|
|
48
|
-
*
|
|
123
|
+
* `/purchase-policy` is the product-shape purchase policy (#6646 D3): its
|
|
124
|
+
* overlay seed carries returns, shipping and refunds sections — the overlay,
|
|
125
|
+
* not `_base`, because the route is core and a scaffold naming no template
|
|
126
|
+
* serves it too. A service-shape template overrides that seed with its own
|
|
127
|
+
* cancellation and refunds file.
|
|
49
128
|
*
|
|
50
129
|
* `/blog` is deliberately NOT here (#5469 D3): the docs-blog module
|
|
51
130
|
* contributes its own `/blog` row, so a base row would make `mergeRoster`
|
|
@@ -54,24 +133,33 @@ export class TemplateError extends Error {
|
|
|
54
133
|
*/
|
|
55
134
|
const TEMPLATE_BASE_ROSTER = [
|
|
56
135
|
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
136
|
+
{ route: "/software" },
|
|
137
|
+
{ route: "/software/[slug]", contentDir: "content/en/SoftwareProduct" },
|
|
57
138
|
{
|
|
58
|
-
route: "/
|
|
59
|
-
content: ["content/en/
|
|
139
|
+
route: "/use-cases",
|
|
140
|
+
content: ["content/en/UseCasesList/use-cases.mdx"],
|
|
60
141
|
},
|
|
61
|
-
{ route: "/
|
|
142
|
+
{ route: "/use-cases/[slug]", contentDir: "content/en/UseCase" },
|
|
62
143
|
{ route: "/pricing", content: ["content/en/Pricing/pricing.mdx"] },
|
|
63
144
|
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
64
145
|
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
65
146
|
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
147
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
66
148
|
{ route: "/sign-in" },
|
|
149
|
+
{ route: "/sign-up" },
|
|
67
150
|
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
68
151
|
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
152
|
+
{
|
|
153
|
+
route: "/purchase-policy",
|
|
154
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
155
|
+
},
|
|
69
156
|
];
|
|
70
157
|
/**
|
|
71
|
-
* The Free `/blog` teaser (#5469 D3) — one static
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
158
|
+
* The Free `/blog` teaser (#5469 D3) — one static BlogList page (schema `Blog`
|
|
159
|
+
* with an empty `ItemList`; the correct page type, not a LandingPage) that
|
|
160
|
+
* says what the Pro docs-blog module gives you. It is served by the generic
|
|
161
|
+
* `[slug]` route — which probes `LandingPage` first, then `BlogList` — over
|
|
162
|
+
* `content/en/BlogList/blog.mdx`, which ships in the always-copied overlay. `/blog` degrades by DIRECTORY PRECEDENCE, not
|
|
75
163
|
* by a module gate: in a keyed docs-blog scaffold the module's own
|
|
76
164
|
* `blog/[[...slug]]/page.tsx` directory exists and Next.js resolves the static
|
|
77
165
|
* segment first, so the teaser file is inert; keyless, no `blog/` directory
|
|
@@ -80,16 +168,36 @@ const TEMPLATE_BASE_ROSTER = [
|
|
|
80
168
|
*/
|
|
81
169
|
const FREE_BLOG_TEASER_ROW = {
|
|
82
170
|
route: "/blog",
|
|
83
|
-
content: ["content/en/
|
|
171
|
+
content: ["content/en/BlogList/blog.mdx"],
|
|
84
172
|
};
|
|
173
|
+
/**
|
|
174
|
+
* The rows for the `signal-collectors` bundle's six sample pages (#6646
|
|
175
|
+
* disposition (a)) — the project listing, its two project pages and the
|
|
176
|
+
* three thank-you pages its `installMap` lands. The module contributes no
|
|
177
|
+
* row for any of these routes (`module-architecture.ts`'s installMap
|
|
178
|
+
* comment), so a template that takes the module declares them, and the
|
|
179
|
+
* roster names every page the scaffold installs. `/projects` is a
|
|
180
|
+
* module-less `GATEABLE_SURFACES` entry, so naming it here also copies the
|
|
181
|
+
* route directory the samples render through (`rosterSurfaces`).
|
|
182
|
+
*/
|
|
183
|
+
const SIGNAL_COLLECTORS_SAMPLE_ROWS = [
|
|
184
|
+
{ route: "/projects", content: ["content/en/ProjectsList/projects.mdx"] },
|
|
185
|
+
{ route: "/projects/[slug]", contentDir: "content/en/Project" },
|
|
186
|
+
{ route: "/thanks/[slug]", contentDir: "content/en/ThankYouPage" },
|
|
187
|
+
];
|
|
85
188
|
/**
|
|
86
189
|
* `minimalism-site`'s own rows (#5589) — the one declared template that does
|
|
87
190
|
* not reuse `TEMPLATE_BASE_ROSTER`. Its page set is the issue's ROSTER, and
|
|
88
191
|
* the rows it does NOT carry are as deliberate as the ones it does: no
|
|
89
|
-
* `/how-it-works`,
|
|
192
|
+
* `/how-it-works`, product page or `/pricing` (a reports-first site sells
|
|
90
193
|
* nothing from a pricing table), and no `/sign-in` (a code route every
|
|
91
194
|
* scaffold carries regardless — `CORE_ROUTE_DIRS` — which this template
|
|
92
|
-
* simply does not advertise as one of its pages).
|
|
195
|
+
* simply does not advertise as one of its pages). It does carry the three
|
|
196
|
+
* pages every starter carries (`SHAPE_INDEPENDENT_ROWS`, #6658), with its
|
|
197
|
+
* own `/book-a-call` seed pointing at the scheduling module's `/meet`.
|
|
198
|
+
*
|
|
199
|
+
* `/purchase-policy` is the service-shape purchase policy (#6646 D3) — this
|
|
200
|
+
* template's own cancellation and refunds seed, overriding `_base`'s.
|
|
93
201
|
*
|
|
94
202
|
* `/meet`, `/meet/[slug]`, `/meet/confirmed`, `/reports/[slug]` and the three
|
|
95
203
|
* `/flows/*` rows are absent here on purpose: they are the `scheduling` and
|
|
@@ -102,20 +210,26 @@ const MINIMALISM_ROSTER = [
|
|
|
102
210
|
{ route: "/reports", content: ["content/en/LandingPage/reports.mdx"] },
|
|
103
211
|
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
104
212
|
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
105
|
-
{ route: "/services/[slug]" },
|
|
213
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
106
214
|
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
107
215
|
{ route: "/referral", content: ["content/en/LandingPage/referral.mdx"] },
|
|
108
216
|
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
217
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
109
218
|
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
110
219
|
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
220
|
+
{
|
|
221
|
+
route: "/purchase-policy",
|
|
222
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
223
|
+
},
|
|
224
|
+
...SIGNAL_COLLECTORS_SAMPLE_ROWS,
|
|
111
225
|
];
|
|
112
226
|
/**
|
|
113
227
|
* `simple-service`'s own rows (#6087) — the T1 lawn-care roster of Epic #5778.
|
|
114
228
|
* The second declared template that does not reuse `TEMPLATE_BASE_ROSTER`: a
|
|
115
229
|
* lawn-care site sells three named services from `/services`, not from a
|
|
116
|
-
* pricing table, so `/how-it-works`,
|
|
117
|
-
*
|
|
118
|
-
*
|
|
230
|
+
* pricing table, so `/how-it-works`, the product page and `/pricing` are absent —
|
|
231
|
+
* and so are their seeds: `scaffold()` installs a `_base` or overlay seed
|
|
232
|
+
* only for a row that names it (#6646 D1), exactly as for `minimalism-site`.
|
|
119
233
|
*
|
|
120
234
|
* `/meet`, `/meet/[slug]`, `/meet/confirmed` and `/appointments` are absent
|
|
121
235
|
* here on purpose: they are the `scheduling` module's own
|
|
@@ -135,33 +249,35 @@ const MINIMALISM_ROSTER = [
|
|
|
135
249
|
* claimant, the template's own roster is the only place that can declare
|
|
136
250
|
* them, and doing so trips no collision.
|
|
137
251
|
*
|
|
252
|
+
* `/thanks/[slug]` is declared here for the same reason (#6646 D2): the
|
|
253
|
+
* post-purchase thank-you route ships base tree and no module claims it.
|
|
254
|
+
*
|
|
255
|
+
* `/purchase-policy` is the service-shape purchase policy (#6646 D3) — its
|
|
256
|
+
* cancellation and refunds sections replace the three #5947 policy rows.
|
|
257
|
+
*
|
|
138
258
|
* `/account` carries no `content`: it is a code route (the `(authed)` group),
|
|
139
259
|
* like `/sign-in` on the base roster and like the API-backed rows the
|
|
140
|
-
* scheduling module contributes. `/services/[slug]`
|
|
141
|
-
*
|
|
142
|
-
* `content` names files the manifest generator reads frontmatter from.
|
|
260
|
+
* scheduling module contributes. `/services/[slug]` declares its seed
|
|
261
|
+
* DIRECTORY (`contentDir`, `content/en/Service`) — the three service pages.
|
|
143
262
|
*/
|
|
144
263
|
const SIMPLE_SERVICE_ROSTER = [
|
|
145
264
|
{ route: "/", content: ["content/en/HomePage/home.mdx"] },
|
|
146
265
|
{ route: "/services", content: ["content/en/ServicesList/services.mdx"] },
|
|
147
|
-
{ route: "/services/[slug]" },
|
|
266
|
+
{ route: "/services/[slug]", contentDir: "content/en/Service" },
|
|
148
267
|
{ route: "/about", content: ["content/en/AboutPage/about.mdx"] },
|
|
149
268
|
{ route: "/contact", content: ["content/en/ContactPage/contact.mdx"] },
|
|
150
269
|
{ route: "/faq", content: ["content/en/FAQPage/faq.mdx"] },
|
|
151
|
-
|
|
270
|
+
...SHAPE_INDEPENDENT_ROWS,
|
|
152
271
|
{
|
|
153
|
-
route: "/
|
|
154
|
-
content: ["content/en/
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
route: "/shipping",
|
|
158
|
-
content: ["content/en/ShippingPolicyPage/shipping.mdx"],
|
|
272
|
+
route: "/purchase-policy",
|
|
273
|
+
content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"],
|
|
159
274
|
},
|
|
160
275
|
{ route: "/privacy", content: ["content/en/PrivacyPage/privacy.mdx"] },
|
|
161
276
|
{ route: "/terms", content: ["content/en/TermsPage/terms.mdx"] },
|
|
162
277
|
{ route: "/account" },
|
|
163
278
|
{ route: "/purchase/success" },
|
|
164
279
|
{ route: "/purchase/cancel" },
|
|
280
|
+
{ route: "/thanks/[slug]" },
|
|
165
281
|
];
|
|
166
282
|
/**
|
|
167
283
|
* The three settled templates and their fixed `requires` lists — settled by
|
|
@@ -194,7 +310,12 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
|
|
|
194
310
|
"marketing-site-free": {
|
|
195
311
|
name: "marketing-site-free",
|
|
196
312
|
requires: ["marketing"],
|
|
313
|
+
// The demo site carries the "Get started with this template" banner
|
|
314
|
+
// (operator ruling 2026-09-23); every other layout knob keeps its default.
|
|
315
|
+
layout: { announcementBanner: true },
|
|
197
316
|
categories: ["accounting", "legal", "technology"],
|
|
317
|
+
shape: "organization-product",
|
|
318
|
+
design: "standard",
|
|
198
319
|
extends: BASE_LAYER_DIR,
|
|
199
320
|
roster: [...TEMPLATE_BASE_ROSTER, FREE_BLOG_TEASER_ROW],
|
|
200
321
|
},
|
|
@@ -221,8 +342,10 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
|
|
|
221
342
|
"technology",
|
|
222
343
|
"medical-specialty",
|
|
223
344
|
],
|
|
345
|
+
shape: "organization-product",
|
|
346
|
+
design: "standard",
|
|
224
347
|
extends: BASE_LAYER_DIR,
|
|
225
|
-
roster: TEMPLATE_BASE_ROSTER,
|
|
348
|
+
roster: [...TEMPLATE_BASE_ROSTER, ...SIGNAL_COLLECTORS_SAMPLE_ROWS],
|
|
226
349
|
},
|
|
227
350
|
/**
|
|
228
351
|
* Pro Plus — the Pro list plus `multi-tenant`, which is correctly in the
|
|
@@ -243,8 +366,10 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
|
|
|
243
366
|
"multi-tenant",
|
|
244
367
|
],
|
|
245
368
|
categories: ["technology", "medical-specialty"],
|
|
369
|
+
shape: "organization-product",
|
|
370
|
+
design: "standard",
|
|
246
371
|
extends: BASE_LAYER_DIR,
|
|
247
|
-
roster: TEMPLATE_BASE_ROSTER,
|
|
372
|
+
roster: [...TEMPLATE_BASE_ROSTER, ...SIGNAL_COLLECTORS_SAMPLE_ROWS],
|
|
248
373
|
},
|
|
249
374
|
/**
|
|
250
375
|
* The second Pro template (#5589) — the reports-first, scroll-snap deck
|
|
@@ -256,11 +381,17 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
|
|
|
256
381
|
*
|
|
257
382
|
* It declares its OWN roster rather than reusing `TEMPLATE_BASE_ROSTER`
|
|
258
383
|
* (the only declared template that does): the deck home replaces the
|
|
259
|
-
* document-scroll home, and `/how-it-works`,
|
|
260
|
-
* `/sign-in` are not pages this site has.
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
384
|
+
* document-scroll home, and `/how-it-works`, the product page, `/pricing` and
|
|
385
|
+
* `/sign-in` are not pages this site has. The roster is what the
|
|
386
|
+
* template IS, so an unrostered page has neither a route directory
|
|
387
|
+
* (`rosterSurfaces`) nor its `_base`/overlay seed (#6646 D1).
|
|
388
|
+
*
|
|
389
|
+
* It declares NO `layout` block (#6638): the deck home, mark-only nav and
|
|
390
|
+
* centered footer are the `minimalism` design's, supplied by
|
|
391
|
+
* `DESIGN_LAYOUTS` from `design:` — the look any shape can wear. The
|
|
392
|
+
* roster rows the `organization-service` shape does not derive
|
|
393
|
+
* (`/reports`, `/referral`) are recorded with their reasons in this
|
|
394
|
+
* template's TEMPLATE-MANIFEST.md § 3a.
|
|
264
395
|
*
|
|
265
396
|
* `/reports` and `/referral` carry no `GATEABLE_SURFACES` entry and need
|
|
266
397
|
* none: both are single-segment `LandingPage` slugs served by the generic
|
|
@@ -268,24 +399,18 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
|
|
|
268
399
|
* uses. `/reports/[slug]` (the reader) is the signal-collectors module's
|
|
269
400
|
* own contributed row.
|
|
270
401
|
*
|
|
271
|
-
* `/services/[slug]` declares
|
|
272
|
-
* (`content/en/Service`, as `routes-map.ts` records it)
|
|
273
|
-
*
|
|
274
|
-
* from. The three samples ride the template tree unmapped, landing at
|
|
275
|
-
* that directory.
|
|
402
|
+
* `/services/[slug]` declares its seed DIRECTORY as `contentDir`
|
|
403
|
+
* (`content/en/Service`, as `routes-map.ts` records it). The three
|
|
404
|
+
* samples ride the template tree unmapped, landing at that directory.
|
|
276
405
|
*/
|
|
277
406
|
"minimalism-site": {
|
|
278
407
|
name: "minimalism-site",
|
|
279
408
|
requires: ["marketing", "scheduling", "signal-collectors"],
|
|
280
409
|
categories: ["real-estate", "technology", "legal"],
|
|
410
|
+
shape: "organization-service",
|
|
411
|
+
design: "minimalism",
|
|
281
412
|
extends: BASE_LAYER_DIR,
|
|
282
413
|
roster: MINIMALISM_ROSTER,
|
|
283
|
-
layout: {
|
|
284
|
-
nav: "mark-only",
|
|
285
|
-
footer: "centered",
|
|
286
|
-
announcementBanner: false,
|
|
287
|
-
home: "deck",
|
|
288
|
-
},
|
|
289
414
|
},
|
|
290
415
|
/**
|
|
291
416
|
* The T1 lawn-care template (#6087, Epic #5778) — the first site shape
|
|
@@ -303,14 +428,16 @@ export const TEMPLATE_MANIFESTS = Object.freeze({
|
|
|
303
428
|
* `scheduling` and `commerce` are both paid, so `templateDelivery`
|
|
304
429
|
* returns `"paid"` from either one alone.
|
|
305
430
|
*
|
|
306
|
-
* It declares NO `layout` block: the default
|
|
307
|
-
* one a lawn-care site wants, and
|
|
308
|
-
* layout knobs the spec does not name.
|
|
431
|
+
* It declares NO `layout` block: the default chrome (full nav, column
|
|
432
|
+
* footer, no announcement banner) is the one a lawn-care site wants, and
|
|
433
|
+
* the issue's STOP boundary excludes layout knobs the spec does not name.
|
|
309
434
|
*/
|
|
310
435
|
"simple-service": {
|
|
311
436
|
name: "simple-service",
|
|
312
437
|
requires: ["marketing", "scheduling", "commerce"],
|
|
313
438
|
categories: ["landscaping"],
|
|
439
|
+
shape: "local-business-service",
|
|
440
|
+
design: "standard",
|
|
314
441
|
extends: BASE_LAYER_DIR,
|
|
315
442
|
roster: SIMPLE_SERVICE_ROSTER,
|
|
316
443
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-ailk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Scaffolder for AI Launch Kit — `pnpm create ailk@latest <dir>` produces a starter repo consuming @working-theory/* from npm (per ADR 0007).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"tar": "^7.5.21"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@working-theory/schema": "0.
|
|
29
|
-
"@working-theory/templates": "0.
|
|
28
|
+
"@working-theory/schema": "0.27.0",
|
|
29
|
+
"@working-theory/templates": "0.27.0"
|
|
30
30
|
},
|
|
31
31
|
"repository": {
|
|
32
32
|
"type": "git",
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"build-catalog": "node scripts/build-component-catalog.mjs",
|
|
59
59
|
"check-catalog": "node scripts/build-component-catalog.mjs --check",
|
|
60
60
|
"manifest:build": "node scripts/build-template-manifest.mjs --template marketing-site-free",
|
|
61
|
-
"manifest:check": "node scripts/build-template-manifest.mjs --template marketing-site-free --check && node scripts/build-template-manifest.mjs --template marketing-site --check"
|
|
61
|
+
"manifest:check": "node scripts/build-template-manifest.mjs --template marketing-site-free --check && node scripts/build-template-manifest.mjs --template marketing-site --check",
|
|
62
|
+
"page-types:build": "tsx scripts/generate-page-types-reference.ts",
|
|
63
|
+
"page-types:check": "tsx scripts/generate-page-types-reference.ts --check"
|
|
62
64
|
}
|
|
63
65
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "BookCall"
|
|
3
|
+
slug: "book-call"
|
|
4
|
+
title: "{Book a call: what a visitor gets from it}"
|
|
5
|
+
description: "{One sentence on who the call is for and what they leave with}"
|
|
6
|
+
placeholder: true
|
|
7
|
+
schema:
|
|
8
|
+
mainEntity:
|
|
9
|
+
"@type": "Offer"
|
|
10
|
+
name: "{Your call name}"
|
|
11
|
+
price: 0
|
|
12
|
+
priceCurrency: "USD"
|
|
13
|
+
sections:
|
|
14
|
+
[
|
|
15
|
+
{
|
|
16
|
+
"id": "hero",
|
|
17
|
+
"type": "hero",
|
|
18
|
+
"data":
|
|
19
|
+
{
|
|
20
|
+
"eyebrow": "Book a call",
|
|
21
|
+
"headline": "{Book a call: what a visitor gets from it}",
|
|
22
|
+
"subheadline": "{One sentence on who the call is for and what they leave with}",
|
|
23
|
+
"primaryCta": { "label": "Get in touch", "href": "/contact" },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "what-happens-on-the-call",
|
|
28
|
+
"type": "items",
|
|
29
|
+
"data":
|
|
30
|
+
{
|
|
31
|
+
"headline": "What happens on the call?",
|
|
32
|
+
"columns": 3,
|
|
33
|
+
"items":
|
|
34
|
+
[
|
|
35
|
+
{
|
|
36
|
+
"title": "{The first thing you cover}",
|
|
37
|
+
"description": "{One or two sentences on what the visitor learns or decides here}",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"title": "{The second thing you cover}",
|
|
41
|
+
"description": "{One or two sentences on what the visitor learns or decides here}",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"title": "{The next step you agree}",
|
|
45
|
+
"description": "{One or two sentences on what happens after the call}",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
{/* Rendered from frontmatter `sections[]` by the /book-a-call route. The call to action sends visitors to your contact page; a template that carries the scheduling module overrides this file to point it at the /meet booker. The `schema:` Offer is the page's JSON-LD main entity — a free call. Placeholder copy — replace every {brace} with your own words before you launch. */}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "GlossaryList"
|
|
3
|
+
slug: "glossary"
|
|
4
|
+
title: "{Glossary: the terms your customers look up}"
|
|
5
|
+
description: "{One sentence on the subject these terms cover and who they help}"
|
|
6
|
+
placeholder: true
|
|
7
|
+
sections:
|
|
8
|
+
[
|
|
9
|
+
{
|
|
10
|
+
"id": "hero",
|
|
11
|
+
"type": "hero",
|
|
12
|
+
"data":
|
|
13
|
+
{
|
|
14
|
+
"eyebrow": "Glossary",
|
|
15
|
+
"headline": "{Glossary: the terms your customers look up}",
|
|
16
|
+
"subheadline": "{One sentence on the subject these terms cover and who they help}",
|
|
17
|
+
"primaryCta": { "label": "{Primary CTA}", "href": "/contact" },
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "glossary-index",
|
|
22
|
+
"type": "glossary-index",
|
|
23
|
+
"data":
|
|
24
|
+
{
|
|
25
|
+
"headline": "{Terms, A to Z}",
|
|
26
|
+
"description": "{One sentence on how to use this list}",
|
|
27
|
+
"variant": "columns",
|
|
28
|
+
"terms":
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
"term": "{Term 1}",
|
|
32
|
+
"slug": "term-1",
|
|
33
|
+
"definition": "{One plain sentence that defines this term the way your customers would say it}",
|
|
34
|
+
"letter": "T",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"term": "{Term 2}",
|
|
38
|
+
"slug": "term-2",
|
|
39
|
+
"definition": "{One plain sentence that defines this term the way your customers would say it}",
|
|
40
|
+
"letter": "T",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"term": "{Term 3}",
|
|
44
|
+
"slug": "term-3",
|
|
45
|
+
"definition": "{One plain sentence that defines this term the way your customers would say it}",
|
|
46
|
+
"letter": "T",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"term": "{Term 4}",
|
|
50
|
+
"slug": "term-4",
|
|
51
|
+
"definition": "{One plain sentence that defines this term the way your customers would say it}",
|
|
52
|
+
"letter": "T",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"term": "{Term 5}",
|
|
56
|
+
"slug": "term-5",
|
|
57
|
+
"definition": "{One plain sentence that defines this term the way your customers would say it}",
|
|
58
|
+
"letter": "T",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
{/* Rendered from frontmatter `sections[]` by the /glossary route. Each `glossary-index` term becomes a DefinedTerm in the page's JSON-LD DefinedTermSet, so write the definition an agent should quote. Placeholder copy — replace every {brace} with your own words, and add or remove terms, before you launch. */}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "NewsletterSignup"
|
|
3
|
+
slug: "newsletter"
|
|
4
|
+
title: "{Newsletter: what subscribers get and how often}"
|
|
5
|
+
description: "{One sentence on what this newsletter covers and who it is for}"
|
|
6
|
+
placeholder: true
|
|
7
|
+
schema:
|
|
8
|
+
mainEntity:
|
|
9
|
+
"@type": "Offer"
|
|
10
|
+
name: "{Your newsletter name}"
|
|
11
|
+
price: 0
|
|
12
|
+
priceCurrency: "USD"
|
|
13
|
+
sections:
|
|
14
|
+
[
|
|
15
|
+
{
|
|
16
|
+
"id": "hero",
|
|
17
|
+
"type": "hero",
|
|
18
|
+
"data":
|
|
19
|
+
{
|
|
20
|
+
"eyebrow": "Newsletter",
|
|
21
|
+
"headline": "{Newsletter: what subscribers get and how often}",
|
|
22
|
+
"subheadline": "{One sentence on what this newsletter covers and who it is for}",
|
|
23
|
+
"primaryCta": { "label": "Subscribe", "href": "#signup" },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "signup",
|
|
28
|
+
"type": "newsletter",
|
|
29
|
+
"data":
|
|
30
|
+
{
|
|
31
|
+
"headline": "Subscribe",
|
|
32
|
+
"description": "{One sentence on what lands in the inbox}",
|
|
33
|
+
"action": "/v1/leads/subscribe",
|
|
34
|
+
"source": "newsletter",
|
|
35
|
+
"placeholder": "you@example.com",
|
|
36
|
+
"submitLabel": "Subscribe",
|
|
37
|
+
"consentText": "{One line on how you use the address, and that readers can unsubscribe any time}",
|
|
38
|
+
"pattern": "none",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "faq",
|
|
43
|
+
"type": "faq",
|
|
44
|
+
"data":
|
|
45
|
+
{
|
|
46
|
+
"headline": "FAQs",
|
|
47
|
+
"presentation": "expanded",
|
|
48
|
+
"items":
|
|
49
|
+
[
|
|
50
|
+
{
|
|
51
|
+
"question": "{How often will I hear from you?}",
|
|
52
|
+
"answer": "{Answer in one or two plain sentences}",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"question": "{What will I get?}",
|
|
56
|
+
"answer": "{Answer in one or two plain sentences}",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"question": "{Can I unsubscribe?}",
|
|
60
|
+
"answer": "{Answer in one or two plain sentences}",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
]
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
{/* Rendered from frontmatter `sections[]` by the /newsletter route. The form posts the address to lead capture (`/v1/leads/subscribe`), which records a subscriber and sends no verification email. The `schema:` Offer is the page's JSON-LD main entity — a free subscription. Placeholder copy — replace every {brace} with your own words before you launch. */}
|