create-ailk 0.12.1 → 0.14.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.
Files changed (163) hide show
  1. package/README.md +12 -4
  2. package/component-catalog.json +247 -33
  3. package/component-catalog.md +10 -6
  4. package/dist/apply-design.d.ts +21 -2
  5. package/dist/apply-design.js +120 -19
  6. package/dist/cli.js +1 -0
  7. package/dist/design-compile.d.ts +70 -2
  8. package/dist/design-compile.js +97 -1
  9. package/dist/design-home.d.ts +74 -0
  10. package/dist/design-home.js +256 -0
  11. package/dist/design-package.d.ts +39 -2
  12. package/dist/design-package.js +223 -9
  13. package/dist/design-presets.d.ts +17 -1
  14. package/dist/design-presets.js +17 -5
  15. package/dist/design-scaffold.d.ts +6 -25
  16. package/dist/design-scaffold.js +26 -74
  17. package/dist/index.d.ts +1 -0
  18. package/dist/lib/design-checks.d.ts +12 -1
  19. package/dist/lib/design-checks.js +38 -2
  20. package/dist/lib/module-license-gate.d.ts +9 -0
  21. package/dist/lib/module-license-gate.js +18 -0
  22. package/dist/module-architecture.js +27 -0
  23. package/dist/programmatic.js +70 -26
  24. package/dist/site-chrome.d.ts +38 -0
  25. package/dist/site-chrome.js +109 -2
  26. package/dist/site-fonts.d.ts +21 -0
  27. package/dist/site-fonts.js +54 -0
  28. package/dist/site-roster.d.ts +16 -0
  29. package/dist/site-roster.js +81 -0
  30. package/dist/starter-grid.js +15 -0
  31. package/dist/surfaces.js +12 -0
  32. package/dist/team-profiles.d.ts +29 -0
  33. package/dist/team-profiles.js +43 -0
  34. package/package.json +3 -3
  35. package/release-scope.json +1 -1
  36. package/site-templates/_base/content/en/TeamList/team.mdx +68 -0
  37. package/site-templates/_base/content/en/TeamMember/first-member.mdx +22 -0
  38. package/site-templates/_base/content/en/TeamMember/second-member.mdx +22 -0
  39. package/site-templates/_base/content/en/TeamMember/third-member.mdx +22 -0
  40. package/site-templates/designs/minimalism/DESIGN.md +164 -34
  41. package/site-templates/designs/minimalism/home/local-business-service.mdx +119 -0
  42. package/site-templates/designs/minimalism/home/organization-product.mdx +132 -0
  43. package/site-templates/designs/minimalism/home/organization-service.mdx +131 -0
  44. package/site-templates/designs/minimalism/home/person-service.mdx +101 -0
  45. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +34 -1
  46. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +20 -0
  47. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +34 -1
  48. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +22 -1
  49. package/site-templates/marketing-site-free/ailk-template.json +1 -1
  50. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.json +34 -1
  51. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +26 -7
  52. package/site-templates/shapes/local-business-service/ailk-template.json +1 -1
  53. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +34 -1
  54. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +26 -7
  55. package/site-templates/shapes/organization-service/ailk-template.json +1 -1
  56. package/templates/.env.example +23 -9
  57. package/templates/README.md +2 -0
  58. package/templates/apps/api/CLAUDE.md +24 -17
  59. package/templates/apps/api/src/__tests__/factories/agent-caller.ts +98 -0
  60. package/templates/apps/api/src/__tests__/factories/in-memory-prisma.ts +321 -0
  61. package/templates/apps/api/src/__tests__/schedule-forwarded-rate-limit.test.ts +117 -0
  62. package/templates/apps/api/src/config/__tests__/hub-require-spoke-key.test.ts +39 -14
  63. package/templates/apps/api/src/config/index.ts +35 -20
  64. package/templates/apps/api/src/lib/__mocks__/prisma-client.js +3 -0
  65. package/templates/apps/api/src/lib/__mocks__/prisma.ts +14 -0
  66. package/templates/apps/api/src/lib/__tests__/agent-store.test.ts +468 -0
  67. package/templates/apps/api/src/lib/__tests__/spoke-store.test.ts +32 -2
  68. package/templates/apps/api/src/lib/agent-store.ts +521 -0
  69. package/templates/apps/api/src/lib/spoke-store.ts +13 -2
  70. package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +384 -1
  71. package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +61 -0
  72. package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +176 -0
  73. package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +76 -0
  74. package/templates/apps/api/src/middleware/auth.ts +219 -5
  75. package/templates/apps/api/src/middleware/default-tenant.ts +29 -8
  76. package/templates/apps/api/src/middleware/rate-limit.ts +35 -13
  77. package/templates/apps/api/src/routes/leads/__tests__/spoke.test.ts +76 -15
  78. package/templates/apps/api/src/routes/leads/index.ts +14 -6
  79. package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +5 -6
  80. package/templates/apps/api/src/routes/project-listings/index.ts +14 -9
  81. package/templates/apps/api/src/routes/project-listings/me.ts +4 -3
  82. package/templates/apps/api/src/routes/project-listings/patch-copy.ts +7 -5
  83. package/templates/apps/api/src/routes/workspaces/__tests__/inbox-wire-schemas.test.ts +198 -0
  84. package/templates/apps/api/src/server.ts +27 -0
  85. package/templates/apps/api/src/services/__tests__/audit-log.test.ts +374 -57
  86. package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +25 -2
  87. package/templates/apps/api/src/services/__tests__/spoke-resolution.test.ts +303 -17
  88. package/templates/apps/api/src/services/audit-log.ts +278 -47
  89. package/templates/apps/api/src/services/default-tenant.ts +55 -5
  90. package/templates/apps/api/src/services/leads-inbox.ts +12 -21
  91. package/templates/apps/api/src/services/project-listings.ts +1 -21
  92. package/templates/apps/api/src/services/public-site-resolver.ts +103 -13
  93. package/templates/apps/mcp/CLAUDE.md +44 -5
  94. package/templates/apps/mcp/__tests__/parity.test.ts +53 -1
  95. package/templates/apps/mcp/__tests__/workspace-surface.test.ts +364 -0
  96. package/templates/apps/mcp/package.json +1 -1
  97. package/templates/apps/mcp/src/http-transport.ts +107 -1
  98. package/templates/apps/mcp/src/workspace-server.ts +193 -0
  99. package/templates/apps/web/.env.example +64 -37
  100. package/templates/apps/web/CLAUDE.md +11 -0
  101. package/templates/apps/web/app/[locale]/(authed)/account/__tests__/settings.test.tsx +10 -0
  102. package/templates/apps/web/app/[locale]/(authed)/account/settings/__tests__/theme-modes.test.ts +42 -0
  103. package/templates/apps/web/app/[locale]/(authed)/account/settings/theme-modes.ts +8 -0
  104. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +2 -2
  105. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +2 -2
  106. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +14 -1
  107. package/templates/apps/web/app/[locale]/contact/__tests__/site-contact-lines.test.ts +69 -0
  108. package/templates/apps/web/app/[locale]/contact/site-contact-lines.ts +64 -0
  109. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +4 -4
  110. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +15 -3
  111. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +17 -6
  112. package/templates/apps/web/app/[locale]/for/__tests__/page-renderer-migration.test.tsx +14 -1
  113. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +2 -2
  114. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +4 -6
  115. package/templates/apps/web/app/[locale]/layout.tsx +156 -53
  116. package/templates/apps/web/app/[locale]/page.tsx +37 -0
  117. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +2 -2
  118. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +4 -6
  119. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +15 -2
  120. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +43 -6
  121. package/templates/apps/web/app/[locale]/services/page.tsx +14 -2
  122. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +2 -2
  123. package/templates/apps/web/app/[locale]/team/[slug]/page.tsx +45 -0
  124. package/templates/apps/web/app/[locale]/team/__tests__/team-routes.test.tsx +155 -0
  125. package/templates/apps/web/app/[locale]/team/page.tsx +49 -0
  126. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +2 -2
  127. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +14 -1
  128. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +2 -2
  129. package/templates/apps/web/app/not-found.tsx +47 -0
  130. package/templates/apps/web/app/v1/[...path]/route.ts +16 -0
  131. package/templates/apps/web/lib/__tests__/profile-back-link.test.ts +95 -0
  132. package/templates/apps/web/lib/__tests__/relay.test.ts +515 -0
  133. package/templates/apps/web/lib/__tests__/site-theme-head.test.ts +70 -0
  134. package/templates/apps/web/lib/__tests__/site-theme.test.ts +64 -1
  135. package/templates/apps/web/lib/profile-back-link.ts +51 -0
  136. package/templates/apps/web/lib/relay.ts +279 -0
  137. package/templates/apps/web/lib/site-chrome.ts +12 -0
  138. package/templates/apps/web/lib/site-fonts.ts +15 -0
  139. package/templates/apps/web/lib/site-logo.tsx +39 -1
  140. package/templates/apps/web/lib/site-theme-head.ts +33 -0
  141. package/templates/apps/web/lib/site-theme.ts +13 -1
  142. package/templates/apps/web/messages/en.json +7 -1
  143. package/templates/apps/web/middleware.ts +5 -4
  144. package/templates/apps/web/next.config.mjs +6 -0
  145. package/templates/database/CHANGELOG.md +22 -0
  146. package/templates/database/__tests__/agents.db.test.ts +235 -0
  147. package/templates/database/auth/schema.prisma +61 -0
  148. package/templates/database/migrations/20261005120000_agents/migration.sql +84 -0
  149. package/templates/database/package.json +1 -1
  150. package/versions.json +35 -35
  151. package/site-templates/designs/minimalism/sample/README.md +0 -48
  152. package/site-templates/designs/minimalism/sample/content/en/HomePage/home.mdx +0 -244
  153. package/site-templates/designs/minimalism/sample/public/avatar-placeholder-1.svg +0 -7
  154. package/site-templates/designs/minimalism/sample/public/avatar-placeholder-2.svg +0 -7
  155. package/site-templates/designs/minimalism/sample/public/avatar-placeholder-3.svg +0 -7
  156. package/site-templates/designs/minimalism/sample/public/avatar-placeholder-4.svg +0 -7
  157. package/site-templates/designs/minimalism/sample/public/avatar-placeholder-5.svg +0 -7
  158. package/site-templates/designs/minimalism/sample/public/avatar-placeholder-6.svg +0 -7
  159. package/site-templates/designs/minimalism/sample/public/hero-backdrop.svg +0 -17
  160. package/site-templates/designs/minimalism/sample/public/logo-placeholder-1.svg +0 -6
  161. package/site-templates/designs/minimalism/sample/public/logo-placeholder-2.svg +0 -6
  162. package/site-templates/designs/minimalism/sample/public/logo-placeholder-3.svg +0 -6
  163. package/site-templates/designs/minimalism/sample/public/wordmark-placeholder.svg +0 -28
package/dist/surfaces.js CHANGED
@@ -299,6 +299,13 @@ export const GATEABLE_SURFACES = [
299
299
  routes: [`${ROUTE_ROOT}/software`],
300
300
  content: ["content/<locale>/SoftwareProduct"],
301
301
  },
302
+ {
303
+ // #7744 — the team profile pages, module-less: a roster row enables it,
304
+ // so only the organization shapes ship /team (person-service does not).
305
+ id: "team",
306
+ routes: [`${ROUTE_ROOT}/team`],
307
+ content: ["content/<locale>/TeamList", "content/<locale>/TeamMember"],
308
+ },
302
309
  {
303
310
  id: "tech-articles",
304
311
  routes: [`${ROUTE_ROOT}/tech-articles`],
@@ -583,6 +590,9 @@ export const ROUTE_SINCE = {
583
590
  "services/[slug]": "0.0.0",
584
591
  software: "0.0.0",
585
592
  "software/[slug]": "0.0.0",
593
+ // #7744 — the team profile pages, a new route pair at today's line.
594
+ team: "0.35.0",
595
+ "team/[slug]": "0.35.0",
586
596
  "tech-articles": "0.0.0",
587
597
  "tech-articles/[slug]": "0.0.0",
588
598
  terms: "0.22.0",
@@ -824,6 +834,8 @@ export const ROUTE_MESSAGE_NAMESPACES = {
824
834
  "(authed)/admin/site": ["admin"],
825
835
  "(authed)/admin/team": ["admin"],
826
836
  "(authed)/waitlist": ["waitlistDashboard.gate"],
837
+ // #7744 — the /team hub's empty state reads the `team` namespace.
838
+ team: ["team"],
827
839
  };
828
840
  /** Template-relative path of the generated site-nav registry. */
829
841
  export const NAV_CONFIG_PATH = "apps/web/lib/nav-config.ts";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * One people-slide / team-index member: the `team` section's member shape,
3
+ * declared here because create-ailk depends on neither
4
+ * `@working-theory/validation` nor `yaml`.
5
+ */
6
+ export interface TeamSlideMember {
7
+ readonly name: string;
8
+ readonly role: string;
9
+ readonly links: readonly [
10
+ {
11
+ readonly type: "page";
12
+ readonly url: string;
13
+ readonly label: string;
14
+ }
15
+ ];
16
+ }
17
+ /**
18
+ * The three seeded people, in seed order: slug, the seed's `title` as `name`,
19
+ * "{Their title}", and a page link to `/team/<slug>` labelled "{View profile}".
20
+ */
21
+ export declare const TEAM_SEED_MEMBERS: readonly (TeamSlideMember & {
22
+ readonly slug: string;
23
+ })[];
24
+ /**
25
+ * `TEAM_SEED_MEMBERS` whose `<siteRoot>/content/en/TeamMember/<slug>.mdx`
26
+ * exists (without `slug`), or `undefined` when none does (person-service, or
27
+ * a site that deleted them). Reads, never writes.
28
+ */
29
+ export declare function teamSlideMembers(siteRoot: string): TeamSlideMember[] | undefined;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The seeded team (#7744 D8) — the one source of the three placeholder people
3
+ * the organization shapes ship.
4
+ *
5
+ * The `_base` layer installs one `TeamMember` profile per person at
6
+ * `/team/<slug>` and a `/team` index listing them (#7744 D4); minimalism's
7
+ * home seeds for the three organization shapes carry a `people` slide listing
8
+ * the same members, each linking to their profile. `team-profiles.test.ts`
9
+ * pins that every one of those seeds agrees with `TEAM_SEED_MEMBERS`.
10
+ *
11
+ * `node:fs` only: create-ailk ships one runtime dependency (`tar`), and its
12
+ * scaffold-time readers may not import `yaml` (see `design-package.ts`), so
13
+ * this module parses nothing — it only checks which profile files a site has.
14
+ */
15
+ import { existsSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ function seedMember(slug, ordinal) {
18
+ return {
19
+ slug,
20
+ name: `{${ordinal} team member's name}`,
21
+ role: "{Their title}",
22
+ links: [{ type: "page", url: `/team/${slug}`, label: "{View profile}" }],
23
+ };
24
+ }
25
+ /**
26
+ * The three seeded people, in seed order: slug, the seed's `title` as `name`,
27
+ * "{Their title}", and a page link to `/team/<slug>` labelled "{View profile}".
28
+ */
29
+ export const TEAM_SEED_MEMBERS = [
30
+ seedMember("first-member", "First"),
31
+ seedMember("second-member", "Second"),
32
+ seedMember("third-member", "Third"),
33
+ ];
34
+ /**
35
+ * `TEAM_SEED_MEMBERS` whose `<siteRoot>/content/en/TeamMember/<slug>.mdx`
36
+ * exists (without `slug`), or `undefined` when none does (person-service, or
37
+ * a site that deleted them). Reads, never writes.
38
+ */
39
+ export function teamSlideMembers(siteRoot) {
40
+ const dir = join(siteRoot, "content", "en", "TeamMember");
41
+ const members = TEAM_SEED_MEMBERS.filter(({ slug }) => existsSync(join(dir, `${slug}.mdx`))).map(({ slug: _slug, ...member }) => member);
42
+ return members.length > 0 ? members : undefined;
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ailk",
3
- "version": "0.12.1",
3
+ "version": "0.14.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",
@@ -27,8 +27,8 @@
27
27
  "tar": "^7.5.21"
28
28
  },
29
29
  "devDependencies": {
30
- "@working-theory/schema": "0.34.1",
31
- "@working-theory/templates": "0.34.1"
30
+ "@working-theory/schema": "0.36.0",
31
+ "@working-theory/templates": "0.36.0"
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",
@@ -11,7 +11,7 @@
11
11
  "person-service": "released",
12
12
  "local-business-product": "deferred"
13
13
  },
14
- "designs": { "standard": "released", "minimalism": "gated" },
14
+ "designs": { "standard": "released", "minimalism": "released" },
15
15
  "modules": {
16
16
  "marketing": "released",
17
17
  "docs-blog": "released",
@@ -0,0 +1,68 @@
1
+ ---
2
+ type: "TeamList"
3
+ slug: "team"
4
+ title: "{The team} | {Company name}"
5
+ description: "{One sentence on who the team is and the work they do together.}"
6
+ sections:
7
+ [
8
+ {
9
+ "id": "team-hero",
10
+ "type": "hero",
11
+ "data":
12
+ {
13
+ "variant": "default",
14
+ "eyebrow": "{Team}",
15
+ "headline": "{The people behind the work.}",
16
+ },
17
+ },
18
+ {
19
+ "id": "team-members",
20
+ "type": "team",
21
+ "data":
22
+ {
23
+ "variant": "with-large-images",
24
+ "members":
25
+ [
26
+ {
27
+ "name": "{First team member's name}",
28
+ "role": "{Their title}",
29
+ "links":
30
+ [
31
+ {
32
+ "type": "page",
33
+ "url": "/team/first-member",
34
+ "label": "{View profile}",
35
+ },
36
+ ],
37
+ },
38
+ {
39
+ "name": "{Second team member's name}",
40
+ "role": "{Their title}",
41
+ "links":
42
+ [
43
+ {
44
+ "type": "page",
45
+ "url": "/team/second-member",
46
+ "label": "{View profile}",
47
+ },
48
+ ],
49
+ },
50
+ {
51
+ "name": "{Third team member's name}",
52
+ "role": "{Their title}",
53
+ "links":
54
+ [
55
+ {
56
+ "type": "page",
57
+ "url": "/team/third-member",
58
+ "label": "{View profile}",
59
+ },
60
+ ],
61
+ },
62
+ ],
63
+ },
64
+ },
65
+ ]
66
+ ---
67
+
68
+ {/* Placeholder copy — replace every {brace} with your own words before you launch. */}
@@ -0,0 +1,22 @@
1
+ ---
2
+ type: "TeamMember"
3
+ slug: "first-member"
4
+ title: "{First team member's name}"
5
+ description: "{One sentence on who they are and what they do here}"
6
+ schema: { "jobTitle": "{Their title}" }
7
+ sections:
8
+ [
9
+ {
10
+ "id": "profile",
11
+ "type": "content-block",
12
+ "data":
13
+ {
14
+ "imagerySlot": true,
15
+ "headline": "{First team member's name}",
16
+ "body": "{Two or three sentences on what they do here, and the work they are known for.} {One or two sentences on how they came to it, and what a client can expect working with them.}",
17
+ },
18
+ },
19
+ ]
20
+ ---
21
+
22
+ {/* Placeholder copy — replace every {brace} with your own words before you launch. */}
@@ -0,0 +1,22 @@
1
+ ---
2
+ type: "TeamMember"
3
+ slug: "second-member"
4
+ title: "{Second team member's name}"
5
+ description: "{One sentence on who they are and what they do here}"
6
+ schema: { "jobTitle": "{Their title}" }
7
+ sections:
8
+ [
9
+ {
10
+ "id": "profile",
11
+ "type": "content-block",
12
+ "data":
13
+ {
14
+ "imagerySlot": true,
15
+ "headline": "{Second team member's name}",
16
+ "body": "{Two or three sentences on what they do here, and the work they are known for.} {One or two sentences on how they came to it, and what a client can expect working with them.}",
17
+ },
18
+ },
19
+ ]
20
+ ---
21
+
22
+ {/* Placeholder copy — replace every {brace} with your own words before you launch. */}
@@ -0,0 +1,22 @@
1
+ ---
2
+ type: "TeamMember"
3
+ slug: "third-member"
4
+ title: "{Third team member's name}"
5
+ description: "{One sentence on who they are and what they do here}"
6
+ schema: { "jobTitle": "{Their title}" }
7
+ sections:
8
+ [
9
+ {
10
+ "id": "profile",
11
+ "type": "content-block",
12
+ "data":
13
+ {
14
+ "imagerySlot": true,
15
+ "headline": "{Third team member's name}",
16
+ "body": "{Two or three sentences on what they do here, and the work they are known for.} {One or two sentences on how they came to it, and what a client can expect working with them.}",
17
+ },
18
+ },
19
+ ]
20
+ ---
21
+
22
+ {/* Placeholder copy — replace every {brace} with your own words before you launch. */}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: Minimalism
3
- description: "The minimalism design — the same black-on-white foundation, presented as a nine-slide scroll-snap deck home with a mark-only navigation and a centred footer."
3
+ description: "The minimalism design — the same black-on-white foundation, presented as a scroll-snap deck home (one slide per home section, the landing hero carrying the brand) with a mark-only navigation and a centred footer."
4
4
  colors:
5
5
  bg: "#ffffff"
6
6
  fg: "#000000"
@@ -21,39 +21,126 @@ treatments:
21
21
  eyebrowCase: sentence
22
22
  placeholders: fill
23
23
  checkmarks: plain
24
+ buttonShape: pill
25
+ typeScale: design
26
+ darkInk: accent
27
+ figures: display
24
28
  layout:
25
29
  nav: mark-only
26
30
  footer: centered
27
31
  announcementBanner: false
28
32
  home: deck
33
+ deckPresentation: true
34
+ innerPages: bare
35
+ colorMode: light
36
+ chromeStyle: minimal
37
+ sections:
38
+ AboutPage:
39
+ content-block:
40
+ variant: profile
41
+ BlogList:
42
+ hero:
43
+ variant: centered
44
+ BookCall:
45
+ hero:
46
+ variant: centered
47
+ ContactPage:
48
+ hero:
49
+ variant: centered
50
+ FAQPage:
51
+ hero:
52
+ variant: centered
53
+ Feature:
54
+ hero:
55
+ variant: centered
56
+ FeaturesList:
57
+ hero:
58
+ variant: centered
59
+ GlossaryList:
60
+ hero:
61
+ variant: centered
62
+ HomePage:
63
+ hero:
64
+ variant: centered
65
+ fill: viewport
66
+ content-block:
67
+ variant: statement
68
+ items:
69
+ variant: list
70
+ logoCloud:
71
+ columns: 5
72
+ phoneColumns: 2
73
+ motion: scroll
74
+ treatment: silhouette
75
+ actionStyle: links
76
+ team:
77
+ variant: with-portraits
78
+ cta:
79
+ actionStyle: one-button
80
+ LandingPage:
81
+ hero:
82
+ variant: centered
83
+ NewsletterSignup:
84
+ hero:
85
+ variant: centered
86
+ PortfolioList:
87
+ hero:
88
+ variant: centered
89
+ surface: none
90
+ eyebrowTone: muted
91
+ items:
92
+ itemStyle: plain
93
+ faq:
94
+ surface: none
95
+ cta:
96
+ variant: minimal
97
+ Pricing:
98
+ hero:
99
+ variant: centered
100
+ ServicesList:
101
+ hero:
102
+ variant: centered
103
+ items:
104
+ itemStyle: plain
105
+ TeamMember:
106
+ content-block:
107
+ variant: profile
108
+ UseCase:
109
+ hero:
110
+ variant: centered
111
+ UseCasesList:
112
+ hero:
113
+ variant: centered
29
114
  copy:
30
115
  density: sparse
31
116
  typography:
32
117
  display:
33
118
  fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
34
- fontSize: "3.5rem"
35
- fontWeight: 700
119
+ fontSize: "2.8rem"
120
+ fontSizeMobile: "1.65rem"
121
+ fontWeight: 400
36
122
  lineHeight: 1.1
37
123
  letterSpacing: "normal"
38
124
  heading-section:
39
125
  fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
40
- fontSize: "3rem"
41
- fontWeight: 700
126
+ fontSize: "2.8rem"
127
+ fontSizeMobile: "1.65rem"
128
+ fontWeight: 400
42
129
  lineHeight: 1.1
43
130
  letterSpacing: "normal"
44
131
  heading-item:
45
- fontSize: "2rem"
46
- fontWeight: 700
132
+ fontSize: "1.6875rem"
133
+ fontWeight: 400
47
134
  lineHeight: 1.375
48
135
  letterSpacing: "normal"
49
136
  body:
50
137
  fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
51
- fontSize: "1.125rem"
138
+ fontSize: "1.05rem"
52
139
  fontWeight: 400
53
- lineHeight: 1.5
140
+ lineHeight: 1.6
54
141
  eyebrow:
55
- fontSize: "0.875rem"
56
- fontWeight: 600
142
+ fontSize: "1.5rem"
143
+ fontWeight: 400
57
144
  lineHeight: 1.4
58
145
  letterSpacing: "0.05em"
59
146
  rounded:
@@ -94,7 +181,9 @@ spacing:
94
181
 
95
182
  ## Overview
96
183
 
97
- The minimalism design is the standard foundation — the same black-on-white wireframe, the same type and the same components — presented as a deck. The home page is a nine-slide deck that snaps one slide per scroll, so the site reads like a presentation before it reads like a website; the rest of the site is quiet and document-like. Its character comes from structure, not a palette: it carries no theme of its own.
184
+ The minimalism design is the standard foundation — the same black-on-white wireframe, the same type and the same components — presented as a deck. The home page is a deck: each home section is one slide, snapping one slide per scroll, and the landing hero carries the brand, so the site reads like a presentation before it reads like a website; the rest of the site is quiet and document-like. Its character comes from structure, not a palette: it carries no theme of its own.
185
+
186
+ The deck presents slide by slide (`layout.deckPresentation: true`). Each slide fits the screen, and a slide with more to say scrolls inside itself, with its down chevron held in view at its foot. The pinned mark takes the ground of the slide under it, so it shows its dark variant over a dark slide. Each slide has its own link, `#slide-<name>`, which the address bar follows as the reader moves without adding a history entry. Slides fade in as they arrive, unless the reader has asked for reduced motion. Every slide's header is centred, and feature cards stack in one column on phones.
98
187
 
99
188
  Every page is composed from the AI Launch Kit component library (`@working-theory/ui`). Nothing is hand-built: a page is a list of registered sections, each with a bounded set of variants.
100
189
 
@@ -127,9 +216,9 @@ Every page is composed from the AI Launch Kit component library (`@working-theor
127
216
 
128
217
  ### Neutral
129
218
 
130
- Pure white ground (`bg` `#ffffff`), pure black ink for headings (`fg` `#000000`), and near-black `#333333` for body copy — well above AA on white. **Borders are black** (`#000000`): card outlines, the rule under the navigation, the rules between sections and the rule above the footer are all 1px black lines. Cards are white, not tinted (`surface-secondary` is white too). There is no accent colour — `accent` is black.
219
+ Pure white ground (`bg` `#ffffff`), pure black ink for headings (`fg` `#000000`), and near-black `#333333` for body copy — well above AA on white. **Borders are black** (`#000000`): card outlines, the rule under the navigation (not on the deck home), the rules between sections and the rule above the footer (not on the deck home) are all 1px black lines. Cards are white, not tinted (`surface-secondary` is white too). There is no accent colour — `accent` is black.
131
220
 
132
- Dark mode inverts: black ground, white ink, white rules, white primary button with black label.
221
+ The site is light only (`layout.colorMode: light`, #7742): it shows no theme switch and ignores the reader's system preference. Dark appears only as a deck ground, where a slide inverts: black ground, white ink, white rules, white primary button with black label.
133
222
 
134
223
  ### Named Rules
135
224
 
@@ -139,13 +228,13 @@ Dark mode inverts: black ground, white ink, white rules, white primary button wi
139
228
 
140
229
  <!-- generated:begin typography -->
141
230
 
142
- | Role | Family | Size | Weight | Line height | Tracking |
143
- | ----------------- | ------------------------------------------------------------------------ | ---------- | ------ | ----------- | -------- |
144
- | `display` | `system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif` | `3.5rem` | 700 | 1.1 | `normal` |
145
- | `heading-section` | `system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif` | `3rem` | 700 | 1.1 | `normal` |
146
- | `heading-item` | — | `2rem` | 700 | 1.375 | `normal` |
147
- | `body` | `system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif` | `1.125rem` | 400 | 1.5 | — |
148
- | `eyebrow` | — | `0.875rem` | 600 | 1.4 | `0.05em` |
231
+ | Role | Family | Size | Weight | Line height | Tracking |
232
+ | ----------------- | ------------------------------------------------------------------------ | ----------- | ------ | ----------- | -------- |
233
+ | `display` | `system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif` | `2.8rem` | 400 | 1.1 | `normal` |
234
+ | `heading-section` | `system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif` | `2.8rem` | 400 | 1.1 | `normal` |
235
+ | `heading-item` | — | `1.6875rem` | 400 | 1.375 | `normal` |
236
+ | `body` | `system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif` | `1.05rem` | 400 | 1.6 | — |
237
+ | `eyebrow` | — | `1.5rem` | 400 | 1.4 | `0.05em` |
149
238
 
150
239
  <!-- generated:end -->
151
240
 
@@ -153,15 +242,15 @@ System sans throughout; no web font.
153
242
 
154
243
  ### Hierarchy
155
244
 
156
- | Role | Size | Weight | Notes |
157
- | --------------- | -------- | ------ | ------------------------------------------------------------------------------------- |
158
- | Hero headline | 3.5rem | 700 | Normal tracking, line-height 1.1; 2.5rem below 1024px |
159
- | Section heading | 3rem | 700 | Normal tracking, line-height 1.1; 2.25rem below 1024px, always under the hero |
160
- | Item heading | 2rem | 700 | Card, feature and step titles; 1.5rem below 1024px |
161
- | Body | 1.125rem | 400 | `#333333`, line-height 1.5; section copy capped at 36rem (about 70 characters a line) |
162
- | Section label | 0.875rem | 600 | Uppercase, +0.05em tracking today — the small label above a section heading |
245
+ | Role | Size | Weight | Notes |
246
+ | --------------- | --------- | ------ | ---------------------------------------------------------------------------------------------------- |
247
+ | Hero headline | 2.8rem | 400 | Normal tracking, line-height 1.1; 1.65rem below 1024px |
248
+ | Section heading | 2.8rem | 400 | Normal tracking, line-height 1.1; 1.65rem below 1024px — a statement, the same size as the hero |
249
+ | Item heading | 1.6875rem | 400 | Card, feature and step titles; 1.5rem below 1024px |
250
+ | Body | 1.05rem | 400 | `#333333`, line-height 1.6; content-block body copy capped at 36rem (about 70 characters a line) |
251
+ | Section label | 1.5rem | 400 | Sentence case, 400, 1.5rem, the body face — the label above a section heading, larger than body copy |
163
252
 
164
- Measured from the rendered scaffold (1440px and 390px wide), not transcribed from tokens. Bold headings at normal tracking follow the foundation's pinned direction (#6493).
253
+ Measured from the rendered scaffold (1440px and 390px wide), not transcribed from tokens. Every heading — hero, statement, list title and person name — is set at 400 at normal tracking, as on the bondcap reference; stat figures take the display face at 400 with no gradient. The design compiles these sizes and weights into the site's `theme:` (`treatments.typeScale: design`, `treatments.figures: display`).
165
254
 
166
255
  The small label above a section heading is **kept** as part of this foundation's voice (operator-disposed 2026-09-22) and is headed toward the treatment below.
167
256
 
@@ -175,6 +264,9 @@ The small label above a section heading is **kept** as part of this foundation's
175
264
  | `footer` | `centered` |
176
265
  | `announcementBanner` | `false` |
177
266
  | `home` | `deck` |
267
+ | `innerPages` | `bare` |
268
+ | `colorMode` | `light` |
269
+ | `chromeStyle` | `minimal` |
178
270
 
179
271
  | Spacing | Value |
180
272
  | ---------------- | -------- |
@@ -187,7 +279,22 @@ The small label above a section heading is **kept** as part of this foundation's
187
279
 
188
280
  <!-- generated:end -->
189
281
 
190
- Home is the `deck` layout: nine full-viewport slides with scroll-snap. The navigation is `mark-only`, the footer is `centered`, and there is no announcement banner (`layout.home: deck`, `layout.nav: mark-only`, `layout.footer: centered` — the design's own knobs, which any template on this design gets without declaring a `layout`). Every page this site carries is listed in its roster of record, `.ailk-site-manifest.json` at the site root. Shared foundation: a 1280px container, sections at 7rem (4rem below 1024px), card grids at 1.5rem, breakpoints 320 / 768 / 1024 / 1440.
282
+ Home is the `deck` layout: one full-viewport slide per home section, with scroll-snap. The landing is bondcap's first slide, and it carries the brand: the site's wordmark (`/wordmark.svg`, or the home hero's own `lockup`) sits in the headline's place, centred in a viewport-filling band, with one action below it drawn as a pill whatever the corner treatment, and the deck's chevron at its foot. The home hero's `backdrop` image, when one is set, fills the slide behind them; with none the slide is a clean band in its own ground. The hero's other copy does not show on slide 1, so it belongs on slide 2. The design writes this as its HomePage hero preset (`variant: centered`, `fill: viewport`); an owner who wants a different first slide sets another hero variant, which keeps its own composition and shows the logomark instead. Either way the landing carries the brand, so the header is bare on slide 1 and reveals the mark from slide 2. The header stays bare on every slide: no bar, no rule and no buttons, only the logomark, centred. Each slide is one full viewport with its content centred vertically, and a chevron button at its foot moves to the next slide, and the last slide's up-chevron returns to the first; with reduced motion the move is instant. The footer is the closing slide: one viewport tall, holding only the wordmark, at most two contact lines (the business's town and region, and its contact email) and one muted legal line (`layout.chromeStyle: minimal`, #7742). There is no Sign in or Sign up anywhere on the home; they sit in every inner page's footer. One wheel notch or one swipe moves exactly one slide; there is no animated transition, and with reduced motion the deck scrolls freely. The navigation is `mark-only`, the footer is `centered`, and there is no announcement banner (`layout.home: deck`, `layout.nav: mark-only`, `layout.footer: centered` — the design's own knobs, which any template on this design gets without declaring a `layout`). Every page this site carries is listed in its roster of record, `.ailk-site-manifest.json` at the site root. Shared foundation: a 1280px container, sections at 7rem (4rem below 1024px), card grids at 1.5rem, breakpoints 320 / 768 / 1024 / 1440. On a new site, the home starts as the design's arc — landing, who we are, proof where the site has logos, how we work, what we offer, why us, the person on a solo site — every line a placeholder.
283
+
284
+ ## Page treatments
285
+
286
+ Minimalism renders two kinds of page. These are the bondcap checklist's § A, word for word; its § B and § C are the deck rules, its § E type, ink and buttons, and its § F chrome and system pages.
287
+
288
+ <!-- prettier-ignore -->
289
+ | Treatment | Pages | What applies |
290
+ |---|---|---|
291
+ | Presentation | The home deck; any page an owner marks as a statement page | § B, § C, § E |
292
+ | Document | Pricing, service and product detail, FAQ, glossary, blog, docs, legal, contact, about (for a person-service site, see § D) | § E, § F |
293
+
294
+ A1. On a document page, body content stays left-aligned for reading, and a section may carry more than one action (one per pricing tier, for example).
295
+ A2. A site can keep a standard-style section look on any page type, through the design's per-page-type section presets.
296
+
297
+ A document page's title is centred through this design's per-page-type presets: every inner page type that places a hero carries `hero: { variant: centered }` in the `sections:` block above (F2).
191
298
 
192
299
  ## Copy
193
300
 
@@ -211,6 +318,10 @@ Copy density: sparse — minimalism pages carry far fewer words than a standard
211
318
  | `treatments.eyebrowCase` | `sentence` |
212
319
  | `treatments.placeholders` | `fill` |
213
320
  | `treatments.checkmarks` | `plain` |
321
+ | `treatments.buttonShape` | `pill` |
322
+ | `treatments.typeScale` | `design` |
323
+ | `treatments.darkInk` | `accent` |
324
+ | `treatments.figures` | `display` |
214
325
 
215
326
  <!-- generated:end -->
216
327
 
@@ -220,7 +331,18 @@ Square corners everywhere (`theme.corners: square`) — buttons, cards, the auth
220
331
 
221
332
  ### Buttons
222
333
 
223
- Primary: black fill, white label, 0.5rem corners. Secondary: transparent with a black 1px outline and black label. Both are the library `Button`.
334
+ One shape: every button is a pill (`theme.buttonShape: pill`), while text fields keep the square corners. Primary: black fill, white label. Secondary: transparent with a black 1px outline and black label. Both are the library `Button`. A home slide carries at most one button; any other action on it is a text link.
335
+
336
+ ### Section looks
337
+
338
+ The deck home's sections take these looks from the design's `sections` presets; a document page keeps its sections' own looks and every action.
339
+
340
+ - **Statement** — `content-block` `variant: statement`: one centred display-size headline, two lines at most, nothing else.
341
+ - **List** — `items` `variant: list`: centred display-size rows with no rules and a generous row gap, each row a link, accent ink on a dark slide. A headline with no eyebrow is set as the slide's small section label above the rows.
342
+ - **Logo wall** — `logoCloud` `columns: 5`, `phoneColumns: 2`, `motion: scroll`, `treatment: silhouette`: five columns (two on phones) in one ink, drifting slowly upward between faded edges; `actionStyle: links` makes "View all" a text link.
343
+ - **Portraits** — `team` `variant: with-portraits`: frameless portraits, three columns (two on phones), the grid and a short last row centred, names on hover and focus at desktop width and beneath each portrait on phones, each portrait a link.
344
+ - **One button** — `cta` `actionStyle: one-button`: the first action stays a button, the second is a text link.
345
+ - **Archive** (opt-in, not preset) — `reports-list` `variant: archive`: a centred grid of report links, five per row (three on phones), the last row centred, at the list's row gap; a headline with no eyebrow is the section label.
224
346
 
225
347
  ### Cards / Containers
226
348
 
@@ -228,7 +350,15 @@ White panels with a black 1px outline, 0.75rem corners, `card` (1.5rem) padding.
228
350
 
229
351
  ### Navigation
230
352
 
231
- Mark-only: the logomark alone, top left. No link row and no buttons in the header.
353
+ Mark-only: no link row. On the deck home the header is bare: no bar, no rule and no buttons, only the logomark, centred, revealed from slide 2. Every other page wears the bare header too (`layout.innerPages: bare`, #7742): a back arrow to the home and the logomark, no rule and no buttons. Sign in / Sign up (the Account link when signed in) move to that page's one-bar footer.
354
+
355
+ ### Footer
356
+
357
+ On the deck home the footer is the deck's closing slide (#7742): one viewport tall with its content centred, the wordmark (an image wordmark at the display size), at most two contact lines and one muted legal line (copyright, Privacy, Terms, Cookie settings, FAQ), and an up-chevron button at its foot that returns to the first slide. No nav links, social icons, theme switch, language switcher or Sign in / Sign up. Every other page ends in one bar: the copyright, the legal links and Sign in / Sign up (the Account link when signed in). The cookie banner sits on the page ground with a hairline above it and no shadow, and the deck's chevron rises above it while it shows.
358
+
359
+ ### Index and profile pages
360
+
361
+ The portfolio and services index pages are the label and title centred on the page ground, then the listing unboxed: no grey band, no tinted tile and no card frame. The About page and each team member's page (`/team/<slug>`) are profiles: the name centred and large, the bio on the left and a frameless portrait on the right, stacked portrait first on a phone. These are the design's section presets (`sections:` above).
232
362
 
233
363
  ## Where this is heading
234
364
 
@@ -237,7 +367,7 @@ The foundation's pinned direction is the pacing of a classic wireframe marketing
237
367
  | Trait | How it is set |
238
368
  | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
239
369
  | Square corners on buttons, cards and inputs | `theme.corners: square` in `_site.mdx` |
240
- | Section label in sentence case, bold, no tracking | `theme.eyebrowCase: sentence` |
370
+ | Section label in sentence case, no tracking | `theme.eyebrowCase: sentence` |
241
371
  | Solid grey image placeholders, no outline | `theme.placeholders: fill` |
242
372
  | Bare check and cross marks, no circle badge | `theme.checkmarks: plain` |
243
373
  | Plain, uncarded feature and step items | per section: `itemStyle: plain`, and `variant: steps` for an image beside a numbered list |
@@ -249,6 +379,6 @@ The foundation's pinned direction is the pacing of a classic wireframe marketing
249
379
 
250
380
  - **Do** keep every page built from registered sections. If a section you need does not exist, request it rather than writing one-off markup.
251
381
  - **Do** set your brand colours (`primary`, `primaryFg`, `accent`, per mode) in `content/_site.mdx` `brand.colors` and your fonts (`display`, `body`) in `brand.fonts`; they reach every section and survive applying another design, which replaces `theme:`.
252
- - **Don't** add a colour accent. The foundation's one idea is black on white; a brand pass adds colour deliberately, through `brand.colors`.
382
+ - **Don't** add a colour accent to a light ground. The foundation's one idea is black on white; a brand pass adds colour deliberately, through `brand.colors`. `accent` is the ink of headings and labels on a dark ground (`treatments.darkInk: accent`); its value is the site's own, `brand.colors.dark.accent`, and it defaults to white.
253
383
  - **Don't** replace a black rule with a shadow or a grey fill.
254
384
  - **Don't** hard-code the "heading toward" values above into a page. They arrive through the platform, or not at all.