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
@@ -1,287 +0,0 @@
1
- # Site-page categories — v1 corpus
2
-
3
- The 10 business categories `suggest-site-pages` knows about, with the
4
- ordered page list and primary schema.org type for each page. Schemas
5
- are drawn from the 60 page types `@working-theory/schema` builds; nothing in
6
- this file should reference a type the package can't generate.
7
-
8
- ## How to read this file
9
-
10
- Each category section has:
11
-
12
- 1. **Name and description** — what the category covers.
13
- 2. **Entity tag** — `organization`, `person`, or `both`. Drives whether
14
- `suggest-site-pages` asks the Person-vs-Organization disambiguation
15
- question.
16
- 3. **Page list** — ordered. The slug is what `scaffold-page` will use.
17
- 4. **Primary schema per page** — the `Schema.orgType` to emit.
18
-
19
- When the entity tag is `both`, some pages (typically home, about,
20
- contact) carry an identity that flips between `Organization` and
21
- `Person` based on the consumer's answer. The page's _own_ schema type
22
- (`HomePage`, `AboutPage`, `ContactPage`) does not change; only the
23
- identity attached inside the JSON-LD does.
24
-
25
- ---
26
-
27
- ## SaaS
28
-
29
- Software-as-a-service products — anything where the value prop is
30
- "sign up and use the software." Includes vertical SaaS, horizontal
31
- tools, dev platforms, and self-serve B2B.
32
-
33
- - **Entity tag:** `organization`
34
- - **Pages:**
35
-
36
- | Slug | Schema.orgType | Purpose |
37
- | ---------- | -------------- | -------------------------------------------------- |
38
- | `home` | `HomePage` | top-of-funnel landing with the headline value prop |
39
- | `about` | `AboutPage` | company story and team |
40
- | `pricing` | `Product` | public price tiers and feature comparison |
41
- | `features` | `ServicesList` | what the product does, broken into capabilities |
42
- | `contact` | `ContactPage` | sales and support entry point |
43
- | `privacy` | `PrivacyPage` | privacy policy |
44
- | `terms` | `TermsPage` | terms of service |
45
-
46
- ---
47
-
48
- ## E-commerce
49
-
50
- Direct-to-consumer or B2B storefronts selling physical or digital
51
- goods. The catalog is the primary surface; everything else supports it.
52
-
53
- - **Entity tag:** `organization`
54
- - **Pages:**
55
-
56
- | Slug | Schema.orgType | Purpose |
57
- | --------- | -------------- | ------------------------------------------- |
58
- | `home` | `HomePage` | featured products and category entry points |
59
- | `shop` | `ProductsList` | the full catalog |
60
- | `about` | `AboutPage` | brand story and what the company makes |
61
- | `contact` | `ContactPage` | customer-service entry point |
62
- | `faq` | `FAQPage` | shipping, returns, sizing, common questions |
63
- | `privacy` | `PrivacyPage` | privacy policy |
64
- | `terms` | `TermsPage` | terms of service |
65
-
66
- Per-product pages use `Product` and live under `shop/<product-slug>`.
67
- `scaffold-page` handles them one at a time once the user has the
68
- catalog page.
69
-
70
- ---
71
-
72
- ## Service business
73
-
74
- Restaurant, salon, contractor, gym, plumber, cleaner — anyone whose
75
- business is "show up and do the work." Owner is usually an entity
76
- (LLC / corp), occasionally a sole proprietor.
77
-
78
- - **Entity tag:** `both`
79
- - **Pages:**
80
-
81
- | Slug | Schema.orgType | Purpose |
82
- | -------------- | ------------------ | --------------------------------------------------- |
83
- | `home` | `HomePage` | what the business does, where, and how to book |
84
- | `services` | `ServicesList` | menu of services offered |
85
- | `about` | `AboutPage` | the operator's story and credentials |
86
- | `contact` | `ContactPage` | hours, address, booking link |
87
- | `testimonials` | `TestimonialsList` | customer reviews and quotes |
88
- | `faq` | `FAQPage` | common questions about service, pricing, scheduling |
89
- | `privacy` | `PrivacyPage` | privacy policy |
90
- | `terms` | `TermsPage` | terms of service |
91
-
92
- Individual services go under `services/<service-slug>` with `Service`
93
- as the type. The home/about/contact pages anchor on `Organization` for
94
- a business entity, `Person` for a sole proprietor.
95
-
96
- ---
97
-
98
- ## Professional services
99
-
100
- Law firms, accounting firms, consulting shops, marketing agencies — fee-for-engagement
101
- expertise. Almost always firm-shaped at scale, but plenty of solo practitioners.
102
-
103
- - **Entity tag:** `both`
104
- - **Pages:**
105
-
106
- | Slug | Schema.orgType | Purpose |
107
- | -------------- | ----------------- | ------------------------------------------------- |
108
- | `home` | `HomePage` | who the firm serves and what kinds of engagements |
109
- | `services` | `ServicesList` | practice areas or service lines |
110
- | `team` | `TeamList` | the people clients will work with |
111
- | `case-studies` | `CaseStudiesList` | engagement outcomes and references |
112
- | `about` | `AboutPage` | firm history, philosophy, credentials |
113
- | `contact` | `ContactPage` | how to reach out about an engagement |
114
- | `blog` | `BlogList` | thought leadership and updates |
115
- | `privacy` | `PrivacyPage` | privacy policy |
116
- | `terms` | `TermsPage` | terms of service |
117
-
118
- For solo practitioners, drop the `team` page and anchor home/about/contact
119
- on `Person` instead of `Organization`.
120
-
121
- ---
122
-
123
- ## Marketplace
124
-
125
- Two-sided platforms — buyers on one side, sellers/providers on the
126
- other. Always organizational; an individual cannot be a marketplace.
127
-
128
- - **Entity tag:** `organization`
129
- - **Pages:**
130
-
131
- | Slug | Schema.orgType | Purpose |
132
- | ------------- | -------------- | ------------------------------------------------ |
133
- | `home` | `HomePage` | the value prop for both sides of the marketplace |
134
- | `for-buyers` | `ServicesList` | what buyers get and how it works |
135
- | `for-sellers` | `ServicesList` | what sellers get and how to onboard |
136
- | `browse` | `ProductsList` | the searchable catalog of listings |
137
- | `about` | `AboutPage` | who runs the platform and why |
138
- | `contact` | `ContactPage` | support entry point |
139
- | `faq` | `FAQPage` | trust, payments, dispute resolution |
140
- | `privacy` | `PrivacyPage` | privacy policy |
141
- | `terms` | `TermsPage` | terms of service |
142
-
143
- ---
144
-
145
- ## Content / Blog
146
-
147
- Publications, personal blogs, newsletters with a website. The
148
- defining feature: posts are the primary surface, not products or
149
- services.
150
-
151
- - **Entity tag:** `both`
152
- - **Pages:**
153
-
154
- | Slug | Schema.orgType | Purpose |
155
- | --------- | -------------- | ----------------------------------------- |
156
- | `home` | `HomePage` | recent and featured posts |
157
- | `blog` | `BlogList` | the full archive |
158
- | `about` | `AboutPage` | who writes and why |
159
- | `contact` | `ContactPage` | how to reach the author or editorial team |
160
- | `privacy` | `PrivacyPage` | privacy policy |
161
- | `terms` | `TermsPage` | terms of service |
162
-
163
- Individual posts use `BlogPosting`. A "personal" blog (one writer,
164
- their name on the site) is `Person`; an editorial publication with a
165
- masthead is `Organization`. Phrases like "personal" or "my" in the
166
- description settle it as Person without asking.
167
-
168
- ---
169
-
170
- ## Course / Education
171
-
172
- Course providers, schools, online academies, individual instructors
173
- selling courses. Core surface is the course catalog.
174
-
175
- - **Entity tag:** `both`
176
- - **Pages:**
177
-
178
- | Slug | Schema.orgType | Purpose |
179
- | -------------- | ------------------ | ------------------------------------------------ |
180
- | `home` | `HomePage` | who the courses are for and the headline outcome |
181
- | `courses` | `CoursesList` | catalog of available courses |
182
- | `about` | `AboutPage` | instructor or institution story |
183
- | `testimonials` | `TestimonialsList` | student outcomes and quotes |
184
- | `contact` | `ContactPage` | enrollment and support |
185
- | `faq` | `FAQPage` | format, prerequisites, certification |
186
- | `privacy` | `PrivacyPage` | privacy policy |
187
- | `terms` | `TermsPage` | terms of service |
188
-
189
- Individual courses use `Course`. A solo instructor anchors on `Person`;
190
- a school anchors on `Organization`.
191
-
192
- ---
193
-
194
- ## Real estate
195
-
196
- Brokerages, individual agents, property-management firms. The
197
- disambiguation matters here: a solo agent's site looks different from
198
- a brokerage's.
199
-
200
- - **Entity tag:** `both`
201
- - **Pages:**
202
-
203
- | Slug | Schema.orgType | Purpose |
204
- | -------------- | ------------------ | ------------------------------------------------------- |
205
- | `home` | `HomePage` | what kinds of properties and which markets |
206
- | `listings` | `ProductsList` | available properties (treat each property as a Product) |
207
- | `services` | `ServicesList` | buyer / seller / rental representation |
208
- | `about` | `AboutPage` | the agent's or brokerage's story and credentials |
209
- | `team` | `TeamList` | the agents at the brokerage (skip for solo agents) |
210
- | `testimonials` | `TestimonialsList` | client reviews |
211
- | `contact` | `ContactPage` | how to reach out about a property |
212
- | `privacy` | `PrivacyPage` | privacy policy |
213
- | `terms` | `TermsPage` | terms of service |
214
-
215
- Words like "brokerage", "team", "our agents" → `Organization`. "Solo
216
- agent", "I represent" → `Person`. Drop the `team` page for solo
217
- agents.
218
-
219
- ---
220
-
221
- ## Healthcare / Medical
222
-
223
- Clinics, solo practitioners, group practices, dental offices,
224
- therapists, specialty practices. Privacy and credibility are
225
- load-bearing here.
226
-
227
- - **Entity tag:** `both`
228
- - **Pages:**
229
-
230
- | Slug | Schema.orgType | Purpose |
231
- | ---------- | -------------- | ------------------------------------------------------ |
232
- | `home` | `HomePage` | what care is offered and for whom |
233
- | `services` | `ServicesList` | conditions treated and procedures offered |
234
- | `team` | `TeamList` | the providers (skip for solo practitioners) |
235
- | `about` | `AboutPage` | practice philosophy, credentials, affiliations |
236
- | `faq` | `FAQPage` | insurance, scheduling, what to expect |
237
- | `contact` | `ContactPage` | hours, address, intake form link |
238
- | `privacy` | `PrivacyPage` | privacy policy (HIPAA-relevant; flag this to the user) |
239
- | `terms` | `TermsPage` | terms of service |
240
-
241
- Solo practitioner → `Person`; clinic or group practice → `Organization`.
242
- Drop `team` for solo practitioners.
243
-
244
- When emitting the privacy line, mention HIPAA: "Healthcare sites need
245
- a HIPAA-aware privacy policy. The default `PrivacyPage` is a starting
246
- point, not a finished policy."
247
-
248
- ---
249
-
250
- ## Nonprofit / Org
251
-
252
- Nonprofits, advocacy groups, professional associations, foundations.
253
- Always organizational by nature; even a one-person foundation
254
- operates as an entity.
255
-
256
- - **Entity tag:** `organization`
257
- - **Pages:**
258
-
259
- | Slug | Schema.orgType | Purpose |
260
- | ---------- | -------------- | ------------------------------------------------------------- |
261
- | `home` | `HomePage` | mission and what the org does this year |
262
- | `programs` | `ServicesList` | programs the org runs |
263
- | `about` | `AboutPage` | history, mission, governance |
264
- | `team` | `TeamList` | staff and board |
265
- | `partners` | `PartnersList` | funders, partners, supporting organizations |
266
- | `events` | `EventsList` | upcoming events and campaigns |
267
- | `donate` | `Service` | donation entry point (treat the act of donating as a Service) |
268
- | `contact` | `ContactPage` | how to reach the org |
269
- | `privacy` | `PrivacyPage` | privacy policy |
270
- | `terms` | `TermsPage` | terms of service |
271
-
272
- ---
273
-
274
- ## Schema-builder coverage
275
-
276
- Every `Schema.orgType` referenced above is a member of the
277
- `SchemaOrgType` union exported by `@working-theory/schema` and has a builder
278
- function. The v1 catalog uses 21 of the 60 supported types:
279
-
280
- `HomePage`, `AboutPage`, `ContactPage`, `PrivacyPage`, `TermsPage`,
281
- `Organization`, `Person`, `ServicesList`, `Service`, `ProductsList`,
282
- `Product`, `FAQPage`, `TestimonialsList`, `TeamList`, `PartnersList`,
283
- `EventsList`, `CoursesList`, `Course`, `BlogList`, `BlogPosting`,
284
- `CaseStudiesList`.
285
-
286
- The remaining 39 types are available to `scaffold-page` and `add-schema`
287
- for per-page use but don't drive category recommendations.
@@ -1,150 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * ContactForm — client component that wires the contact form to
5
- * captureLeadAction via useFormState.
6
- *
7
- * Validation errors render inline next to each field.
8
- * Success shows a confirmation message.
9
- * Server errors show a generic fallback message.
10
- *
11
- * Honeypot + rate-limit enforcement lives in apps/api; no duplication here.
12
- *
13
- * `initialValues` (#4534, epic #4521's integration leg): optional prefill
14
- * for name/email/message, set via `defaultValue` (the fields stay
15
- * uncontrolled — unchanged for the no-prop call site). Lets
16
- * `ConversationalIntakeWrapper` carry over whatever the visitor already
17
- * typed into the conversation before Skip (or a failed auto-submit)
18
- * dropped them here, instead of asking them to retype it.
19
- */
20
-
21
- import { useTranslations } from "next-intl";
22
- import { useFormState, useFormStatus } from "react-dom";
23
-
24
- import { captureLeadAction } from "./contact.actions";
25
-
26
- export interface ContactFormInitialValues {
27
- name?: string;
28
- email?: string;
29
- message?: string;
30
- }
31
-
32
- interface ContactFormProps {
33
- initialValues?: ContactFormInitialValues;
34
- }
35
-
36
- function SubmitButton() {
37
- const t = useTranslations("contact");
38
- const { pending } = useFormStatus();
39
- return (
40
- <button type="submit" disabled={pending} data-testid="contact-submit">
41
- {pending ? t("sending") : t("sendMessage")}
42
- </button>
43
- );
44
- }
45
-
46
- export function ContactForm({ initialValues }: ContactFormProps = {}) {
47
- const t = useTranslations("contact");
48
- const [state, formAction] = useFormState(captureLeadAction, null);
49
-
50
- if (state?.kind === "success") {
51
- return (
52
- <p data-testid="contact-success">
53
- {t("successMessage")}
54
- </p>
55
- );
56
- }
57
-
58
- const fieldErrors = state?.kind === "error" ? (state.fieldErrors ?? {}) : {};
59
- const formError =
60
- state?.kind === "error" && !state.fieldErrors ? state.message : undefined;
61
-
62
- return (
63
- <form action={formAction} noValidate>
64
- {formError && (
65
- <p role="alert" data-testid="contact-form-error">
66
- {formError}
67
- </p>
68
- )}
69
-
70
- {/* Honeypot — hidden from users; bots fill it; API rejects non-empty */}
71
- <input
72
- type="text"
73
- name="website"
74
- tabIndex={-1}
75
- aria-hidden="true"
76
- style={{ display: "none" }}
77
- />
78
-
79
- <div>
80
- <label htmlFor="contact-name">{t("nameLabel")}</label>
81
- <input
82
- id="contact-name"
83
- name="name"
84
- type="text"
85
- autoComplete="name"
86
- required
87
- defaultValue={initialValues?.name}
88
- aria-describedby={fieldErrors.name ? "contact-name-error" : undefined}
89
- />
90
- {fieldErrors.name && (
91
- <span
92
- id="contact-name-error"
93
- role="alert"
94
- data-testid="contact-name-error"
95
- >
96
- {fieldErrors.name}
97
- </span>
98
- )}
99
- </div>
100
-
101
- <div>
102
- <label htmlFor="contact-email">{t("emailLabel")}</label>
103
- <input
104
- id="contact-email"
105
- name="email"
106
- type="email"
107
- autoComplete="email"
108
- required
109
- defaultValue={initialValues?.email}
110
- aria-describedby={
111
- fieldErrors.email ? "contact-email-error" : undefined
112
- }
113
- />
114
- {fieldErrors.email && (
115
- <span
116
- id="contact-email-error"
117
- role="alert"
118
- data-testid="contact-email-error"
119
- >
120
- {fieldErrors.email}
121
- </span>
122
- )}
123
- </div>
124
-
125
- <div>
126
- <label htmlFor="contact-message">{t("messageLabel")}</label>
127
- <textarea
128
- id="contact-message"
129
- name="message"
130
- rows={5}
131
- defaultValue={initialValues?.message}
132
- aria-describedby={
133
- fieldErrors.message ? "contact-message-error" : undefined
134
- }
135
- />
136
- {fieldErrors.message && (
137
- <span
138
- id="contact-message-error"
139
- role="alert"
140
- data-testid="contact-message-error"
141
- >
142
- {fieldErrors.message}
143
- </span>
144
- )}
145
- </div>
146
-
147
- <SubmitButton />
148
- </form>
149
- );
150
- }
@@ -1,44 +0,0 @@
1
- // ReturnsPolicyPage route (#5947). Reads the ReturnsPolicyPage MDX frontmatter, renders sections via
2
- // SectionRenderer, and emits a JSON-LD <script>.
3
- import type {
4
- getMdxSource as defaultGetMdxSource,
5
- getPageSections as defaultGetPageSections} from "@working-theory/page-renderer";
6
- import {
7
- renderPage,
8
- renderPageMetadata
9
- } from "@working-theory/page-renderer";
10
- import type { Metadata } from "next";
11
- import type { ReactElement } from "react";
12
-
13
- interface Props {
14
- params: Promise<{ locale: string }>;
15
- getMdxSource?: typeof defaultGetMdxSource;
16
- getPageSections?: typeof defaultGetPageSections;
17
- }
18
-
19
- export async function generateMetadata({
20
- params,
21
- }: Pick<Props, "params">): Promise<Metadata> {
22
- const { locale } = await params;
23
- return renderPageMetadata({ type: "ReturnsPolicyPage", slug: "returns", locale });
24
- }
25
-
26
- export default async function Page({
27
- params,
28
- getMdxSource,
29
- getPageSections,
30
- }: Props): Promise<ReactElement> {
31
- const { locale } = await params;
32
- return renderPage({
33
- type: "ReturnsPolicyPage",
34
- slug: "returns",
35
- locale,
36
- // Without a namespace `renderPage` 404s on a missing seed — and a scaffold
37
- // IS a missing-seed environment, since `build-templates.mjs` snapshots
38
- // `apps/` but deliberately not `content/`. The namespace makes this route
39
- // render the #4154 authoring empty state at 200, exactly as /terms does.
40
- translationsNamespace: "returns",
41
- ...(getMdxSource !== undefined && { getMdxSource }),
42
- ...(getPageSections !== undefined && { getPageSections }),
43
- });
44
- }
@@ -1,44 +0,0 @@
1
- // ShippingPolicyPage route (#5947). Reads the ShippingPolicyPage MDX frontmatter, renders sections via
2
- // SectionRenderer, and emits a JSON-LD <script>.
3
- import type {
4
- getMdxSource as defaultGetMdxSource,
5
- getPageSections as defaultGetPageSections} from "@working-theory/page-renderer";
6
- import {
7
- renderPage,
8
- renderPageMetadata
9
- } from "@working-theory/page-renderer";
10
- import type { Metadata } from "next";
11
- import type { ReactElement } from "react";
12
-
13
- interface Props {
14
- params: Promise<{ locale: string }>;
15
- getMdxSource?: typeof defaultGetMdxSource;
16
- getPageSections?: typeof defaultGetPageSections;
17
- }
18
-
19
- export async function generateMetadata({
20
- params,
21
- }: Pick<Props, "params">): Promise<Metadata> {
22
- const { locale } = await params;
23
- return renderPageMetadata({ type: "ShippingPolicyPage", slug: "shipping", locale });
24
- }
25
-
26
- export default async function Page({
27
- params,
28
- getMdxSource,
29
- getPageSections,
30
- }: Props): Promise<ReactElement> {
31
- const { locale } = await params;
32
- return renderPage({
33
- type: "ShippingPolicyPage",
34
- slug: "shipping",
35
- locale,
36
- // Without a namespace `renderPage` 404s on a missing seed — and a scaffold
37
- // IS a missing-seed environment, since `build-templates.mjs` snapshots
38
- // `apps/` but deliberately not `content/`. The namespace makes this route
39
- // render the #4154 authoring empty state at 200, exactly as /terms does.
40
- translationsNamespace: "shipping",
41
- ...(getMdxSource !== undefined && { getMdxSource }),
42
- ...(getPageSections !== undefined && { getPageSections }),
43
- });
44
- }
@@ -1,108 +0,0 @@
1
- ---
2
- type: "CancellationPolicyPage"
3
- slug: "cancellation"
4
- title: "Cancellation Policy"
5
- description: "How to cancel or reschedule a booking on this site, the notice required, and what a late cancellation or no-show costs."
6
- updatedAt: "2026-09-17"
7
- sections:
8
- [
9
- {
10
- "id": "cancellation-document",
11
- "type": "document-chassis",
12
- "data":
13
- {
14
- "headline": "Cancellation Policy",
15
- "backHref": "/",
16
- "backLabel": "Back home",
17
- "navGroupLabel": "Contents",
18
- "stats":
19
- [
20
- { "label": "Last updated", "sublabel": "17 September 2026" },
21
- { "label": "Applies to", "sublabel": "Bookings made on this site" },
22
- ],
23
- "sections":
24
- [
25
- {
26
- "id": "intro",
27
- "heading": "Cancellation Policy",
28
- "blocks":
29
- [
30
- {
31
- "kind": "paragraph",
32
- "text": "This page explains how cancellations and reschedules work for bookings made on this site. Replace the starter copy below with the policy you actually operate — the headings are the ones a customer and an agent both look for, so keep them and fill in your own terms.",
33
- },
34
- ],
35
- },
36
- {
37
- "id": "notice",
38
- "heading": "How much notice is required",
39
- "blocks":
40
- [
41
- {
42
- "kind": "paragraph",
43
- "text": "State the notice period in hours before the appointment, and say how it is measured. A customer reading at midnight should be able to work out, without arithmetic you have not shown them, whether they are still inside it.",
44
- },
45
- ],
46
- },
47
- {
48
- "id": "how-to-cancel",
49
- "heading": "How to cancel or reschedule",
50
- "blocks":
51
- [
52
- {
53
- "kind": "paragraph",
54
- "text": "Give one route to cancel and one to reschedule, and say whether a reschedule inside the notice period counts as a cancellation. If a booking confirmation carries a self-service link, name it here.",
55
- },
56
- ],
57
- },
58
- {
59
- "id": "fees",
60
- "heading": "Late cancellations and no-shows",
61
- "blocks":
62
- [
63
- {
64
- "kind": "paragraph",
65
- "text": "Say what a late cancellation costs and what a no-show costs, as a figure or a share of the booking, and when each is charged. If you hold a deposit, say what happens to it in each case.",
66
- },
67
- ],
68
- },
69
- {
70
- "id": "our-cancellations",
71
- "heading": "If we cancel",
72
- "blocks":
73
- [
74
- {
75
- "kind": "paragraph",
76
- "text": "Set out what a customer gets if you cancel or move an appointment — a full refund, a rebooking, or both — and how quickly you tell them. A policy that only binds one side reads as one.",
77
- },
78
- ],
79
- },
80
- {
81
- "id": "exceptions",
82
- "heading": "Exceptions",
83
- "blocks":
84
- [
85
- {
86
- "kind": "paragraph",
87
- "text": "Name the circumstances in which you waive a fee — illness, bereavement, severe weather — and say what you need from the customer to apply the waiver. Vague discretion is worse for you than a short written list.",
88
- },
89
- ],
90
- },
91
- {
92
- "id": "contact",
93
- "heading": "Questions about a booking",
94
- "blocks":
95
- [
96
- {
97
- "kind": "paragraph",
98
- "text": "Point to the one place a customer should write, and say roughly how quickly you answer.",
99
- },
100
- ],
101
- },
102
- ],
103
- },
104
- },
105
- ]
106
- ---
107
-
108
- {/* Rendered from frontmatter `sections[]`; the MDX body is not read by the section-catalog renderer. schema.org has no cancellation-policy type, so this page emits a plain WebPage (#5947, D2) — a real policy field reaches the JSON-LD through the `schema:` escape hatch, never a coined @type. */}