create-ailk 0.6.1 → 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.
Files changed (324) hide show
  1. package/README.md +87 -14
  2. package/component-catalog.json +735 -95
  3. package/component-catalog.md +13 -7
  4. package/dist/add-module-core.d.ts +22 -0
  5. package/dist/add-module-core.js +50 -0
  6. package/dist/add-module.d.ts +89 -0
  7. package/dist/add-module.js +334 -0
  8. package/dist/category-profile.d.ts +126 -0
  9. package/dist/category-profile.js +262 -0
  10. package/dist/cli.js +89 -29
  11. package/dist/index.d.ts +4 -2
  12. package/dist/index.js +6 -1
  13. package/dist/lib/extract-module-bundle.d.ts +56 -1
  14. package/dist/lib/extract-module-bundle.js +170 -14
  15. package/dist/lib/license-key-files.d.ts +15 -0
  16. package/dist/lib/license-key-files.js +102 -0
  17. package/dist/lib/module-license-gate.d.ts +79 -0
  18. package/dist/lib/module-license-gate.js +160 -12
  19. package/dist/lib/module-tier.d.ts +45 -16
  20. package/dist/lib/module-tier.js +76 -0
  21. package/dist/lib/pro-callout.d.ts +16 -10
  22. package/dist/lib/pro-callout.js +34 -3
  23. package/dist/license-set.d.ts +34 -0
  24. package/dist/license-set.js +194 -0
  25. package/dist/module-architecture.d.ts +20 -0
  26. package/dist/module-architecture.js +77 -19
  27. package/dist/modules/commerce/0.6.1.tar.gz +0 -0
  28. package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
  29. package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
  30. package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
  31. package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
  32. package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
  33. package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
  34. package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
  35. package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
  36. package/dist/modules/workspace/0.6.1.tar.gz +0 -0
  37. package/dist/parse-args.d.ts +85 -10
  38. package/dist/parse-args.js +227 -15
  39. package/dist/programmatic.d.ts +81 -5
  40. package/dist/programmatic.js +291 -32
  41. package/dist/site-chrome.d.ts +18 -7
  42. package/dist/site-chrome.js +32 -14
  43. package/dist/site-roster.d.ts +127 -0
  44. package/dist/site-roster.js +499 -0
  45. package/dist/starter-grid.d.ts +216 -0
  46. package/dist/starter-grid.js +449 -0
  47. package/dist/surfaces.d.ts +20 -7
  48. package/dist/surfaces.js +204 -24
  49. package/dist/sync-routes.d.ts +9 -0
  50. package/dist/sync-routes.js +2 -2
  51. package/dist/template-manifest.d.ts +94 -19
  52. package/dist/template-manifest.js +170 -289
  53. package/dist/template-names.d.ts +14 -12
  54. package/dist/template-names.js +13 -17
  55. package/package.json +6 -4
  56. package/site-templates/_base/content/en/BookCall/book-call.mdx +52 -0
  57. package/site-templates/_base/content/en/Feature/feature-1.mdx +69 -0
  58. package/site-templates/_base/content/en/Feature/feature-2.mdx +69 -0
  59. package/site-templates/_base/content/en/Feature/feature-3.mdx +69 -0
  60. package/site-templates/_base/content/en/FeaturesList/features.mdx +91 -0
  61. package/site-templates/_base/content/en/GlossaryList/glossary.mdx +65 -0
  62. package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +67 -0
  63. package/site-templates/_base/content/en/PortfolioItem/sample-four.mdx +105 -0
  64. package/site-templates/_base/content/en/PortfolioItem/sample-one.mdx +34 -0
  65. package/site-templates/_base/content/en/PortfolioItem/sample-three.mdx +94 -0
  66. package/site-templates/_base/content/en/PortfolioItem/sample-two.mdx +45 -0
  67. package/site-templates/_base/content/en/PortfolioList/portfolio.mdx +169 -0
  68. package/site-templates/_base/content/en/Pricing/pricing.mdx +71 -62
  69. package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +17 -3
  70. package/site-templates/_base/content/en/TermsPage/terms.mdx +2 -3
  71. package/site-templates/_base/content/en/UseCase/persona-1.mdx +69 -0
  72. package/site-templates/_base/content/en/UseCase/persona-2.mdx +69 -0
  73. package/site-templates/_base/content/en/UseCase/persona-3.mdx +69 -0
  74. package/site-templates/designs/minimalism/DESIGN.md +162 -0
  75. package/site-templates/designs/standard/DESIGN.md +167 -0
  76. package/site-templates/marketing-site/DESIGN.md +59 -40
  77. package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +376 -57
  78. package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +230 -90
  79. package/site-templates/marketing-site/ailk-template.json +1 -0
  80. package/site-templates/marketing-site-free/DESIGN.md +59 -40
  81. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +323 -63
  82. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +323 -113
  83. package/site-templates/marketing-site-free/ailk-template.json +3 -2
  84. package/site-templates/marketing-site-free/content/en/NewsletterSignup/newsletter.mdx +59 -0
  85. package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +199 -0
  86. package/site-templates/minimalism-site/DESIGN.md +54 -40
  87. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +246 -19
  88. package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +173 -51
  89. package/site-templates/minimalism-site/ailk-template.json +3 -2
  90. package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +52 -0
  91. package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +3 -37
  92. package/site-templates/minimalism-site/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  93. package/site-templates/saas-product/DESIGN.md +59 -40
  94. package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
  95. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.json +369 -0
  96. package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +302 -0
  97. package/site-templates/shapes/local-business-service/ailk-template.json +10 -0
  98. package/site-templates/{simple-service → shapes/local-business-service}/content/en/AboutPage/about.mdx +4 -4
  99. package/site-templates/shapes/local-business-service/content/en/HomePage/home.mdx +70 -0
  100. package/site-templates/shapes/local-business-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  101. package/site-templates/shapes/local-business-service/content/en/PortfolioList/portfolio.mdx +171 -0
  102. package/site-templates/shapes/local-business-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  103. package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +39 -0
  104. package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +39 -0
  105. package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +39 -0
  106. package/site-templates/shapes/local-business-service/content/en/ServicesList/services.mdx +61 -0
  107. package/site-templates/shapes/local-business-service/provenance.json +4 -0
  108. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +362 -0
  109. package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +300 -0
  110. package/site-templates/shapes/organization-service/ailk-template.json +10 -0
  111. package/site-templates/shapes/organization-service/content/en/AboutPage/about.mdx +38 -0
  112. package/site-templates/shapes/organization-service/content/en/HomePage/home.mdx +85 -0
  113. package/site-templates/shapes/organization-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  114. package/site-templates/shapes/organization-service/content/en/PortfolioList/portfolio.mdx +171 -0
  115. package/site-templates/shapes/organization-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  116. package/site-templates/shapes/organization-service/content/en/Service/first-engagement.mdx +38 -0
  117. package/site-templates/shapes/organization-service/content/en/Service/second-engagement.mdx +38 -0
  118. package/site-templates/shapes/organization-service/content/en/Service/third-engagement.mdx +38 -0
  119. package/site-templates/shapes/organization-service/content/en/ServicesList/services.mdx +72 -0
  120. package/site-templates/shapes/organization-service/provenance.json +4 -0
  121. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +369 -0
  122. package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +299 -0
  123. package/site-templates/shapes/person-service/ailk-template.json +10 -0
  124. package/site-templates/shapes/person-service/content/_site.mdx +85 -0
  125. package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +39 -0
  126. package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +97 -0
  127. package/site-templates/shapes/person-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
  128. package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +169 -0
  129. package/site-templates/shapes/person-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
  130. package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +38 -0
  131. package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +38 -0
  132. package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +38 -0
  133. package/site-templates/{simple-service → shapes/person-service}/content/en/ServicesList/services.mdx +16 -16
  134. package/site-templates/shapes/person-service/provenance.json +4 -0
  135. package/templates/.claude/settings.json +15 -0
  136. package/templates/.claude/skills/README.md +10 -9
  137. package/templates/.claude/skills/{scaffold-auth → add-auth}/SKILL.md +7 -7
  138. package/templates/.claude/skills/{scaffold-auth → add-auth}/references/env-vars.md +2 -2
  139. package/templates/.claude/skills/{scaffold-auth → add-auth}/references/oauth-app-setup.md +3 -3
  140. package/templates/.claude/skills/{scaffold-page → add-page}/SKILL.md +76 -62
  141. package/templates/.claude/skills/add-page/references/page-types.md +115 -0
  142. package/templates/.claude/skills/{scaffold-page → add-page}/templates/content.mdx.tmpl +4 -4
  143. package/templates/.claude/skills/{scaffold-page → add-page}/templates/route.tsx.tmpl +1 -1
  144. package/templates/.claude/skills/{audit-site → check-site}/SKILL.md +16 -17
  145. package/templates/.claude/skills/{audit-site → check-site}/references/common-errors.md +3 -3
  146. package/templates/.claude/skills/{audit-site → check-site}/references/findings-glossary.md +16 -14
  147. package/templates/.claude/skills/{audit-site → check-site}/references/severity-levels.md +1 -1
  148. package/templates/.claude/skills/fill-page/SKILL.md +180 -0
  149. package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +80 -0
  150. package/templates/.claude/skills/fill-page/references/section-sources.md +41 -0
  151. package/templates/.claude/skills/setup-database/SKILL.md +156 -0
  152. package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +154 -0
  153. package/templates/.claude/skills/{provision-config → setup-deploy}/SKILL.md +73 -41
  154. package/templates/.claude/skills/{provision-config → setup-deploy}/references/env-vars-template.md +21 -30
  155. package/templates/.claude/skills/setup-deploy/references/runbook-template.md +204 -0
  156. package/templates/.claude/skills/{provision-config → setup-deploy}/references/vercel-json-template.md +1 -1
  157. package/templates/.claude/skills/upgrade-plan/SKILL.md +117 -0
  158. package/templates/.claude/skills/upgrade-plan/references/options.md +24 -0
  159. package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +527 -0
  160. package/templates/.github/workflows/ci.yml +5 -0
  161. package/templates/CLAUDE.md +8 -2
  162. package/templates/DESIGN.md +56 -44
  163. package/templates/README.md +116 -46
  164. package/templates/apps/api/.env.example +2 -1
  165. package/templates/apps/api/CLAUDE.md +3 -2
  166. package/templates/apps/api/package.json +1 -1
  167. package/templates/apps/api/src/config/__tests__/index.test.ts +146 -10
  168. package/templates/apps/api/src/config/index.ts +46 -14
  169. package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +30 -0
  170. package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +96 -0
  171. package/templates/apps/api/src/lib/lead-capture-store.ts +12 -0
  172. package/templates/apps/api/src/lib/lead-delivery.ts +52 -0
  173. package/templates/apps/api/src/lib/license-key-store.ts +45 -0
  174. package/templates/apps/api/src/lib/site.ts +5 -3
  175. package/templates/apps/api/src/middleware/__tests__/auth.database-not-configured.test.ts +97 -0
  176. package/templates/apps/api/src/middleware/auth.ts +9 -0
  177. package/templates/apps/api/src/openapi/spec.ts +63 -12
  178. package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +127 -5
  179. package/templates/apps/api/src/routes/content/get-page.ts +86 -2
  180. package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +88 -0
  181. package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +100 -0
  182. package/templates/apps/api/src/routes/leads/index.ts +46 -1
  183. package/templates/apps/api/src/server.ts +13 -0
  184. package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +194 -0
  185. package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +124 -0
  186. package/templates/apps/api/src/services/lead-routing.ts +140 -30
  187. package/templates/apps/api/src/services/leads-inbox.ts +48 -11
  188. package/templates/apps/mcp/__tests__/audit-single-page.test.ts +75 -1
  189. package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +57 -9
  190. package/templates/apps/mcp/__tests__/parity.test.ts +5 -4
  191. package/templates/apps/mcp/package.json +2 -1
  192. package/templates/apps/mcp/src/index.ts +7 -0
  193. package/templates/apps/mcp/src/lib/audit-single-page.ts +36 -10
  194. package/templates/apps/mcp/src/lib/license-key-store.ts +45 -0
  195. package/templates/apps/mcp/src/tools/create_project.ts +21 -6
  196. package/templates/apps/web/__tests__/setup.ts +18 -0
  197. package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +10 -2
  198. package/templates/apps/web/app/[locale]/(auth)/layout.tsx +2 -2
  199. package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +10 -4
  200. package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +22 -14
  201. package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +26 -18
  202. package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +12 -4
  203. package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +35 -4
  204. package/templates/apps/web/app/[locale]/[slug]/page.tsx +49 -9
  205. package/templates/apps/web/app/[locale]/book-a-call/page.tsx +50 -0
  206. package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +3 -3
  207. package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +3 -3
  208. package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +3 -4
  209. package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +67 -29
  210. package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +94 -11
  211. package/templates/apps/web/app/[locale]/contact/__tests__/contact-form-text.test.ts +32 -0
  212. package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +129 -0
  213. package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +228 -86
  214. package/templates/apps/web/app/[locale]/contact/contact-form-text.ts +50 -0
  215. package/templates/apps/web/app/[locale]/contact/contact.actions.ts +73 -20
  216. package/templates/apps/web/app/[locale]/contact/page.tsx +115 -7
  217. package/templates/apps/web/app/[locale]/contact/site-contact-email.ts +54 -0
  218. package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +3 -3
  219. package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +3 -4
  220. package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +4 -5
  221. package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +64 -0
  222. package/templates/apps/web/app/[locale]/features/page.tsx +52 -0
  223. package/templates/apps/web/app/[locale]/glossary/page.tsx +50 -0
  224. package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +1 -1
  225. package/templates/apps/web/app/[locale]/how-to/page.tsx +25 -15
  226. package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +3 -3
  227. package/templates/apps/web/app/[locale]/layout.tsx +146 -52
  228. package/templates/apps/web/app/[locale]/newsletter/__tests__/newsletter.actions.test.ts +75 -0
  229. package/templates/apps/web/app/[locale]/newsletter/__tests__/page.test.tsx +163 -0
  230. package/templates/apps/web/app/[locale]/newsletter/newsletter.actions.ts +66 -0
  231. package/templates/apps/web/app/[locale]/newsletter/page.tsx +142 -0
  232. package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +3 -3
  233. package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +59 -0
  234. package/templates/apps/web/app/[locale]/portfolio/page.tsx +49 -0
  235. package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +3 -3
  236. package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +4 -5
  237. package/templates/apps/web/app/[locale]/{cancellation → purchase-policy}/page.tsx +15 -10
  238. package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +4 -5
  239. package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +3 -3
  240. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +14 -1
  241. package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +1 -1
  242. package/templates/apps/web/app/[locale]/software/page.tsx +25 -15
  243. package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +1 -1
  244. package/templates/apps/web/app/[locale]/tech-articles/page.tsx +25 -15
  245. package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +3 -4
  246. package/templates/apps/web/app/[locale]/use-cases/[slug]/page.tsx +63 -0
  247. package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +3 -4
  248. package/templates/apps/web/app/[locale]/use-cases/page.tsx +15 -2
  249. package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +1 -1
  250. package/templates/apps/web/app/[locale]/whitepapers/page.tsx +25 -15
  251. package/templates/apps/web/app/error-fallback.tsx +17 -45
  252. package/templates/apps/web/app/not-found.tsx +14 -38
  253. package/templates/apps/web/app/og/route.tsx +6 -0
  254. package/templates/apps/web/eslint.config.mjs +3 -0
  255. package/templates/apps/web/instrumentation.ts +14 -0
  256. package/templates/apps/web/lib/__tests__/structured-data.test.tsx +38 -0
  257. package/templates/apps/web/lib/license-key-store.ts +52 -0
  258. package/templates/apps/web/lib/nav-config.ts +82 -18
  259. package/templates/apps/web/lib/prisma-for-auth.ts +9 -6
  260. package/templates/apps/web/lib/site-brand.tsx +1 -1
  261. package/templates/apps/web/lib/site-chrome.ts +3 -3
  262. package/templates/apps/web/lib/site-identity.ts +148 -0
  263. package/templates/apps/web/lib/site-theme.ts +11 -0
  264. package/templates/apps/web/messages/en.json +78 -37
  265. package/templates/apps/web/public/android-chrome-192x192.png +0 -0
  266. package/templates/apps/web/public/android-chrome-512x512.png +0 -0
  267. package/templates/apps/web/public/apple-touch-icon.png +0 -0
  268. package/templates/apps/web/public/favicon-16x16.png +0 -0
  269. package/templates/apps/web/public/favicon-32x32.png +0 -0
  270. package/templates/apps/web/public/favicon.ico +0 -0
  271. package/templates/apps/web/public/favicon.svg +3 -3
  272. package/templates/apps/web/public/logomark.svg +6 -3
  273. package/templates/apps/web/public/logos/ai-launch-kit-light.svg +4 -0
  274. package/templates/apps/web/public/logos/ai-launch-kit.svg +4 -0
  275. package/templates/apps/web/public/logos/atomic-agent-light.svg +4 -0
  276. package/templates/apps/web/public/logos/atomic-agent.svg +4 -0
  277. package/templates/apps/web/public/logos/salessmyth-light.svg +4 -0
  278. package/templates/apps/web/public/logos/salessmyth.svg +4 -0
  279. package/templates/apps/web/public/site.webmanifest +4 -4
  280. package/templates/apps/web/public/wordmark-light.svg +4 -0
  281. package/templates/apps/web/public/wordmark.svg +3 -3
  282. package/templates/apps/web/security-headers.config.ts +5 -1
  283. package/templates/content/_site.mdx +25 -0
  284. package/templates/content/en/AboutPage/about.mdx +150 -144
  285. package/templates/content/en/BlogList/blog.mdx +126 -0
  286. package/templates/content/en/ContactPage/contact.mdx +21 -92
  287. package/templates/content/en/FAQPage/faq.mdx +86 -57
  288. package/templates/content/en/HomePage/home.mdx +268 -217
  289. package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +181 -0
  290. package/templates/content/en/UseCasesList/use-cases.mdx +170 -0
  291. package/templates/database/CHANGELOG.md +14 -0
  292. package/templates/database/package.json +1 -1
  293. package/templates/package.json +3 -1
  294. package/templates/tools/lint-architecture.ts +315 -0
  295. package/templates/tools/tsconfig.json +14 -0
  296. package/versions.json +33 -33
  297. package/site-templates/simple-service/DESIGN.md +0 -148
  298. package/site-templates/simple-service/TEMPLATE-MANIFEST.json +0 -240
  299. package/site-templates/simple-service/TEMPLATE-MANIFEST.md +0 -278
  300. package/site-templates/simple-service/ailk-template.json +0 -10
  301. package/site-templates/simple-service/content/en/ContactPage/contact.mdx +0 -67
  302. package/site-templates/simple-service/content/en/FAQPage/faq.mdx +0 -56
  303. package/site-templates/simple-service/content/en/HomePage/home.mdx +0 -85
  304. package/site-templates/simple-service/content/en/Service/landscape-design.mdx +0 -40
  305. package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +0 -40
  306. package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +0 -40
  307. package/site-templates/simple-service/provenance.json +0 -4
  308. package/templates/.claude/skills/add-schema/SKILL.md +0 -277
  309. package/templates/.claude/skills/add-schema/references/conflict-handling.md +0 -200
  310. package/templates/.claude/skills/add-schema/references/file-finding.md +0 -123
  311. package/templates/.claude/skills/add-schema/references/schema-types.md +0 -234
  312. package/templates/.claude/skills/provision-config/references/runbook-template.md +0 -248
  313. package/templates/.claude/skills/scaffold-page/references/page-types.md +0 -169
  314. package/templates/.claude/skills/suggest-site-pages/SKILL.md +0 -242
  315. package/templates/.claude/skills/suggest-site-pages/references/categories.md +0 -287
  316. package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +0 -150
  317. package/templates/apps/web/app/[locale]/returns/page.tsx +0 -44
  318. package/templates/apps/web/app/[locale]/shipping/page.tsx +0 -44
  319. package/templates/content/en/CancellationPolicyPage/cancellation.mdx +0 -108
  320. package/templates/content/en/LandingPage/blog.mdx +0 -83
  321. package/templates/content/en/LandingPage/features.mdx +0 -103
  322. package/templates/content/en/LandingPage/how-it-works.mdx +0 -143
  323. package/templates/content/en/ReturnsPolicyPage/returns.mdx +0 -108
  324. package/templates/content/en/ShippingPolicyPage/shipping.mdx +0 -108
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Architecture Boundary Linter — enforces this site's `architecture.yaml`.
4
+ *
5
+ * `architecture.yaml` is generated by create-ailk from the selected module
6
+ * set; this file is what makes it more than prose. It walks `apps/` and
7
+ * `database/` for .ts/.tsx files and reports:
8
+ *
9
+ * - apps do not import apps — any file under `apps/<a>/` (or `database/`)
10
+ * importing `apps/<b>/`, by package name or by relative path, whether or
11
+ * not architecture.yaml declares either app;
12
+ * - `may_not_import_from` / `may_import_from` per declared app;
13
+ * - the global and per-app `forbidden_patterns` (with `paths_excluded`);
14
+ * - the `namespaces` boundaries inside `database/`, when declared:
15
+ * cross-namespace relative imports and cross-namespace Prisma `@relation`
16
+ * directives.
17
+ *
18
+ * An import target is checked only when it is a workspace present in this
19
+ * repo (`apps/*`, `database`); `@working-theory/*` libraries install from npm
20
+ * and are not source here.
21
+ *
22
+ * Usage:
23
+ * pnpm architecture # or: tsx tools/lint-architecture.ts
24
+ *
25
+ * Exit codes:
26
+ * 0 — no violations
27
+ * 1 — violations found (each names the file, the line and the rule)
28
+ */
29
+
30
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
31
+ import { dirname, join, relative, resolve, sep } from "node:path";
32
+
33
+ import { parse as parseYaml } from "yaml";
34
+
35
+ interface ForbiddenPattern {
36
+ pattern: string;
37
+ reason: string;
38
+ paths_excluded?: string[];
39
+ }
40
+
41
+ interface AppRule {
42
+ path: string;
43
+ may_import_from?: string[];
44
+ may_not_import_from?: string[];
45
+ forbidden_patterns?: ForbiddenPattern[];
46
+ }
47
+
48
+ interface ArchConfig {
49
+ apps?: Record<string, AppRule>;
50
+ forbidden_patterns?: ForbiddenPattern[];
51
+ namespaces?: { members?: Record<string, { path: string }> };
52
+ }
53
+
54
+ interface Violation {
55
+ file: string;
56
+ line: number;
57
+ rule: string;
58
+ reason: string;
59
+ }
60
+
61
+ const ROOT = resolve(dirname(process.argv[1] ?? "."), "..");
62
+ const SKIP_DIRS = new Set([
63
+ "node_modules",
64
+ "dist",
65
+ ".next",
66
+ ".turbo",
67
+ ".source",
68
+ "coverage",
69
+ "generated",
70
+ ]);
71
+ const IMPORT_RE =
72
+ /(?:^|[\n;])\s*(?:import\s+(?:type\s+)?|export\s+(?:type\s+)?(?=[*{]))[^;'"]*?\bfrom\s+['"]([^'"]+)['"]/g;
73
+ const SIDE_EFFECT_IMPORT_RE = /(?:^|[\n;])\s*import\s+['"]([^'"]+)['"]/g;
74
+ const DYNAMIC_IMPORT_RE = /\b(?:import|require)\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
75
+
76
+ function toPosix(p: string): string {
77
+ return p.split(sep).join("/");
78
+ }
79
+
80
+ function rel(abs: string): string {
81
+ return toPosix(relative(ROOT, abs));
82
+ }
83
+
84
+ function walk(dir: string, match: RegExp, out: string[] = []): string[] {
85
+ if (!existsSync(dir)) return out;
86
+ for (const entry of readdirSync(dir)) {
87
+ if (SKIP_DIRS.has(entry)) continue;
88
+ const p = join(dir, entry);
89
+ if (statSync(p).isDirectory()) walk(p, match, out);
90
+ else if (match.test(entry) && !entry.endsWith(".d.ts")) out.push(p);
91
+ }
92
+ return out;
93
+ }
94
+
95
+ /** Every workspace in this repo: `apps/<name>` for each app dir, plus `database`. */
96
+ function workspacesOnDisk(): string[] {
97
+ const out: string[] = [];
98
+ const appsDir = join(ROOT, "apps");
99
+ if (existsSync(appsDir)) {
100
+ for (const entry of readdirSync(appsDir).sort()) {
101
+ if (statSync(join(appsDir, entry)).isDirectory()) out.push(`apps/${entry}`);
102
+ }
103
+ }
104
+ if (existsSync(join(ROOT, "database"))) out.push("database");
105
+ return out;
106
+ }
107
+
108
+ /** Package name → workspace, read from each workspace's own package.json. */
109
+ function packageNames(workspaces: string[]): Map<string, string> {
110
+ const names = new Map<string, string>();
111
+ for (const ws of workspaces) {
112
+ const pkgPath = join(ROOT, ws, "package.json");
113
+ if (!existsSync(pkgPath)) continue;
114
+ const name = (JSON.parse(readFileSync(pkgPath, "utf8")) as { name?: unknown })
115
+ .name;
116
+ if (typeof name === "string") names.set(name, ws);
117
+ }
118
+ return names;
119
+ }
120
+
121
+ function workspaceOfPath(relPath: string, workspaces: string[]): string | null {
122
+ for (const ws of workspaces) {
123
+ if (relPath === ws || relPath.startsWith(`${ws}/`)) return ws;
124
+ }
125
+ return null;
126
+ }
127
+
128
+ function extractImports(content: string): { specifier: string; line: number }[] {
129
+ const lineOf = (offset: number) => content.slice(0, offset).split("\n").length;
130
+ const out: { specifier: string; line: number }[] = [];
131
+ for (const re of [IMPORT_RE, SIDE_EFFECT_IMPORT_RE, DYNAMIC_IMPORT_RE]) {
132
+ for (const m of content.matchAll(re)) {
133
+ // The newline/semicolon (and blank lines) the static regexes anchor on
134
+ // belong to earlier lines; count from the import keyword itself.
135
+ const lead = Math.max(0, m[0].search(/[^\s;]/));
136
+ if (m[1]) out.push({ specifier: m[1], line: lineOf((m.index ?? 0) + lead) });
137
+ }
138
+ }
139
+ return out;
140
+ }
141
+
142
+ function resolveTarget(
143
+ file: string,
144
+ specifier: string,
145
+ workspaces: string[],
146
+ names: Map<string, string>,
147
+ ): string | null {
148
+ if (specifier.startsWith(".")) {
149
+ return workspaceOfPath(rel(resolve(dirname(file), specifier)), workspaces);
150
+ }
151
+ for (const [name, ws] of names) {
152
+ if (specifier === name || specifier.startsWith(`${name}/`)) return ws;
153
+ }
154
+ return null;
155
+ }
156
+
157
+ function checkImport(
158
+ fileWs: string,
159
+ targetWs: string,
160
+ cfg: ArchConfig,
161
+ ): { rule: string; reason: string } | null {
162
+ if (targetWs.startsWith("apps/")) {
163
+ return fileWs.startsWith("apps/")
164
+ ? {
165
+ rule: `${fileWs} may not import ${targetWs} — apps do not import apps`,
166
+ reason:
167
+ "Apps talk over HTTP (web → api) and MCP (mcp → api); shared code belongs in a package.",
168
+ }
169
+ : {
170
+ rule: `${fileWs} may not import ${targetWs} — the data tier imports no app`,
171
+ reason: "database/ sits below every app; apps import it, never the reverse.",
172
+ };
173
+ }
174
+ const rule = fileWs.startsWith("apps/")
175
+ ? cfg.apps?.[fileWs.slice("apps/".length)]
176
+ : undefined;
177
+ if (!rule) return null;
178
+ if (rule.may_not_import_from?.includes(targetWs)) {
179
+ return {
180
+ rule: `${fileWs} may_not_import_from ${targetWs}`,
181
+ reason: "Forbidden by architecture.yaml",
182
+ };
183
+ }
184
+ if (rule.may_import_from?.length && !rule.may_import_from.includes(targetWs)) {
185
+ return {
186
+ rule: `${fileWs} may_import_from does not include ${targetWs}`,
187
+ reason: `Not on ${fileWs}'s allowlist in architecture.yaml`,
188
+ };
189
+ }
190
+ return null;
191
+ }
192
+
193
+ function isExcluded(relPath: string, globs: string[] | undefined): boolean {
194
+ return (globs ?? []).some((glob) =>
195
+ glob.endsWith("/**") ? relPath.startsWith(glob.slice(0, -2)) : relPath === glob,
196
+ );
197
+ }
198
+
199
+ function checkForbiddenPattern(
200
+ file: string,
201
+ content: string,
202
+ fp: ForbiddenPattern,
203
+ ): Violation[] {
204
+ if (isExcluded(rel(file), fp.paths_excluded)) return [];
205
+ const re = new RegExp(fp.pattern);
206
+ const out: Violation[] = [];
207
+ content.split("\n").forEach((text, i) => {
208
+ if (re.test(text)) {
209
+ out.push({ file, line: i + 1, rule: `forbidden_pattern: ${fp.pattern}`, reason: fp.reason });
210
+ }
211
+ });
212
+ return out;
213
+ }
214
+
215
+ /** Namespace boundaries inside database/ — imports and Prisma @relation. */
216
+ function checkNamespaces(cfg: ArchConfig): Violation[] {
217
+ const members = Object.values(cfg.namespaces?.members ?? {}).map((m) => m.path);
218
+ if (members.length === 0) return [];
219
+ const nsOf = (relPath: string) => workspaceOfPath(relPath, members);
220
+ const dbDir = join(ROOT, "database");
221
+ const out: Violation[] = [];
222
+
223
+ for (const file of walk(dbDir, /\.tsx?$/)) {
224
+ const fromNs = nsOf(rel(file));
225
+ if (!fromNs) continue;
226
+ for (const imp of extractImports(readFileSync(file, "utf8"))) {
227
+ if (!imp.specifier.startsWith(".")) continue;
228
+ const toNs = nsOf(rel(resolve(dirname(file), imp.specifier)));
229
+ if (!toNs || toNs === fromNs) continue;
230
+ out.push({
231
+ file,
232
+ line: imp.line,
233
+ rule: `cross-namespace-import: ${fromNs} may not import ${toNs}`,
234
+ reason: "Cross-namespace data assembly routes through apps/api.",
235
+ });
236
+ }
237
+ }
238
+
239
+ const prismaFiles = walk(dbDir, /\.prisma$/);
240
+ const modelNs = new Map<string, string>();
241
+ for (const file of prismaFiles) {
242
+ const ns = nsOf(rel(file));
243
+ if (!ns) continue;
244
+ for (const m of readFileSync(file, "utf8").matchAll(/^\s*model\s+(\w+)\s*\{/gm)) {
245
+ if (m[1] && !modelNs.has(m[1])) modelNs.set(m[1], ns);
246
+ }
247
+ }
248
+ const relationLine = /^\s*\w+\s+(\w+)(\?|\[\])?\s+@relation\s*\(/;
249
+ for (const file of prismaFiles) {
250
+ const fromNs = nsOf(rel(file));
251
+ if (!fromNs) continue;
252
+ readFileSync(file, "utf8")
253
+ .split("\n")
254
+ .forEach((text, i) => {
255
+ const model = relationLine.exec(text)?.[1];
256
+ const toNs = model ? modelNs.get(model) : undefined;
257
+ if (!toNs || toNs === fromNs) return;
258
+ out.push({
259
+ file,
260
+ line: i + 1,
261
+ rule: `cross-namespace-prisma-relation: ${fromNs} may not relate to ${toNs}`,
262
+ reason: `@relation to model '${model}' crosses a namespace boundary.`,
263
+ });
264
+ });
265
+ }
266
+ return out;
267
+ }
268
+
269
+ function main(): void {
270
+ const yamlPath = join(ROOT, "architecture.yaml");
271
+ if (!existsSync(yamlPath)) {
272
+ console.error(`architecture: no architecture.yaml at ${ROOT}`);
273
+ process.exitCode = 1;
274
+ return;
275
+ }
276
+ const cfg = (parseYaml(readFileSync(yamlPath, "utf8")) ?? {}) as ArchConfig;
277
+ const workspaces = workspacesOnDisk();
278
+ const names = packageNames(workspaces);
279
+ const violations: Violation[] = [];
280
+
281
+ for (const ws of workspaces) {
282
+ for (const file of walk(join(ROOT, ws), /\.tsx?$/)) {
283
+ const content = readFileSync(file, "utf8");
284
+ for (const imp of extractImports(content)) {
285
+ const targetWs = resolveTarget(file, imp.specifier, workspaces, names);
286
+ if (!targetWs || targetWs === ws) continue;
287
+ const v = checkImport(ws, targetWs, cfg);
288
+ if (v) violations.push({ file, line: imp.line, ...v });
289
+ }
290
+ for (const fp of cfg.forbidden_patterns ?? []) {
291
+ violations.push(...checkForbiddenPattern(file, content, fp));
292
+ }
293
+ const app = ws.startsWith("apps/") ? cfg.apps?.[ws.slice("apps/".length)] : undefined;
294
+ for (const fp of app?.forbidden_patterns ?? []) {
295
+ violations.push(...checkForbiddenPattern(file, content, fp));
296
+ }
297
+ }
298
+ }
299
+ violations.push(...checkNamespaces(cfg));
300
+
301
+ if (violations.length === 0) {
302
+ console.log("architecture: OK");
303
+ return;
304
+ }
305
+ console.error(`architecture: ${violations.length} violation(s)`);
306
+ for (const v of violations) {
307
+ console.error(` ${rel(v.file)}:${v.line} ${v.rule}`);
308
+ console.error(` ${v.reason}`);
309
+ }
310
+ // exitCode, not exit(): stderr to a pipe is asynchronous on macOS, and the
311
+ // hook reads this report through one.
312
+ process.exitCode = 1;
313
+ }
314
+
315
+ main();
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "noUncheckedIndexedAccess": true,
9
+ "skipLibCheck": true,
10
+ "noEmit": true,
11
+ "types": ["node"]
12
+ },
13
+ "include": ["*.ts"]
14
+ }
package/versions.json CHANGED
@@ -1,39 +1,39 @@
1
1
  {
2
- "@working-theory/admin-ui": "0.26.0",
3
- "@working-theory/aeo": "0.26.0",
4
- "@working-theory/agent-context": "0.26.0",
2
+ "@working-theory/admin-ui": "0.28.0",
3
+ "@working-theory/aeo": "0.28.0",
4
+ "@working-theory/agent-context": "0.28.0",
5
5
  "@working-theory/agent-contract": "0.1.0",
6
6
  "@working-theory/agent-memory": "0.0.0",
7
7
  "@working-theory/ai": "0.1.0",
8
- "@working-theory/analytics": "0.26.0",
9
- "@working-theory/api-client": "0.26.0",
8
+ "@working-theory/analytics": "0.28.0",
9
+ "@working-theory/api-client": "0.28.0",
10
10
  "@working-theory/cda-filesystem": "0.0.0",
11
- "@working-theory/cli": "0.26.0",
12
- "@working-theory/common": "0.26.0",
11
+ "@working-theory/cli": "0.28.0",
12
+ "@working-theory/common": "0.28.0",
13
13
  "@working-theory/consent": "0.1.0",
14
- "@working-theory/content-adapters": "0.26.0",
15
- "@working-theory/content-projection": "0.26.0",
16
- "@working-theory/email": "0.26.0",
14
+ "@working-theory/content-adapters": "0.28.0",
15
+ "@working-theory/content-projection": "0.28.0",
16
+ "@working-theory/email": "0.28.0",
17
17
  "@working-theory/env": "0.0.0",
18
- "@working-theory/eslint-config": "0.26.0",
19
- "@working-theory/fumadocs-schema": "0.26.0",
18
+ "@working-theory/eslint-config": "0.28.0",
19
+ "@working-theory/fumadocs-schema": "0.28.0",
20
20
  "@working-theory/ids": "0.8.0",
21
- "@working-theory/jsonld": "0.26.0",
22
- "@working-theory/license": "0.26.0",
23
- "@working-theory/metadata": "0.26.0",
24
- "@working-theory/observability": "0.26.0",
25
- "@working-theory/page-renderer": "0.26.0",
26
- "@working-theory/schema": "0.26.0",
27
- "@working-theory/schema-pack-registry": "0.26.0",
28
- "@working-theory/schema-validator": "0.26.0",
29
- "@working-theory/sections-registry": "0.26.0",
30
- "@working-theory/site-config": "0.26.0",
31
- "@working-theory/stripe-client": "0.26.0",
32
- "@working-theory/templates": "0.26.0",
33
- "@working-theory/theme": "0.26.0",
34
- "@working-theory/ui": "0.26.0",
35
- "@working-theory/validation": "0.26.0",
36
- "@working-theory/web-i18n": "0.26.0",
21
+ "@working-theory/jsonld": "0.28.0",
22
+ "@working-theory/license": "0.28.0",
23
+ "@working-theory/metadata": "0.28.0",
24
+ "@working-theory/observability": "0.28.0",
25
+ "@working-theory/page-renderer": "0.28.0",
26
+ "@working-theory/schema": "0.28.0",
27
+ "@working-theory/schema-pack-registry": "0.28.0",
28
+ "@working-theory/schema-validator": "0.28.0",
29
+ "@working-theory/sections-registry": "0.28.0",
30
+ "@working-theory/site-config": "0.28.0",
31
+ "@working-theory/stripe-client": "0.28.0",
32
+ "@working-theory/templates": "0.28.0",
33
+ "@working-theory/theme": "0.28.0",
34
+ "@working-theory/ui": "0.28.0",
35
+ "@working-theory/validation": "0.28.0",
36
+ "@working-theory/web-i18n": "0.28.0",
37
37
  "@working-theory/billing-client": "0.0.0",
38
38
  "@working-theory/branding": "0.0.0",
39
39
  "@working-theory/license-client": "0.0.0",
@@ -41,12 +41,12 @@
41
41
  "@working-theory/marketing-api-client": "0.0.0",
42
42
  "@working-theory/partner-session": "0.0.0",
43
43
  "@working-theory/preview-protocol": "0.0.0",
44
- "@working-theory/ui-commerce": "0.23.3",
45
- "@working-theory/ui-docs-blog": "0.23.3",
46
- "@working-theory/ui-scheduling": "0.23.3",
47
- "@working-theory/ui-signal-collectors": "0.24.1",
44
+ "@working-theory/ui-commerce": "0.23.5",
45
+ "@working-theory/ui-docs-blog": "0.23.5",
46
+ "@working-theory/ui-scheduling": "0.23.5",
47
+ "@working-theory/ui-signal-collectors": "0.24.3",
48
48
  "@working-theory/web": "0.0.0",
49
49
  "@working-theory/api": "1.0.0",
50
50
  "@working-theory/mcp": "0.0.0",
51
- "@working-theory/database": "0.26.0"
51
+ "@working-theory/database": "0.28.0"
52
52
  }
@@ -1,148 +0,0 @@
1
- ---
2
- name: Simple service (Pro) — simple-service
3
- description: A local-service site: three priced services, online booking, checkout, and the policy pages a paying customer expects.
4
- colors:
5
- bg: "#ffffff"
6
- fg: "#000000"
7
- surface: "#ffffff"
8
- surface-secondary: "#ffffff"
9
- border: "#000000"
10
- text-muted: "#333333"
11
- brand: "#000000"
12
- fg-on-brand: "#ffffff"
13
- accent: "#000000"
14
- bg-dark: "#000000"
15
- fg-dark: "#ffffff"
16
- border-dark: "#ffffff"
17
- brand-dark: "#ffffff"
18
- typography:
19
- display:
20
- fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
21
- fontSize: "6rem"
22
- fontWeight: 400
23
- lineHeight: 1
24
- letterSpacing: "-0.05em"
25
- heading-section:
26
- fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
27
- fontSize: "2.25rem"
28
- fontWeight: 400
29
- lineHeight: 1.25
30
- letterSpacing: "-0.05em"
31
- heading-item:
32
- fontSize: "1.25rem"
33
- fontWeight: 600
34
- lineHeight: 1.375
35
- body:
36
- fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, sans-serif"
37
- fontSize: "1.125rem"
38
- fontWeight: 400
39
- lineHeight: 1.5
40
- eyebrow:
41
- fontSize: "0.875rem"
42
- fontWeight: 600
43
- lineHeight: 1.4
44
- letterSpacing: "0.05em"
45
- rounded:
46
- button: "0.25rem"
47
- card: "0.75rem"
48
- spacing:
49
- section: "4rem"
50
- card: "1.5rem"
51
- grid: "1.5rem"
52
- container: "1280px"
53
- ---
54
-
55
- <!--
56
- Source template: simple-service
57
- Version: create-ailk {{CREATE_AILK_VERSION}}
58
- Extends: _base — installing this template replaces the base scaffold's
59
- DESIGN.md with this file. Its tokens are the base foundation's, unchanged:
60
- this template carries no theme of its own.
61
-
62
- The tokens above describe what the site RENDERS today. Colours come from
63
- content/_site.mdx (`theme.colors`); type, radius and spacing are platform
64
- defaults a site cannot override yet — see "Where this is heading" below.
65
- -->
66
-
67
- # Simple service (Pro)
68
-
69
- ## Overview
70
-
71
- A template for a local service business — the reference shape is a lawn-care company. Three priced services, a booking page, a checkout return pair, a customer account, and the returns, cancellation and shipping policies. It runs on the base foundation; the design job is trust and clarity, so nothing competes with the price and the book button.
72
-
73
- ## Colors
74
-
75
- ### Primary
76
-
77
- **Black** (`brand` `#000000`) fills the primary button; its label is white. The secondary button is white with a black hairline and black label.
78
-
79
- ### Neutral
80
-
81
- 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.
82
-
83
- Dark mode inverts: black ground, white ink, white rules, white primary button with black label.
84
-
85
- ### Named Rules
86
-
87
- - **Rules, not fills.** A container is drawn with a black hairline on the white ground. Grey fills are reserved for image placeholders.
88
-
89
- ## Typography
90
-
91
- System sans throughout; no web font.
92
-
93
- ### Hierarchy
94
-
95
- | Role | Size | Weight | Notes |
96
- | --------------- | -------- | ------ | --------------------------------------------------------------------------- |
97
- | Hero headline | 6rem | 400 | Tracking -0.05em, line-height 1 |
98
- | Section heading | 2.25rem | 400 | Tracking -0.05em — light and tight, not bold |
99
- | Item heading | 1.25rem | 600 | Card, feature and step titles |
100
- | Body | 1.125rem | 400 | `#333333`, line-height 1.5 |
101
- | Section label | 0.875rem | 600 | Uppercase, +0.05em tracking today — the small label above a section heading |
102
-
103
- Measured from the rendered scaffold (1440px wide), not transcribed from tokens.
104
-
105
- 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.
106
-
107
- ## Layout
108
-
109
- Full navigation with the announcement banner; a multi-column footer; the default home. Every page and its sections are listed in `TEMPLATE-MANIFEST.md` in this directory. Shared foundation: a 1280px container, sections at 4rem, card grids at 1.5rem, breakpoints 320 / 768 / 1024 / 1440.
110
-
111
- ## Shapes
112
-
113
- Two radii today: buttons at 0.25rem, cards and outlined boxes at 0.75rem. Headed toward square corners — see below.
114
-
115
- ## Components
116
-
117
- ### Buttons
118
-
119
- Primary: black fill, white label, 0.25rem corners. Secondary: transparent with a black 1px outline and black label. Both are the library `Button`.
120
-
121
- ### Cards / Containers
122
-
123
- White panels with a black 1px outline, 0.75rem corners, `card` (1.5rem) padding. The one exception today: the "how it works" steps render as dark filled cards (see below).
124
-
125
- ### Navigation
126
-
127
- Full navigation: wordmark left, page links, an outlined and a filled button at the far right, the announcement banner above. A black hairline separates it from the page.
128
-
129
- ## Where this is heading
130
-
131
- The foundation's pinned direction is the pacing of a classic wireframe marketing kit — `standardissue.webflow.io` is the reference for rhythm, type scale, spacing density and section pacing only; no image, copy or code is taken from it. Six parts of that direction cannot be expressed through a site's theme today, so they wait on a platform change rather than being hand-coded. Until they land, this file describes the rendered site above, not these targets.
132
-
133
- | Target | Reference value | Blocked by |
134
- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
135
- | Square corners on buttons, cards and inputs | radius 0 | A site's `theme:` block accepts colours only — no radius |
136
- | Bold, tighter headings | hero ~3.6rem and section headings ~2.9rem, both at weight 700 with tracking about -0.02em (today 6rem and 2.25rem at weight 400) | No per-site type-role override |
137
- | Generous section pacing | about 10rem between sections, not 4rem | No per-site section-spacing override; `spacious` (6rem) is not author-selectable |
138
- | Section label in sentence case, bold, no tracking | "Core Features", not "CORE FEATURES" | The eyebrow role bakes in uppercase and tracking |
139
- | Whitespace between sections, not rules | no rule between bands | Section dividers share the one `border` colour with card outlines, so black outlines make black dividers |
140
- | Outlined steps in "how it works" | three plain outlined columns | The steps section renders dark filled cards; no outlined variant |
141
-
142
- ## Do's and Don'ts
143
-
144
- - **Do** keep every page built from registered sections. If a section you need does not exist, request it rather than writing one-off markup.
145
- - **Do** change colours in `content/_site.mdx` `theme.colors`; they reach every section.
146
- - **Don't** add a colour accent. The foundation's one idea is black on white; a brand pass adds colour deliberately, through the theme.
147
- - **Don't** replace a black rule with a shadow or a grey fill.
148
- - **Don't** hard-code the "heading toward" values above into a page. They arrive through the platform, or not at all.