create-ailk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +39 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +80 -0
- package/dist/copy.d.ts +8 -0
- package/dist/copy.js +109 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/lib/pro-callout.d.ts +12 -0
- package/dist/lib/pro-callout.js +20 -0
- package/dist/parse-args.d.ts +13 -0
- package/dist/parse-args.js +81 -0
- package/dist/programmatic.d.ts +49 -0
- package/dist/programmatic.js +89 -0
- package/dist/substitute.d.ts +31 -0
- package/dist/substitute.js +45 -0
- package/dist/validate.d.ts +8 -0
- package/dist/validate.js +70 -0
- package/package.json +47 -0
- package/templates/.claude/.gitkeep +0 -0
- package/templates/.claude/agents/web.md +80 -0
- package/templates/.claude/rules/architecture.md +62 -0
- package/templates/.claude/rules/preserve-existing-style.md +51 -0
- package/templates/.claude/skills/README.md +43 -0
- package/templates/.claude/skills/add-schema/SKILL.md +270 -0
- package/templates/.claude/skills/add-schema/references/conflict-handling.md +200 -0
- package/templates/.claude/skills/add-schema/references/file-finding.md +123 -0
- package/templates/.claude/skills/add-schema/references/schema-types.md +131 -0
- package/templates/.claude/skills/audit-site/SKILL.md +213 -0
- package/templates/.claude/skills/audit-site/references/common-errors.md +113 -0
- package/templates/.claude/skills/audit-site/references/findings-glossary.md +138 -0
- package/templates/.claude/skills/audit-site/references/severity-levels.md +114 -0
- package/templates/.claude/skills/provision-config/SKILL.md +243 -0
- package/templates/.claude/skills/provision-config/references/env-vars-template.md +184 -0
- package/templates/.claude/skills/provision-config/references/runbook-template.md +248 -0
- package/templates/.claude/skills/provision-config/references/vercel-json-template.md +98 -0
- package/templates/.claude/skills/scaffold-auth/SKILL.md +261 -0
- package/templates/.claude/skills/scaffold-auth/references/env-vars.md +91 -0
- package/templates/.claude/skills/scaffold-auth/references/oauth-app-setup.md +171 -0
- package/templates/.claude/skills/scaffold-commerce/SKILL.md +310 -0
- package/templates/.claude/skills/scaffold-commerce/references/lookup-keys-template.md +71 -0
- package/templates/.claude/skills/scaffold-commerce/references/marketplace-brand-pages.md +83 -0
- package/templates/.claude/skills/scaffold-commerce/templates/marketplace-cta-route.tsx.tmpl +72 -0
- package/templates/.claude/skills/scaffold-page/SKILL.md +243 -0
- package/templates/.claude/skills/scaffold-page/references/page-types.md +169 -0
- package/templates/.claude/skills/scaffold-page/templates/content.mdx.tmpl +28 -0
- package/templates/.claude/skills/scaffold-page/templates/route.tsx.tmpl +28 -0
- package/templates/.claude/skills/suggest-site-pages/SKILL.md +242 -0
- package/templates/.claude/skills/suggest-site-pages/references/categories.md +287 -0
- package/templates/.env.example +205 -0
- package/templates/.gitkeep +2 -0
- package/templates/CLAUDE.md +142 -0
- package/templates/CONVENTIONS.md +222 -0
- package/templates/README.md +110 -0
- package/templates/apps/api/.env.example +40 -0
- package/templates/apps/api/CLAUDE.md +63 -0
- package/templates/apps/api/api/index.ts +144 -0
- package/templates/apps/api/jest.config.cjs +74 -0
- package/templates/apps/api/package.json +54 -0
- package/templates/apps/api/src/__tests__/factories/content-fixture.ts +138 -0
- package/templates/apps/api/src/__tests__/factories/index.ts +70 -0
- package/templates/apps/api/src/__tests__/factories/lead-fixture.ts +82 -0
- package/templates/apps/api/src/__tests__/index.test.ts +118 -0
- package/templates/apps/api/src/__tests__/server.test.ts +207 -0
- package/templates/apps/api/src/__tests__/services/enrichment-shim.test.ts +126 -0
- package/templates/apps/api/src/__tests__/setup.ts +24 -0
- package/templates/apps/api/src/cli.ts +30 -0
- package/templates/apps/api/src/config/__tests__/index.test.ts +97 -0
- package/templates/apps/api/src/config/index.ts +56 -0
- package/templates/apps/api/src/index.ts +32 -0
- package/templates/apps/api/src/lib/__mocks__/prisma-client.js +15 -0
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +45 -0
- package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +178 -0
- package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +100 -0
- package/templates/apps/api/src/lib/__tests__/errors.test.ts +94 -0
- package/templates/apps/api/src/lib/__tests__/file-fallback.test.ts +144 -0
- package/templates/apps/api/src/lib/__tests__/fixtures/HomePage/home.mdx +8 -0
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +227 -0
- package/templates/apps/api/src/lib/__tests__/outbound-http.test.ts +125 -0
- package/templates/apps/api/src/lib/__tests__/prisma.test.ts +165 -0
- package/templates/apps/api/src/lib/__tests__/require-paid-tier.test.ts +129 -0
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +74 -0
- package/templates/apps/api/src/lib/content-adapter.ts +86 -0
- package/templates/apps/api/src/lib/error-serializer.ts +77 -0
- package/templates/apps/api/src/lib/errors.ts +95 -0
- package/templates/apps/api/src/lib/file-fallback.ts +87 -0
- package/templates/apps/api/src/lib/lead-capture-store.ts +110 -0
- package/templates/apps/api/src/lib/locales.ts +201 -0
- package/templates/apps/api/src/lib/outbound-http.ts +122 -0
- package/templates/apps/api/src/lib/prisma.ts +21 -0
- package/templates/apps/api/src/lib/require-paid-tier.ts +53 -0
- package/templates/apps/api/src/lib/stripe.ts +30 -0
- package/templates/apps/api/src/lib/webhook-idempotency.ts +92 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/bearer-token-format.test.ts +111 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/cookie-or-bearer-precedence.test.ts +172 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-bearer-skip.test.ts +119 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/csrf-cookie-path.test.ts +138 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-fixation.test.ts +149 -0
- package/templates/apps/api/src/middleware/__tests__/adversarial/session-timeout.test.ts +139 -0
- package/templates/apps/api/src/middleware/__tests__/auth.bearer-path.test.ts +175 -0
- package/templates/apps/api/src/middleware/__tests__/auth.both-present-precedence.test.ts +76 -0
- package/templates/apps/api/src/middleware/__tests__/auth.cookie-path.test.ts +153 -0
- package/templates/apps/api/src/middleware/__tests__/auth.neither-present.test.ts +72 -0
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +292 -0
- package/templates/apps/api/src/middleware/auth.ts +246 -0
- package/templates/apps/api/src/middleware/rate-limit.ts +132 -0
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +129 -0
- package/templates/apps/api/src/openapi/index.ts +12 -0
- package/templates/apps/api/src/openapi/spec.ts +408 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-tokens.functional.test.ts +193 -0
- package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +201 -0
- package/templates/apps/api/src/routes/auth/__tests__/tokens.test.ts +294 -0
- package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +486 -0
- package/templates/apps/api/src/routes/auth/tokens.ts +199 -0
- package/templates/apps/api/src/routes/auth/user.ts +244 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +588 -0
- package/templates/apps/api/src/routes/checkout/index.ts +13 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +185 -0
- package/templates/apps/api/src/routes/content/__tests__/create.test.ts +239 -0
- package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +201 -0
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +141 -0
- package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +122 -0
- package/templates/apps/api/src/routes/content/__tests__/list-types.test.ts +44 -0
- package/templates/apps/api/src/routes/content/__tests__/locale.test.ts +118 -0
- package/templates/apps/api/src/routes/content/__tests__/rate-limit.test.ts +51 -0
- package/templates/apps/api/src/routes/content/__tests__/update.test.ts +252 -0
- package/templates/apps/api/src/routes/content/create.ts +114 -0
- package/templates/apps/api/src/routes/content/delete.ts +81 -0
- package/templates/apps/api/src/routes/content/get-page.ts +98 -0
- package/templates/apps/api/src/routes/content/index.ts +32 -0
- package/templates/apps/api/src/routes/content/list-pages.ts +83 -0
- package/templates/apps/api/src/routes/content/list-types.ts +19 -0
- package/templates/apps/api/src/routes/content/rate-limit.ts +13 -0
- package/templates/apps/api/src/routes/content/slug.ts +9 -0
- package/templates/apps/api/src/routes/content/update.ts +111 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +415 -0
- package/templates/apps/api/src/routes/leads/__tests__/track.test.ts +165 -0
- package/templates/apps/api/src/routes/leads/index.ts +130 -0
- package/templates/apps/api/src/routes/test/auth/__tests__/session.test.ts +296 -0
- package/templates/apps/api/src/routes/test/auth/session.ts +141 -0
- package/templates/apps/api/src/routes/webhooks/README.md +57 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +247 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +198 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +633 -0
- package/templates/apps/api/src/routes/webhooks/index.ts +41 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +253 -0
- package/templates/apps/api/src/server.ts +157 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +395 -0
- package/templates/apps/api/src/services/enrichment-shim.ts +53 -0
- package/templates/apps/api/src/services/lead-routing.ts +338 -0
- package/templates/apps/api/tsconfig.json +34 -0
- package/templates/apps/api/vercel.json +17 -0
- package/templates/apps/mcp/.env.example +52 -0
- package/templates/apps/mcp/CLAUDE.md +84 -0
- package/templates/apps/mcp/__tests__/abuse/daily-cap.test.ts +52 -0
- package/templates/apps/mcp/__tests__/abuse/email-validator.test.ts +46 -0
- package/templates/apps/mcp/__tests__/abuse/honeypot.test.ts +36 -0
- package/templates/apps/mcp/__tests__/abuse/user-agent-deny.test.ts +54 -0
- package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +110 -0
- package/templates/apps/mcp/__tests__/audit-single-page.test.ts +213 -0
- package/templates/apps/mcp/__tests__/audit.test.ts +217 -0
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +52 -0
- package/templates/apps/mcp/__tests__/create_page.test.ts +201 -0
- package/templates/apps/mcp/__tests__/delete_page.test.ts +176 -0
- package/templates/apps/mcp/__tests__/get_business_hours.test.ts +82 -0
- package/templates/apps/mcp/__tests__/get_faq.test.ts +80 -0
- package/templates/apps/mcp/__tests__/get_locations.test.ts +65 -0
- package/templates/apps/mcp/__tests__/get_offerings.test.ts +90 -0
- package/templates/apps/mcp/__tests__/get_pricing.test.ts +80 -0
- package/templates/apps/mcp/__tests__/get_site_info.test.ts +81 -0
- package/templates/apps/mcp/__tests__/http-transport.test.ts +323 -0
- package/templates/apps/mcp/__tests__/lib/errors.test.ts +75 -0
- package/templates/apps/mcp/__tests__/lib/require-paid-tier.test.ts +75 -0
- package/templates/apps/mcp/__tests__/list_pages.test.ts +112 -0
- package/templates/apps/mcp/__tests__/locale.test.ts +135 -0
- package/templates/apps/mcp/__tests__/parity.test.ts +205 -0
- package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +34 -0
- package/templates/apps/mcp/__tests__/read_content.test.ts +153 -0
- package/templates/apps/mcp/__tests__/request_callback.test.ts +163 -0
- package/templates/apps/mcp/__tests__/search_content.test.ts +153 -0
- package/templates/apps/mcp/__tests__/server.test.ts +115 -0
- package/templates/apps/mcp/__tests__/submit_lead.test.ts +165 -0
- package/templates/apps/mcp/__tests__/subscribe_newsletter.test.ts +161 -0
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +227 -0
- package/templates/apps/mcp/__tests__/tools/scaffold.test.ts +237 -0
- package/templates/apps/mcp/__tests__/update_page.test.ts +195 -0
- package/templates/apps/mcp/jest.config.cjs +82 -0
- package/templates/apps/mcp/package.json +37 -0
- package/templates/apps/mcp/src/abuse/daily-cap.ts +47 -0
- package/templates/apps/mcp/src/abuse/email-validator.ts +25 -0
- package/templates/apps/mcp/src/abuse/honeypot.ts +21 -0
- package/templates/apps/mcp/src/abuse/index.ts +111 -0
- package/templates/apps/mcp/src/abuse/user-agent-deny.ts +58 -0
- package/templates/apps/mcp/src/http-transport.ts +303 -0
- package/templates/apps/mcp/src/index.ts +67 -0
- package/templates/apps/mcp/src/lib/audit-single-page.ts +194 -0
- package/templates/apps/mcp/src/lib/errors.ts +61 -0
- package/templates/apps/mcp/src/lib/locales.ts +171 -0
- package/templates/apps/mcp/src/lib/require-paid-tier.ts +44 -0
- package/templates/apps/mcp/src/lib/resolve-locale.ts +30 -0
- package/templates/apps/mcp/src/server.ts +139 -0
- package/templates/apps/mcp/src/tools/audit.ts +103 -0
- package/templates/apps/mcp/src/tools/capture_lead.ts +52 -0
- package/templates/apps/mcp/src/tools/create_page.ts +95 -0
- package/templates/apps/mcp/src/tools/delete_page.ts +73 -0
- package/templates/apps/mcp/src/tools/get_business_hours.ts +66 -0
- package/templates/apps/mcp/src/tools/get_faq.ts +69 -0
- package/templates/apps/mcp/src/tools/get_locations.ts +85 -0
- package/templates/apps/mcp/src/tools/get_offerings.ts +66 -0
- package/templates/apps/mcp/src/tools/get_pricing.ts +74 -0
- package/templates/apps/mcp/src/tools/get_site_info.ts +84 -0
- package/templates/apps/mcp/src/tools/index.ts +125 -0
- package/templates/apps/mcp/src/tools/list_pages.ts +72 -0
- package/templates/apps/mcp/src/tools/purchase.ts +89 -0
- package/templates/apps/mcp/src/tools/read_content.ts +61 -0
- package/templates/apps/mcp/src/tools/request_callback.ts +51 -0
- package/templates/apps/mcp/src/tools/scaffold.ts +119 -0
- package/templates/apps/mcp/src/tools/search_content.ts +59 -0
- package/templates/apps/mcp/src/tools/subscribe_newsletter.ts +47 -0
- package/templates/apps/mcp/src/tools/update_page.ts +91 -0
- package/templates/apps/mcp/tsconfig.json +19 -0
- package/templates/apps/web/.env.example +47 -0
- package/templates/apps/web/CLAUDE.md +81 -0
- package/templates/apps/web/__tests__/auth/adversarial/cookie-attributes.test.ts +94 -0
- package/templates/apps/web/__tests__/auth/adversarial/oauth-state-parameter.test.ts +75 -0
- package/templates/apps/web/__tests__/auth/adversarial/redirect-uri-allowlist.test.ts +82 -0
- package/templates/apps/web/__tests__/auth/env-helpers.test.ts +168 -0
- package/templates/apps/web/__tests__/authority-list-routes.test.tsx +208 -0
- package/templates/apps/web/__tests__/better-stack.test.ts +66 -0
- package/templates/apps/web/__tests__/blog-dir-resolution.test.ts +87 -0
- package/templates/apps/web/__tests__/blog-source-populated.test.ts +130 -0
- package/templates/apps/web/__tests__/data-testid-coverage.test.tsx +60 -0
- package/templates/apps/web/__tests__/google-analytics.test.tsx +104 -0
- package/templates/apps/web/__tests__/i18n/middleware.test.ts +119 -0
- package/templates/apps/web/__tests__/i18n/routing.test.ts +114 -0
- package/templates/apps/web/__tests__/i18n/translations.test.ts +191 -0
- package/templates/apps/web/__tests__/json-ld.test.ts +98 -0
- package/templates/apps/web/__tests__/knowledge-events-routes.test.tsx +580 -0
- package/templates/apps/web/__tests__/layout-stealth.test.ts +39 -0
- package/templates/apps/web/__tests__/lighthouse-fixtures/improvement-image-shrink.tsx +103 -0
- package/templates/apps/web/__tests__/lighthouse-fixtures/override-fixture.md +114 -0
- package/templates/apps/web/__tests__/lighthouse-fixtures/regression-bloat.tsx +94 -0
- package/templates/apps/web/__tests__/page.test.tsx +230 -0
- package/templates/apps/web/__tests__/products-services-phase1.test.tsx +321 -0
- package/templates/apps/web/__tests__/projects-routes.test.tsx +392 -0
- package/templates/apps/web/__tests__/resources-downloads-integrations-phase2.test.tsx +475 -0
- package/templates/apps/web/__tests__/routes/ai-plugin-json.test.ts +53 -0
- package/templates/apps/web/__tests__/routes/blog-route.test.tsx +191 -0
- package/templates/apps/web/__tests__/routes/llms-txt.test.ts +123 -0
- package/templates/apps/web/__tests__/routes/robots-txt.test.ts +52 -0
- package/templates/apps/web/__tests__/routes/sitemap-xml.test.ts +78 -0
- package/templates/apps/web/__tests__/routes/well-known-mcp.test.ts +203 -0
- package/templates/apps/web/__tests__/section-routes.test.tsx +693 -0
- package/templates/apps/web/__tests__/security-headers.test.ts +201 -0
- package/templates/apps/web/__tests__/sentry-config.test.ts +116 -0
- package/templates/apps/web/__tests__/setup.ts +82 -0
- package/templates/apps/web/__tests__/sitemap-locales.test.ts +415 -0
- package/templates/apps/web/__tests__/standalone-informational-routes.test.tsx +844 -0
- package/templates/apps/web/app/.well-known/ai-plugin.json/route.ts +81 -0
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +110 -0
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +58 -0
- package/templates/apps/web/app/[locale]/__tests__/layout.test.tsx +120 -0
- package/templates/apps/web/app/[locale]/__tests__/page-renderer-migration.test.tsx +202 -0
- package/templates/apps/web/app/[locale]/about/page.tsx +31 -0
- package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +173 -0
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +45 -0
- package/templates/apps/web/app/[locale]/careers/__tests__/page-renderer-migration.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/careers/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/case-studies/__tests__/page-renderer-migration.test.tsx +113 -0
- package/templates/apps/web/app/[locale]/case-studies/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/clients/__tests__/page-renderer-migration.test.tsx +63 -0
- package/templates/apps/web/app/[locale]/clients/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +130 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +152 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +92 -0
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +79 -0
- package/templates/apps/web/app/[locale]/contact/error.tsx +24 -0
- package/templates/apps/web/app/[locale]/contact/page.tsx +38 -0
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/courses/__tests__/page-renderer-migration.test.tsx +119 -0
- package/templates/apps/web/app/[locale]/courses/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/dev/purchase/__tests__/actions.test.ts +160 -0
- package/templates/apps/web/app/[locale]/dev/purchase/error.tsx +25 -0
- package/templates/apps/web/app/[locale]/dev/purchase/page.tsx +117 -0
- package/templates/apps/web/app/[locale]/dev/purchase/purchase.actions.ts +58 -0
- package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +118 -0
- package/templates/apps/web/app/[locale]/downloads/__tests__/page-renderer-migration.test.tsx +72 -0
- package/templates/apps/web/app/[locale]/downloads/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +47 -0
- package/templates/apps/web/app/[locale]/events/__tests__/page-renderer-migration.test.tsx +130 -0
- package/templates/apps/web/app/[locale]/events/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/faq/page.tsx +36 -0
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/how-to/__tests__/page-renderer-migration.test.tsx +78 -0
- package/templates/apps/web/app/[locale]/how-to/page.tsx +40 -0
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +43 -0
- package/templates/apps/web/app/[locale]/integrations/__tests__/page-renderer-migration.test.tsx +129 -0
- package/templates/apps/web/app/[locale]/integrations/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/launch-service/page.tsx +31 -0
- package/templates/apps/web/app/[locale]/layout.tsx +241 -0
- package/templates/apps/web/app/[locale]/page.tsx +41 -0
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/partners/__tests__/page-renderer-migration.test.tsx +113 -0
- package/templates/apps/web/app/[locale]/partners/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +43 -0
- package/templates/apps/web/app/[locale]/products/__tests__/page-renderer-migration.test.tsx +129 -0
- package/templates/apps/web/app/[locale]/products/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +39 -0
- package/templates/apps/web/app/[locale]/projects/__tests__/page-renderer-migration.test.tsx +138 -0
- package/templates/apps/web/app/[locale]/projects/page.tsx +30 -0
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +51 -0
- package/templates/apps/web/app/[locale]/resources/__tests__/page-renderer-migration.test.tsx +117 -0
- package/templates/apps/web/app/[locale]/resources/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +43 -0
- package/templates/apps/web/app/[locale]/services/__tests__/page-renderer-migration.test.tsx +129 -0
- package/templates/apps/web/app/[locale]/services/page.tsx +25 -0
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/software/__tests__/page-renderer-migration.test.tsx +81 -0
- package/templates/apps/web/app/[locale]/software/page.tsx +39 -0
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/tech-articles/__tests__/page-renderer-migration.test.tsx +82 -0
- package/templates/apps/web/app/[locale]/tech-articles/page.tsx +39 -0
- package/templates/apps/web/app/[locale]/testimonials/__tests__/page-renderer-migration.test.tsx +63 -0
- package/templates/apps/web/app/[locale]/testimonials/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +63 -0
- package/templates/apps/web/app/[locale]/use-cases/page.tsx +27 -0
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +34 -0
- package/templates/apps/web/app/[locale]/whitepapers/__tests__/page-renderer-migration.test.tsx +82 -0
- package/templates/apps/web/app/[locale]/whitepapers/page.tsx +39 -0
- package/templates/apps/web/app/__tests__/error-boundaries.test.tsx +152 -0
- package/templates/apps/web/app/api/auth/[...all]/route.ts +16 -0
- package/templates/apps/web/app/error-fallback.tsx +75 -0
- package/templates/apps/web/app/error.tsx +23 -0
- package/templates/apps/web/app/layout.tsx +18 -0
- package/templates/apps/web/app/llms.txt/route.ts +101 -0
- package/templates/apps/web/app/not-found.tsx +48 -0
- package/templates/apps/web/app/og/__tests__/route.test.ts +164 -0
- package/templates/apps/web/app/og/route.tsx +135 -0
- package/templates/apps/web/app/robots.txt/route.ts +36 -0
- package/templates/apps/web/app/sitemap.xml/route.ts +146 -0
- package/templates/apps/web/auth.ts +141 -0
- package/templates/apps/web/components/ThemeToggle.tsx +60 -0
- package/templates/apps/web/components/google-analytics.tsx +34 -0
- package/templates/apps/web/content/en/blog/index.mdx +15 -0
- package/templates/apps/web/content/en/blog/launching-ailk.mdx +20 -0
- package/templates/apps/web/content/en/docs/getting-started.mdx +30 -0
- package/templates/apps/web/i18n/request.ts +36 -0
- package/templates/apps/web/jest.config.cjs +100 -0
- package/templates/apps/web/lib/__mocks__/next-mdx-remote-rsc.js +12 -0
- package/templates/apps/web/lib/__mocks__/source-server.js +31 -0
- package/templates/apps/web/lib/__tests__/og.test.ts +65 -0
- package/templates/apps/web/lib/auth-env.ts +66 -0
- package/templates/apps/web/lib/blog-list-data.ts +95 -0
- package/templates/apps/web/lib/blog-post-data.ts +79 -0
- package/templates/apps/web/lib/nav-config.ts +13 -0
- package/templates/apps/web/lib/observability/better-stack.ts +27 -0
- package/templates/apps/web/lib/og.ts +23 -0
- package/templates/apps/web/lib/prisma-for-auth.ts +34 -0
- package/templates/apps/web/lib/source.ts +34 -0
- package/templates/apps/web/messages/en.json +131 -0
- package/templates/apps/web/middleware.ts +80 -0
- package/templates/apps/web/next.config.mjs +167 -0
- package/templates/apps/web/package.json +62 -0
- package/templates/apps/web/public/.well-known/security.txt +17 -0
- package/templates/apps/web/public/android-chrome-192x192.png +0 -0
- package/templates/apps/web/public/android-chrome-512x512.png +0 -0
- package/templates/apps/web/public/apple-touch-icon.png +0 -0
- package/templates/apps/web/public/favicon-16x16.png +0 -0
- package/templates/apps/web/public/favicon-32x32.png +0 -0
- package/templates/apps/web/public/favicon.ico +0 -0
- package/templates/apps/web/public/favicon.svg +4 -0
- package/templates/apps/web/public/logo-dark.svg +21 -0
- package/templates/apps/web/public/logo-light.svg +21 -0
- package/templates/apps/web/public/logomark-dark.svg +4 -0
- package/templates/apps/web/public/logomark-light.svg +4 -0
- package/templates/apps/web/public/og-default.png +0 -0
- package/templates/apps/web/public/site.webmanifest +19 -0
- package/templates/apps/web/scripts/assert-content-bundled.ts +55 -0
- package/templates/apps/web/security-headers.config.ts +132 -0
- package/templates/apps/web/sentry.client.config.ts +27 -0
- package/templates/apps/web/sentry.edge.config.ts +15 -0
- package/templates/apps/web/sentry.server.config.ts +20 -0
- package/templates/apps/web/source.config.ts +78 -0
- package/templates/apps/web/src/components/SiteNav.tsx +21 -0
- package/templates/apps/web/src/lib/routes.ts +37 -0
- package/templates/apps/web/tsconfig.json +35 -0
- package/templates/apps/web/types/messages.d.ts +19 -0
- package/templates/content/.gitkeep +0 -0
- package/templates/content/CLAUDE.md +85 -0
- package/templates/content/_site.mdx +38 -0
- package/templates/content/ar/HomePage/home.mdx +123 -0
- package/templates/content/ar/_site.mdx +35 -0
- package/templates/content/de/_site.mdx +29 -0
- package/templates/content/en/.gitkeep +0 -0
- package/templates/content/en/AboutPage/about.mdx +19 -0
- package/templates/content/en/AboutPage/about.schema.json +82 -0
- package/templates/content/en/BookCall/book-call.mdx +19 -0
- package/templates/content/en/BookCall/book-call.schema.json +121 -0
- package/templates/content/en/BreadcrumbList/site-breadcrumbs.mdx +20 -0
- package/templates/content/en/CareersList/careers.mdx +24 -0
- package/templates/content/en/CaseStudiesList/case-studies.mdx +22 -0
- package/templates/content/en/CaseStudiesList/showcase.mdx +8 -0
- package/templates/content/en/CaseStudy/ailk-aeo-rollout.mdx +32 -0
- package/templates/content/en/CaseStudy/schema-builder-migration.mdx +41 -0
- package/templates/content/en/ClientsList/clients.mdx +38 -0
- package/templates/content/en/ContactPage/contact.mdx +19 -0
- package/templates/content/en/ContactPage/contact.schema.json +100 -0
- package/templates/content/en/ContactPoint/primary.mdx +14 -0
- package/templates/content/en/Course/aeo-fundamentals.mdx +37 -0
- package/templates/content/en/Course/schema-builder-workshop.mdx +62 -0
- package/templates/content/en/CoursesList/courses.mdx +22 -0
- package/templates/content/en/DownloadsList/downloads.mdx +22 -0
- package/templates/content/en/Event/aeo-office-hours-may-2026.mdx +39 -0
- package/templates/content/en/Event/ailk-launch-day-2026.mdx +35 -0
- package/templates/content/en/EventsList/events.mdx +26 -0
- package/templates/content/en/FAQPage/faq.mdx +420 -0
- package/templates/content/en/FAQPage/faq.schema.json +231 -0
- package/templates/content/en/GlossaryList/glossary.mdx +19 -0
- package/templates/content/en/GlossaryList/glossary.schema.json +300 -0
- package/templates/content/en/HomePage/home.mdx +312 -0
- package/templates/content/en/HomePage/home.schema.json +88 -0
- package/templates/content/en/HomePage/launch-service.mdx +475 -0
- package/templates/content/en/HomePage/launch-service.schema.json +138 -0
- package/templates/content/en/HowTo/add-mdx-content.mdx +38 -0
- package/templates/content/en/HowTo/configure-aeo-scoring.mdx +35 -0
- package/templates/content/en/HowTo/set-up-json-ld.mdx +36 -0
- package/templates/content/en/Integration/github-actions.mdx +31 -0
- package/templates/content/en/Integration/openai-api.mdx +26 -0
- package/templates/content/en/Integration/vercel.mdx +32 -0
- package/templates/content/en/IntegrationsList/integrations.mdx +22 -0
- package/templates/content/en/JobPosting/content-strategist.mdx +46 -0
- package/templates/content/en/JobPosting/developer-advocate.mdx +47 -0
- package/templates/content/en/JobPosting/senior-fullstack-engineer.mdx +57 -0
- package/templates/content/en/LandingPage/aeo-audit.mdx +19 -0
- package/templates/content/en/LandingPage/aeo-audit.schema.json +92 -0
- package/templates/content/en/LandingPage/agency-waitlist.mdx +340 -0
- package/templates/content/en/LandingPage/agency-waitlist.schema.json +152 -0
- package/templates/content/en/LandingPage/developers.mdx +19 -0
- package/templates/content/en/LandingPage/developers.schema.json +109 -0
- package/templates/content/en/LandingPage/for-agencies.mdx +390 -0
- package/templates/content/en/LandingPage/for-agencies.schema.json +107 -0
- package/templates/content/en/LandingPage/for-ai-search-agencies.mdx +417 -0
- package/templates/content/en/LandingPage/for-ai-search-agencies.schema.json +105 -0
- package/templates/content/en/LandingPage/for-businesses.mdx +19 -0
- package/templates/content/en/LandingPage/for-businesses.schema.json +96 -0
- package/templates/content/en/LandingPage/platform.mdx +369 -0
- package/templates/content/en/LandingPage/platform.schema.json +166 -0
- package/templates/content/en/LandingPage/vs-ai-website-builders.mdx +19 -0
- package/templates/content/en/LandingPage/vs-ai-website-builders.schema.json +102 -0
- package/templates/content/en/LandingPage/vs-wordpress.mdx +19 -0
- package/templates/content/en/LandingPage/vs-wordpress.schema.json +53 -0
- package/templates/content/en/NewsletterSignup/newsletter.mdx +236 -0
- package/templates/content/en/NewsletterSignup/newsletter.schema.json +91 -0
- package/templates/content/en/Organization/site-owner.mdx +16 -0
- package/templates/content/en/Partner/prisma.mdx +31 -0
- package/templates/content/en/Partner/supabase.mdx +30 -0
- package/templates/content/en/Partner/vercel.mdx +28 -0
- package/templates/content/en/PartnersList/partners.mdx +22 -0
- package/templates/content/en/Person/founder.mdx +18 -0
- package/templates/content/en/Pricing/pricing.mdx +538 -0
- package/templates/content/en/Pricing/pricing.schema.json +209 -0
- package/templates/content/en/PrivacyPage/privacy.mdx +165 -0
- package/templates/content/en/PrivacyPage/privacy.schema.json +64 -0
- package/templates/content/en/Product/ailk.mdx +19 -0
- package/templates/content/en/Product/ailk.schema.json +94 -0
- package/templates/content/en/Product/api-launch-kit.mdx +26 -0
- package/templates/content/en/Product/launch-kit.mdx +28 -0
- package/templates/content/en/ProductsList/products.mdx +26 -0
- package/templates/content/en/Project/ailk-phase-2.mdx +54 -0
- package/templates/content/en/ProjectsList/projects.mdx +25 -0
- package/templates/content/en/ResourceDetail/aeo-scoring-guide.mdx +27 -0
- package/templates/content/en/ResourceDetail/content-model-whitepaper.mdx +28 -0
- package/templates/content/en/ResourceDetail/schema-org-quick-reference.mdx +39 -0
- package/templates/content/en/ResourcesHub/resources.mdx +22 -0
- package/templates/content/en/Service/consulting.mdx +22 -0
- package/templates/content/en/Service/implementation.mdx +30 -0
- package/templates/content/en/Service/launch-service.mdx +232 -0
- package/templates/content/en/Service/launch.mdx +228 -0
- package/templates/content/en/ServicesList/services.mdx +84 -0
- package/templates/content/en/SoftwareProduct/ailk-aeo.mdx +44 -0
- package/templates/content/en/SoftwareProduct/ailk-content-adapters.mdx +47 -0
- package/templates/content/en/SoftwareProduct/ailk-schema.mdx +49 -0
- package/templates/content/en/TeamList/team.mdx +63 -0
- package/templates/content/en/TeamMember/founder.mdx +72 -0
- package/templates/content/en/TermsPage/terms.mdx +19 -0
- package/templates/content/en/TermsPage/terms.schema.json +99 -0
- package/templates/content/en/TestimonialsList/testimonials.mdx +44 -0
- package/templates/content/en/UseCasesList/use-cases.mdx +30 -0
- package/templates/content/en/Whitepaper/ax-first-product-development.mdx +27 -0
- package/templates/content/en/Whitepaper/open-core-commercial-strategy.mdx +27 -0
- package/templates/content/en/Whitepaper/structured-data-for-answer-engines.mdx +31 -0
- package/templates/content/en-XA/AboutPage/about.mdx +8 -0
- package/templates/content/en-XA/FAQPage/faq.mdx +8 -0
- package/templates/content/en-XA/HomePage/home.mdx +8 -0
- package/templates/content/es/_site.mdx +30 -0
- package/templates/content/fr/_site.mdx +30 -0
- package/templates/content/ja/_site.mdx +30 -0
- package/templates/content/pt-BR/AboutPage/about.mdx +8 -0
- package/templates/content/pt-BR/FAQPage/faq.mdx +8 -0
- package/templates/content/pt-BR/HomePage/home.mdx +23 -0
- package/templates/database/CHANGELOG.md +5 -0
- package/templates/database/README.md +234 -0
- package/templates/database/__tests__/user-cascade.test.ts +125 -0
- package/templates/database/auth/.gitkeep +0 -0
- package/templates/database/config/.gitkeep +0 -0
- package/templates/database/content/.gitkeep +0 -0
- package/templates/database/inbox/.gitkeep +0 -0
- package/templates/database/inbox/README.md +3 -0
- package/templates/database/inbox/__tests__/schema.test.ts +40 -0
- package/templates/database/inbox/schema.prisma +52 -0
- package/templates/database/jest.config.cjs +29 -0
- package/templates/database/migrations/20260508000000_add_inbox_namespace/migration.sql +328 -0
- package/templates/database/migrations/20260513000000_better_auth_migration/migration.sql +100 -0
- package/templates/database/migrations/20260515000000_add_user_billing_fields/migration.sql +28 -0
- package/templates/database/migrations/20260516000000_add_user_tier_care_plan_seat/migration.sql +25 -0
- package/templates/database/migrations/20260518000000_add_telemetry_records/migration.sql +42 -0
- package/templates/database/migrations/20260525000000_theme_wiring/migration.sql +67 -0
- package/templates/database/migrations/20260710000000_retire_commercial_tier/migration.sql +21 -0
- package/templates/database/migrations/migration_lock.toml +3 -0
- package/templates/database/ops/.gitkeep +0 -0
- package/templates/database/package.json +45 -0
- package/templates/database/prisma.config.ts +20 -0
- package/templates/database/schema.prisma +487 -0
- package/templates/database/scripts/db-generate-locked.sh +80 -0
- package/templates/database/seed-test.ts +85 -0
- package/templates/database/tsconfig.build.json +16 -0
- package/templates/database/tsconfig.json +9 -0
- package/templates/package.json +125 -0
- package/templates/pnpm-workspace.yaml +6 -0
- package/templates/project.yaml +59 -0
- package/templates/tsconfig.base.json +18 -0
- package/templates/tsconfig.json +45 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Severity Levels — Score Banding + Severity Mapping
|
|
2
|
+
|
|
3
|
+
The AEO audit JSON does **not** include explicit severity fields.
|
|
4
|
+
Severity is **derived** by the `audit-site` skill from each rule's
|
|
5
|
+
`weight` and `pass`. This file is the source of truth for that
|
|
6
|
+
mapping.
|
|
7
|
+
|
|
8
|
+
The skill applies these rules in `SKILL.md` Step 5.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Severity tiers
|
|
13
|
+
|
|
14
|
+
| Tier | Source signal | Meaning |
|
|
15
|
+
| -------- | ----------------------------------------------- | ----------------------------------------------------------------------- |
|
|
16
|
+
| Critical | `pass: false` AND `weight >= 10` | Rule that materially affects citation readiness; failure is blocking. |
|
|
17
|
+
| Warning | `pass: false` AND `weight` in `[1, 9]` | Rule that nudges citation quality; failure is fixable, not blocking. |
|
|
18
|
+
| Info | `pass: true` AND `weight: 0` (incentive rules) | Positive signal earned. Bonus, not a finding. |
|
|
19
|
+
| Neutral | `pass: true` AND `weight: 0` AND `bonus: false` | Page is fine but didn't earn the incentive. Don't surface unless asked. |
|
|
20
|
+
|
|
21
|
+
A rule with `pass: false` AND `weight: 0` is **not possible** today
|
|
22
|
+
(incentive rules are designed to never fail — see
|
|
23
|
+
`faq-howto-incentive` in `packages/aeo`). If one ever appears,
|
|
24
|
+
treat it as Info (the rule's own design says failures are neutral).
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Why weight thresholds, not explicit severity
|
|
29
|
+
|
|
30
|
+
The AEO type system intentionally keeps rules weight-based, not
|
|
31
|
+
severity-based. Reasons:
|
|
32
|
+
|
|
33
|
+
- **Score arithmetic stays simple.** `passing-weight / total-weight`
|
|
34
|
+
is the score; introducing severity as a separate axis would force
|
|
35
|
+
every rule to choose two attributes (weight AND severity) when
|
|
36
|
+
one is enough.
|
|
37
|
+
- **The skill is the right place for the translation.** Consumers
|
|
38
|
+
don't care about weights — they care about "should I fix this?".
|
|
39
|
+
The skill turns "weight 10 fail" into "Critical" because that's
|
|
40
|
+
the language consumers can act on.
|
|
41
|
+
- **Rule authors don't have to think about severity.** A new rule
|
|
42
|
+
added to `packages/aeo` gets a weight (its impact on the score)
|
|
43
|
+
and the skill maps that to a severity tier automatically. No
|
|
44
|
+
coupling between rule authoring and consumer-facing UX.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Score banding (optional)
|
|
49
|
+
|
|
50
|
+
When the consumer asks "is this a good score?", you can map the
|
|
51
|
+
numeric score to a band. This is optional — Step 4 always emits
|
|
52
|
+
the raw score first.
|
|
53
|
+
|
|
54
|
+
| Score | Band | Hint |
|
|
55
|
+
| ------ | ----------------- | ---------------------------------------------------------------- |
|
|
56
|
+
| 90–100 | Excellent | All critical rules pass; site is well-instrumented for citation. |
|
|
57
|
+
| 75–89 | Good | Probably a critical or warning fixable on a couple of pages. |
|
|
58
|
+
| 50–74 | Needs work | Multiple critical rules failing; address those first. |
|
|
59
|
+
| 0–49 | Foundational gaps | Site likely has no schema or invalid schema across most pages. |
|
|
60
|
+
|
|
61
|
+
Hint sentences are suggestions; adapt phrasing to the consumer's
|
|
62
|
+
context. Don't quote the band tag verbatim if a more natural
|
|
63
|
+
phrasing fits the conversation ("you're at 87 — couple of fixes
|
|
64
|
+
away from clean").
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Severity counting for the summary line
|
|
69
|
+
|
|
70
|
+
Step 5 of SKILL.md asks for a summary like:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
2 critical · 1 warning · 0 info
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Counts are computed as:
|
|
77
|
+
|
|
78
|
+
- **Critical count** = count of `perRule[]` entries where
|
|
79
|
+
`pass === false && weight >= 10`.
|
|
80
|
+
- **Warning count** = count of `perRule[]` entries where
|
|
81
|
+
`pass === false && weight >= 1 && weight < 10`.
|
|
82
|
+
- **Info count** = count of `perRule[]` entries where
|
|
83
|
+
`pass === true && weight === 0` (i.e., earned incentives).
|
|
84
|
+
|
|
85
|
+
Some rules surface per-page failures (`perRule[].perPage[]`).
|
|
86
|
+
Those are deeper-level findings the skill can drill into in Step 6;
|
|
87
|
+
they don't change the rule-level severity counts. A `schema-coverage`
|
|
88
|
+
rule with `pass: false` and 5 failing pages is **one** critical
|
|
89
|
+
finding (the rule failed), with 5 page-specific evidence entries
|
|
90
|
+
for drill-down.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## What this skill does NOT classify as severity
|
|
95
|
+
|
|
96
|
+
- **`bonus: true` per page** is not a finding; it's a positive
|
|
97
|
+
signal. Surface it on drill-down ("These pages earned the FAQ
|
|
98
|
+
bonus: …") but don't include it in the severity summary.
|
|
99
|
+
- **Schema-version mismatch** (a `meta.schemaVersion` from the
|
|
100
|
+
audit that doesn't match the consumer's `@working-theory/schema`) is not a
|
|
101
|
+
rule failure — it's a setup-drift signal. Surface only if the
|
|
102
|
+
consumer asks why the score might be inconsistent across runs.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Future rules
|
|
107
|
+
|
|
108
|
+
When `packages/aeo` adds a new rule, this glossary may not name
|
|
109
|
+
it. The severity mapping still works because it keys off `weight`
|
|
110
|
+
and `pass` only — both fields are guaranteed by the
|
|
111
|
+
`PerRuleResult` type. New critical-tier rules will surface as
|
|
112
|
+
`Critical` automatically; new warnings as `Warning`. The findings
|
|
113
|
+
glossary may lag in offering plain-language explanations until
|
|
114
|
+
this template is updated.
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: provision-config
|
|
3
|
+
description: Emit deploy configuration for an AILK consumer site — `vercel.json`, `.env.example`, and `RUNBOOK.md`. Vercel-only at v1; other platforms reject with a clear "not yet supported" message. Use when the user asks "set up Vercel", "provision deploy config", "what env vars do I need for production?", "I'm ready to ship to Vercel", or otherwise asks about pre-deploy file setup. The RUNBOOK includes the three named persistence-upgrade paths for leads.jsonl (Vercel KV / Supabase / Postgres-via-`@working-theory/database`).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# provision-config
|
|
7
|
+
|
|
8
|
+
Emit `vercel.json`, `.env.example`, and `RUNBOOK.md` at the consumer's
|
|
9
|
+
project root, ready for a Vercel deploy. Vercel is the only valid
|
|
10
|
+
`platform` value at v1. Other platforms (Netlify, Cloudflare, Render,
|
|
11
|
+
Fly, self-host) reject with an explicit "not yet supported" message
|
|
12
|
+
and emit nothing.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
The consumer is preparing to deploy their AILK site for the first
|
|
17
|
+
time, or wants to verify their deploy config is complete. Triggers:
|
|
18
|
+
|
|
19
|
+
- "provision Vercel config" / "set up Vercel"
|
|
20
|
+
- "what env vars do I need to deploy?"
|
|
21
|
+
- "I'm ready to ship — what files do I need?"
|
|
22
|
+
- "regenerate `vercel.json`" / "refresh `.env.example`"
|
|
23
|
+
|
|
24
|
+
Skip this skill when:
|
|
25
|
+
|
|
26
|
+
- The consumer is on a non-Vercel platform — emit the rejection
|
|
27
|
+
message (see Step 1) and stop.
|
|
28
|
+
- The consumer asks about runtime environment values
|
|
29
|
+
(`process.env.X` debugging) — that's an app-level concern, not a
|
|
30
|
+
config-emission concern.
|
|
31
|
+
- The consumer is asking about Stripe live-mode setup — that's
|
|
32
|
+
hard-floor blocked across AILK; sandbox-only at v1. Mention and stop.
|
|
33
|
+
|
|
34
|
+
## What this skill does (and does not do)
|
|
35
|
+
|
|
36
|
+
**Does:**
|
|
37
|
+
|
|
38
|
+
- Validate the `platform` parameter — only `vercel` is accepted at v1.
|
|
39
|
+
- Detect existing `vercel.json`, `.env.example`, and `RUNBOOK.md` at
|
|
40
|
+
the consumer's project root.
|
|
41
|
+
- For each artifact, ask the consumer how to handle conflicts
|
|
42
|
+
(merge / overwrite / skip) before writing.
|
|
43
|
+
- Emit the three artifacts at the consumer's project root, derived
|
|
44
|
+
from templates in `references/`.
|
|
45
|
+
- Validate the emitted output (parse `vercel.json` as JSON, check
|
|
46
|
+
`.env.example` covers required vars, confirm `RUNBOOK.md` has the
|
|
47
|
+
three named persistence-upgrade headings).
|
|
48
|
+
|
|
49
|
+
**Does not:**
|
|
50
|
+
|
|
51
|
+
- Call any Vercel API. The consumer runs `vercel deploy` themselves.
|
|
52
|
+
- Read or write live secrets. `.env.example` uses placeholder values
|
|
53
|
+
only.
|
|
54
|
+
- Configure Cloudflare anything (deploy target, KV, D1, R2). CF is
|
|
55
|
+
deferred entirely as a coherent follow-up unit.
|
|
56
|
+
- Emit Netlify / Render / Fly / self-host config. v1 is Vercel only.
|
|
57
|
+
- Modify the consumer's actual `.env.local` or any other file
|
|
58
|
+
containing real secrets.
|
|
59
|
+
|
|
60
|
+
## The mechanic
|
|
61
|
+
|
|
62
|
+
### Step 1 — Validate the platform parameter
|
|
63
|
+
|
|
64
|
+
Default platform is `vercel`. If the consumer asks for any other
|
|
65
|
+
platform, respond:
|
|
66
|
+
|
|
67
|
+
> "`provision-config` is Vercel-only at v1. Netlify / Cloudflare /
|
|
68
|
+
> Render / Fly / self-host support are tracked at the upstream repo —
|
|
69
|
+
> file an issue at <https://github.com/tailwind-ai/ai-launch-kit/issues>
|
|
70
|
+
> if your platform is missing.
|
|
71
|
+
>
|
|
72
|
+
> Cloudflare is deferred entirely (deploy target + KV/D1/R2 data
|
|
73
|
+
> layer) as a coherent follow-up. CF requires different default
|
|
74
|
+
> persistence per platform because Workers lack the Node `fs` API
|
|
75
|
+
> the JSONL fallback depends on."
|
|
76
|
+
|
|
77
|
+
Then stop. Do not emit any files.
|
|
78
|
+
|
|
79
|
+
### Step 2 — Detect existing artifacts
|
|
80
|
+
|
|
81
|
+
Look for `vercel.json`, `.env.example`, and `RUNBOOK.md` at the
|
|
82
|
+
consumer's project root. For each one, note:
|
|
83
|
+
|
|
84
|
+
- **Missing** — will emit fresh.
|
|
85
|
+
- **Present** — ask how to handle (Step 3).
|
|
86
|
+
|
|
87
|
+
### Step 3 — Conflict handling per file
|
|
88
|
+
|
|
89
|
+
For each existing artifact, show the consumer:
|
|
90
|
+
|
|
91
|
+
1. The first ~10 lines of the existing file (preview).
|
|
92
|
+
2. A summary of what the skill would emit (template name + key
|
|
93
|
+
fields).
|
|
94
|
+
3. Three options: **merge** (only for `RUNBOOK.md` and
|
|
95
|
+
`.env.example` — see merge logic below), **overwrite**
|
|
96
|
+
(replace contents), **skip** (leave existing file untouched).
|
|
97
|
+
|
|
98
|
+
Wait for the consumer's choice per file. Do not blindly overwrite.
|
|
99
|
+
|
|
100
|
+
**Merge logic — `.env.example`:** if a var listed in
|
|
101
|
+
`references/env-vars-template.md` is **missing** from the existing
|
|
102
|
+
file, append it (with comment) at the bottom under a "## Added by
|
|
103
|
+
provision-config" section. Vars already present are not modified.
|
|
104
|
+
|
|
105
|
+
**Merge logic — `RUNBOOK.md`:** if any of the three named
|
|
106
|
+
persistence sections (Vercel KV, Supabase,
|
|
107
|
+
Postgres-via-`@working-theory/database`) is missing from the existing file,
|
|
108
|
+
append it at the end. Existing sections are not modified.
|
|
109
|
+
|
|
110
|
+
**Merge logic — `vercel.json`:** **not supported.** `vercel.json` is
|
|
111
|
+
either overwritten or skipped — no field-level merge. Reason: the
|
|
112
|
+
file is small and consumers are likely to have customized it
|
|
113
|
+
intentionally; merging risks subtle config drift.
|
|
114
|
+
|
|
115
|
+
### Step 4 — Emit `vercel.json`
|
|
116
|
+
|
|
117
|
+
Use the template at `references/vercel-json-template.md`. The
|
|
118
|
+
emitted file has these fields:
|
|
119
|
+
|
|
120
|
+
- `version: 2` — Vercel config schema version.
|
|
121
|
+
- `framework: "nextjs"` — Vercel auto-detects `apps/web` as Next.js.
|
|
122
|
+
- `buildCommand` — pnpm-aware build (typically
|
|
123
|
+
`cd ../.. && pnpm install --frozen-lockfile && pnpm --filter ./apps/web build`
|
|
124
|
+
for monorepo deploys, or `pnpm build` for single-app deploys).
|
|
125
|
+
- `installCommand` — match the consumer's package manager.
|
|
126
|
+
- `env` — env-var passthrough; AILK ships an empty `env: {}` and
|
|
127
|
+
expects Vercel's project-level env-var dashboard to handle real
|
|
128
|
+
values.
|
|
129
|
+
|
|
130
|
+
After write, parse the JSON. If parse fails, the skill has a bug —
|
|
131
|
+
report it to the consumer with the literal error.
|
|
132
|
+
|
|
133
|
+
### Step 5 — Emit `.env.example`
|
|
134
|
+
|
|
135
|
+
Use the template at `references/env-vars-template.md`. The emitted
|
|
136
|
+
file lists every env var the consumer's site reads, grouped by
|
|
137
|
+
concern (auth, content, payments, analytics, etc.) with placeholder
|
|
138
|
+
values and inline comments.
|
|
139
|
+
|
|
140
|
+
The skill **does not** read live `.env` files. Placeholder values
|
|
141
|
+
only. No `sk_live_*`, no `pk_live_*`, no real Resend keys, no real
|
|
142
|
+
NextAuth secrets.
|
|
143
|
+
|
|
144
|
+
After write, count the declared vars and confirm the count matches
|
|
145
|
+
the template's expected count. If a var the consumer's site uses
|
|
146
|
+
(grep `process.env.X` from a quick scan) is missing from the
|
|
147
|
+
template, add it under "## Added by provision-config" — never silently
|
|
148
|
+
omit a var the consumer needs.
|
|
149
|
+
|
|
150
|
+
### Step 6 — Emit `RUNBOOK.md`
|
|
151
|
+
|
|
152
|
+
Use the template at `references/runbook-template.md`. The emitted
|
|
153
|
+
runbook has these sections:
|
|
154
|
+
|
|
155
|
+
1. **Pre-deploy checklist** — what to set in Vercel's project
|
|
156
|
+
dashboard before clicking Deploy.
|
|
157
|
+
2. **Operations — leads.jsonl persistence** — the **critical**
|
|
158
|
+
section. AILK's lead-capture writes JSONL to
|
|
159
|
+
`apps/api/leads.jsonl`, which **does not persist** on Vercel's
|
|
160
|
+
ephemeral filesystem. Consumer must pick a persistence backend
|
|
161
|
+
before going live or leads disappear on cold-start.
|
|
162
|
+
3. **Persistence upgrade — Vercel KV** — drop-in, no new infra,
|
|
163
|
+
cheapest fix. When to pick.
|
|
164
|
+
4. **Persistence upgrade — Supabase** — Postgres + auth + storage
|
|
165
|
+
in one provider. When to pick.
|
|
166
|
+
5. **Persistence upgrade — Postgres via `@working-theory/database`** — for
|
|
167
|
+
consumers who already have Postgres elsewhere (Neon, Railway,
|
|
168
|
+
RDS). When to pick.
|
|
169
|
+
6. **Custom domain + DNS** — pointer at Vercel's domain docs.
|
|
170
|
+
7. **Production callbacks for OAuth** — for consumers who used
|
|
171
|
+
`scaffold-auth` (#364) and need to register prod redirect URIs.
|
|
172
|
+
|
|
173
|
+
After write, grep the RUNBOOK for the three named persistence
|
|
174
|
+
section headings (Vercel KV, Supabase,
|
|
175
|
+
Postgres-via-`@working-theory/database`). All three must be present. If any
|
|
176
|
+
is missing, the skill has a bug — flag with the literal error.
|
|
177
|
+
|
|
178
|
+
### Step 7 — Closing summary
|
|
179
|
+
|
|
180
|
+
Print:
|
|
181
|
+
|
|
182
|
+
- Which artifacts were emitted vs skipped (per consumer's Step 3
|
|
183
|
+
choices).
|
|
184
|
+
- A pointer to `RUNBOOK.md`'s leads-persistence section (the
|
|
185
|
+
highest-stakes operational caveat).
|
|
186
|
+
- A reminder that Vercel project-level env-vars need to be set in
|
|
187
|
+
the Vercel dashboard before deploy — `.env.example` is the
|
|
188
|
+
contract, not the values.
|
|
189
|
+
- The next step: `vercel deploy` (or `git push` if the consumer is
|
|
190
|
+
using Vercel's GitHub integration).
|
|
191
|
+
|
|
192
|
+
## Re-invocation
|
|
193
|
+
|
|
194
|
+
The skill is idempotent. Re-running on a project with all three
|
|
195
|
+
artifacts present asks the consumer how to handle each conflict
|
|
196
|
+
(per Step 3). A consumer who picks **skip** for all three gets a
|
|
197
|
+
no-op run with a "all artifacts already present, nothing to do"
|
|
198
|
+
message.
|
|
199
|
+
|
|
200
|
+
## Validation
|
|
201
|
+
|
|
202
|
+
Before reporting "done":
|
|
203
|
+
|
|
204
|
+
- `vercel.json` parses as JSON ✓
|
|
205
|
+
- `.env.example` declares >= the count of vars in the template ✓
|
|
206
|
+
- `RUNBOOK.md` contains all three named persistence section
|
|
207
|
+
headings ✓
|
|
208
|
+
|
|
209
|
+
If any check fails, surface the failure to the consumer (not silent).
|
|
210
|
+
|
|
211
|
+
## What this skill does NOT validate
|
|
212
|
+
|
|
213
|
+
- That the consumer's Vercel project actually deploys. That's
|
|
214
|
+
`vercel deploy`'s job.
|
|
215
|
+
- That env-var values in the consumer's Vercel dashboard are
|
|
216
|
+
correct or live. The skill never reads dashboard state.
|
|
217
|
+
- That OAuth callback URLs in `scaffold-auth`'s RUNBOOK are
|
|
218
|
+
registered in production OAuth apps. That's the consumer's job
|
|
219
|
+
pre-launch.
|
|
220
|
+
|
|
221
|
+
## References
|
|
222
|
+
|
|
223
|
+
- `references/vercel-json-template.md` — minimal viable `vercel.json`.
|
|
224
|
+
- `references/env-vars-template.md` — `.env.example` structure with
|
|
225
|
+
placeholder values per category.
|
|
226
|
+
- `references/runbook-template.md` — `RUNBOOK.md` with the three
|
|
227
|
+
named persistence-upgrade sections.
|
|
228
|
+
|
|
229
|
+
## Coordination
|
|
230
|
+
|
|
231
|
+
- **`scaffold-auth` (#364)** — produces its own `RUNBOOK.md`
|
|
232
|
+
sections for OAuth setup (dev callback URLs). This skill's
|
|
233
|
+
RUNBOOK adds production callback URLs and merges with any
|
|
234
|
+
existing runbook content (not blindly overwrites).
|
|
235
|
+
- **`@working-theory/env`** — at v1 a placeholder package, not yet a Zod
|
|
236
|
+
schema. This skill derives `.env.example` from the template, not
|
|
237
|
+
from a runtime schema. When `@working-theory/env` ships its schema, this
|
|
238
|
+
skill should be revised to read from it.
|
|
239
|
+
- **Stripe sandbox-only** — hard-floor enforced globally. Emitted
|
|
240
|
+
`.env.example` uses `sk_test_*` placeholders, never `sk_live_*`.
|
|
241
|
+
- **Cloudflare deferred** — neither CF Pages (deploy target) nor
|
|
242
|
+
CF KV / D1 / R2 (data layer) is in v1. Will ship as a coherent
|
|
243
|
+
follow-up PR.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# `.env.example` Template
|
|
2
|
+
|
|
3
|
+
The structure the `provision-config` skill emits at the consumer's
|
|
4
|
+
project root. Placeholder values only — the skill never echoes a
|
|
5
|
+
real secret.
|
|
6
|
+
|
|
7
|
+
When `@working-theory/env` ships a Zod schema (currently a placeholder
|
|
8
|
+
package), this template should be revised to derive from that
|
|
9
|
+
schema instead. Until then, this file is the source of truth for
|
|
10
|
+
what env vars an AILK consumer site reads.
|
|
11
|
+
|
|
12
|
+
## Template
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# AI Launch Kit — environment template
|
|
16
|
+
# Copy this file to `.env.local` (gitignored) and fill in values.
|
|
17
|
+
# Production values live in your deploy platform's dashboard
|
|
18
|
+
# (Vercel project settings → Environment Variables).
|
|
19
|
+
|
|
20
|
+
# ── Marketing / canonical domain ─────────────────────────────────
|
|
21
|
+
# Your site's canonical public domain (no protocol).
|
|
22
|
+
AILK_PUBLIC_DOMAIN=your-domain.com
|
|
23
|
+
|
|
24
|
+
# ── Content backend ──────────────────────────────────────────────
|
|
25
|
+
# AILK's MDX adapter is the default. Other adapters ship as
|
|
26
|
+
# additive PRs later.
|
|
27
|
+
CONTENT_BACKEND=mdx
|
|
28
|
+
# Override the content directory. Default is <repo-root>/content.
|
|
29
|
+
# AILK_CONTENT_ROOT=
|
|
30
|
+
|
|
31
|
+
# ── Database (optional in standalone mode) ───────────────────────
|
|
32
|
+
# Required only if you've installed @working-theory/database for persistent
|
|
33
|
+
# leads, sessions, or other data. See RUNBOOK.md § "Persistence
|
|
34
|
+
# upgrade — Postgres via @working-theory/database" for setup.
|
|
35
|
+
# DATABASE_URL=postgres://user:pass@host:5432/db
|
|
36
|
+
|
|
37
|
+
# ── Auth — required env vars ─────────────────────────────────────
|
|
38
|
+
# Set to "1" to require sign-in for protected routes; default is
|
|
39
|
+
# auth-disabled / public.
|
|
40
|
+
# AILK_AUTH_REQUIRED=1
|
|
41
|
+
#
|
|
42
|
+
# NextAuth secret — production must be set; generate with:
|
|
43
|
+
# openssl rand -base64 32
|
|
44
|
+
# Local dev (next dev) auto-generates a session-only secret.
|
|
45
|
+
# NEXTAUTH_SECRET=
|
|
46
|
+
#
|
|
47
|
+
# Production base URL for callback construction. Local dev defaults
|
|
48
|
+
# to http://localhost:3000 if unset.
|
|
49
|
+
# NEXTAUTH_URL=https://your-domain.com
|
|
50
|
+
|
|
51
|
+
# ── Auth — magic-link (Resend) ───────────────────────────────────
|
|
52
|
+
# Activated when both AUTH_EMAIL_SERVER and AUTH_EMAIL_FROM are set.
|
|
53
|
+
# Get a Resend API key at https://resend.com/api-keys.
|
|
54
|
+
# AUTH_EMAIL_SERVER=smtp://resend:re_yourkeyhere@smtp.resend.com:465
|
|
55
|
+
# AUTH_EMAIL_FROM=onboarding@resend.dev
|
|
56
|
+
|
|
57
|
+
# ── Auth — Google OAuth ──────────────────────────────────────────
|
|
58
|
+
# Activated when both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET set.
|
|
59
|
+
# Set up at https://console.cloud.google.com/apis/credentials.
|
|
60
|
+
# Production callback: https://your-domain.com/api/auth/callback/google
|
|
61
|
+
# GOOGLE_CLIENT_ID=
|
|
62
|
+
# GOOGLE_CLIENT_SECRET=
|
|
63
|
+
|
|
64
|
+
# ── Auth — GitHub OAuth ──────────────────────────────────────────
|
|
65
|
+
# Activated when both GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET set.
|
|
66
|
+
# Set up at https://github.com/settings/developers.
|
|
67
|
+
# Production callback: https://your-domain.com/api/auth/callback/github
|
|
68
|
+
# GITHUB_CLIENT_ID=
|
|
69
|
+
# GITHUB_CLIENT_SECRET=
|
|
70
|
+
|
|
71
|
+
# ── Stripe (sandbox keys only — sk_test_* / pk_test_*) ───────────
|
|
72
|
+
# AILK is sandbox-only at v1. Live keys (sk_live_*, pk_live_*) are
|
|
73
|
+
# hook-blocked from appearing in source.
|
|
74
|
+
# Get test keys at https://dashboard.stripe.com/test/apikeys.
|
|
75
|
+
# STRIPE_SECRET_KEY=sk_test_...
|
|
76
|
+
# NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
|
|
77
|
+
# Webhook signing secret — see Stripe Dashboard → Developers →
|
|
78
|
+
# Webhooks → <endpoint> → Signing secret. Format: whsec_*.
|
|
79
|
+
# STRIPE_WEBHOOK_SECRET=
|
|
80
|
+
|
|
81
|
+
# ── Email provider (Resend) ──────────────────────────────────────
|
|
82
|
+
# Used by transactional senders outside auth (e.g., contact form).
|
|
83
|
+
# Same Resend account as magic-link if both are configured.
|
|
84
|
+
# RESEND_API_KEY=
|
|
85
|
+
|
|
86
|
+
# ── Analytics — all off by default ───────────────────────────────
|
|
87
|
+
# Each provider is independent. Set the env var(s) to enable.
|
|
88
|
+
#
|
|
89
|
+
# Vercel Analytics — built-in dashboard for Vercel deploys.
|
|
90
|
+
# Requires Vercel hosting. Set to "true" to enable. Requires redeploy
|
|
91
|
+
# after change (NEXT_PUBLIC_* values bake at build time).
|
|
92
|
+
# NEXT_PUBLIC_VERCEL_ANALYTICS_ENABLED=
|
|
93
|
+
#
|
|
94
|
+
# Google Analytics 4 — gtag.js measurement. Requires consent in EU/UK/CA.
|
|
95
|
+
# Get the measurement ID from analytics.google.com → Admin → Data Streams.
|
|
96
|
+
# Format: G-XXXXXXXXXX. Requires redeploy after change.
|
|
97
|
+
# NEXT_PUBLIC_GA_MEASUREMENT_ID=
|
|
98
|
+
#
|
|
99
|
+
# GA4 Measurement Protocol — server-side analytics secret.
|
|
100
|
+
# Required alongside NEXT_PUBLIC_GA_MEASUREMENT_ID for server-side
|
|
101
|
+
# lead/purchase events.
|
|
102
|
+
# GA_API_SECRET=
|
|
103
|
+
#
|
|
104
|
+
# Google Search Console — verification meta tag. No script, no consent.
|
|
105
|
+
# Get the token from search.google.com/search-console → Settings →
|
|
106
|
+
# Ownership verification → HTML tag. Paste only the content="..." value.
|
|
107
|
+
# GOOGLE_SITE_VERIFICATION=
|
|
108
|
+
|
|
109
|
+
# ── Persistent leads (optional) ──────────────────────────────────
|
|
110
|
+
# By default, leads.jsonl is written to apps/api/leads.jsonl. On
|
|
111
|
+
# Vercel's ephemeral filesystem this does NOT persist across cold
|
|
112
|
+
# starts. See RUNBOOK.md § "Persistence upgrade" for the three
|
|
113
|
+
# named upgrade paths.
|
|
114
|
+
#
|
|
115
|
+
# Vercel KV (drop-in):
|
|
116
|
+
# KV_REST_API_URL=
|
|
117
|
+
# KV_REST_API_TOKEN=
|
|
118
|
+
#
|
|
119
|
+
# Supabase (Postgres + auth + storage):
|
|
120
|
+
# NEXT_PUBLIC_SUPABASE_URL=
|
|
121
|
+
# NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
122
|
+
# SUPABASE_SERVICE_ROLE_KEY=
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Categories the skill emits
|
|
126
|
+
|
|
127
|
+
The template above groups vars into seven categories. Every emitted
|
|
128
|
+
`.env.example` should hit each category at least with its header
|
|
129
|
+
comment, even if the consumer hasn't activated any vars in that
|
|
130
|
+
category — the comment block tells future-them what's available.
|
|
131
|
+
|
|
132
|
+
Categories:
|
|
133
|
+
|
|
134
|
+
1. Marketing / canonical domain
|
|
135
|
+
2. Content backend
|
|
136
|
+
3. Database (optional)
|
|
137
|
+
4. Auth — required + per-provider
|
|
138
|
+
5. Stripe (sandbox-only)
|
|
139
|
+
6. Email + Analytics
|
|
140
|
+
7. Persistent leads (optional)
|
|
141
|
+
|
|
142
|
+
## What the skill never includes
|
|
143
|
+
|
|
144
|
+
- Real secret values. All values are placeholders or commented
|
|
145
|
+
examples.
|
|
146
|
+
- Live Stripe keys. Sandbox-only at AILK v1.
|
|
147
|
+
- Live Vercel deploy tokens. The Vercel CLI handles deploy auth via
|
|
148
|
+
`vercel login`.
|
|
149
|
+
- Database connection strings with embedded passwords. Comments
|
|
150
|
+
show shape only.
|
|
151
|
+
|
|
152
|
+
## Counting vars for validation
|
|
153
|
+
|
|
154
|
+
The skill's Step 5 validation counts the declared (uncommented) vars
|
|
155
|
+
the template emits and confirms the count is non-zero. Empty
|
|
156
|
+
`.env.example` is a bug. Currently declared vars in the template:
|
|
157
|
+
|
|
158
|
+
- `AILK_PUBLIC_DOMAIN`
|
|
159
|
+
- `CONTENT_BACKEND`
|
|
160
|
+
|
|
161
|
+
(All other entries are commented optional vars.) The skill should
|
|
162
|
+
not require the consumer to set every commented var — they're
|
|
163
|
+
opt-in. The two declared entries are the minimum the AILK scaffold
|
|
164
|
+
needs to boot, even on a static-content-only site.
|
|
165
|
+
|
|
166
|
+
## Merge logic
|
|
167
|
+
|
|
168
|
+
If the consumer already has `.env.example`, the skill (per SKILL.md
|
|
169
|
+
Step 3) offers merge / overwrite / skip. Merge logic:
|
|
170
|
+
|
|
171
|
+
1. Read the existing file.
|
|
172
|
+
2. For each line in this template that's not a comment-only line,
|
|
173
|
+
check whether the var name already appears anywhere in the
|
|
174
|
+
existing file (commented or uncommented).
|
|
175
|
+
3. Vars **already present** are not modified — the consumer's
|
|
176
|
+
existing comments and value choices win.
|
|
177
|
+
4. Vars **missing** are appended at the end of the existing file
|
|
178
|
+
under a new section:
|
|
179
|
+
```
|
|
180
|
+
# ── Added by provision-config ────────────────────────────────
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This avoids duplicating vars while still surfacing additions the
|
|
184
|
+
template gained since the consumer's last run.
|