create-ailk 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -10
- package/component-catalog.json +798 -49
- package/component-catalog.md +9 -6
- package/dist/add-module.d.ts +20 -0
- package/dist/add-module.js +43 -7
- package/dist/add-route.d.ts +56 -0
- package/dist/add-route.js +286 -0
- package/dist/apply-design-md.d.ts +7 -0
- package/dist/apply-design-md.js +50 -0
- package/dist/apply-design.d.ts +64 -0
- package/dist/apply-design.js +273 -0
- package/dist/claude-md.d.ts +111 -0
- package/dist/claude-md.js +334 -0
- package/dist/cli.js +114 -28
- package/dist/derive-architecture.js +41 -36
- package/dist/design-compile.d.ts +71 -0
- package/dist/design-compile.js +98 -0
- package/dist/design-package.d.ts +83 -0
- package/dist/design-package.js +468 -0
- package/dist/design-presets.d.ts +86 -0
- package/dist/design-presets.js +642 -0
- package/dist/design-scaffold.d.ts +76 -0
- package/dist/design-scaffold.js +220 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/legacy-nav-renderers.d.ts +45 -0
- package/dist/legacy-nav-renderers.js +545 -0
- package/dist/lib/auth-secret-file.d.ts +19 -0
- package/dist/lib/auth-secret-file.js +112 -0
- package/dist/lib/design-checks.d.ts +78 -0
- package/dist/lib/design-checks.js +174 -0
- package/dist/lib/extract-module-bundle.js +5 -1
- package/dist/lib/license-key-files.d.ts +9 -0
- package/dist/lib/license-key-files.js +2 -2
- package/dist/lib/module-license-gate.d.ts +89 -0
- package/dist/lib/module-license-gate.js +171 -12
- package/dist/lib/module-tier.d.ts +45 -16
- package/dist/lib/module-tier.js +76 -0
- package/dist/lib/pro-callout.js +10 -2
- package/dist/lib/render-verdict.d.ts +52 -0
- package/dist/lib/render-verdict.js +77 -0
- package/dist/lib/scaffold-render-sweep.d.ts +105 -0
- package/dist/lib/scaffold-render-sweep.js +236 -0
- package/dist/module-architecture.d.ts +19 -16
- package/dist/module-architecture.js +64 -21
- package/dist/parse-args.d.ts +88 -10
- package/dist/parse-args.js +272 -21
- package/dist/programmatic.d.ts +66 -12
- package/dist/programmatic.js +361 -34
- package/dist/site-chrome.d.ts +19 -9
- package/dist/site-chrome.js +23 -13
- package/dist/site-manifest.d.ts +25 -0
- package/dist/site-manifest.js +254 -0
- package/dist/site-roster.d.ts +41 -0
- package/dist/site-roster.js +149 -11
- package/dist/starter-grid.d.ts +232 -0
- package/dist/starter-grid.js +545 -0
- package/dist/surfaces.d.ts +41 -9
- package/dist/surfaces.js +268 -92
- package/dist/template-manifest.d.ts +65 -29
- package/dist/template-manifest.js +161 -382
- package/dist/template-names.d.ts +14 -12
- package/dist/template-names.js +13 -17
- package/package.json +5 -4
- package/site-templates/_base/content/en/Feature/feature-1.mdx +69 -0
- package/site-templates/_base/content/en/Feature/feature-2.mdx +69 -0
- package/site-templates/_base/content/en/Feature/feature-3.mdx +69 -0
- package/site-templates/_base/content/en/FeaturesList/features.mdx +91 -0
- package/site-templates/_base/content/en/GlossaryList/glossary.mdx +0 -1
- package/site-templates/_base/content/en/NewsletterSignup/newsletter.mdx +0 -1
- package/site-templates/_base/content/en/PortfolioItem/sample-four.mdx +105 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-one.mdx +34 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-three.mdx +94 -0
- package/site-templates/_base/content/en/PortfolioItem/sample-two.mdx +45 -0
- package/site-templates/_base/content/en/PortfolioList/portfolio.mdx +169 -0
- package/site-templates/_base/content/en/PrivacyPage/privacy.mdx +15 -0
- package/site-templates/_base/content/en/UseCase/persona-1.mdx +70 -0
- package/site-templates/_base/content/en/UseCase/persona-2.mdx +70 -0
- package/site-templates/_base/content/en/UseCase/persona-3.mdx +70 -0
- package/site-templates/{minimalism-site/TEMPLATE-MANIFEST.json → aliases/minimalism-site.TEMPLATE-MANIFEST.json} +72 -40
- package/site-templates/designs/minimalism/DESIGN.md +98 -6
- package/site-templates/designs/minimalism/sample/README.md +48 -0
- package/site-templates/designs/standard/DESIGN.md +103 -6
- package/site-templates/marketing-site/DESIGN.md +103 -6
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +144 -47
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +82 -41
- package/site-templates/marketing-site-free/DESIGN.md +103 -6
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +150 -48
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +114 -67
- package/site-templates/marketing-site-free/ailk-template.json +1 -1
- package/site-templates/marketing-site-free/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +199 -0
- package/site-templates/saas-product/DESIGN.md +103 -6
- package/site-templates/saas-product/TEMPLATE-MANIFEST.md +9 -1
- package/site-templates/{simple-service → shapes/local-business-service}/TEMPLATE-MANIFEST.json +210 -81
- package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +356 -0
- package/site-templates/shapes/local-business-service/ailk-template.json +10 -0
- package/site-templates/{simple-service → shapes/local-business-service}/content/en/AboutPage/about.mdx +4 -4
- package/site-templates/shapes/local-business-service/content/en/HomePage/home.mdx +70 -0
- package/site-templates/shapes/local-business-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/shapes/local-business-service/content/en/PortfolioList/portfolio.mdx +171 -0
- package/site-templates/{minimalism-site → shapes/local-business-service}/content/en/PurchasePolicyPage/purchase-policy.mdx +7 -8
- package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +39 -0
- package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +39 -0
- package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +39 -0
- package/site-templates/shapes/local-business-service/content/en/ServicesList/services.mdx +61 -0
- package/site-templates/shapes/local-business-service/provenance.json +4 -0
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +471 -0
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +354 -0
- package/site-templates/shapes/organization-service/ailk-template.json +10 -0
- package/site-templates/shapes/organization-service/content/en/AboutPage/about.mdx +38 -0
- package/site-templates/shapes/organization-service/content/en/HomePage/home.mdx +85 -0
- package/site-templates/shapes/organization-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/shapes/organization-service/content/en/PortfolioList/portfolio.mdx +171 -0
- package/site-templates/shapes/organization-service/content/en/PurchasePolicyPage/purchase-policy.mdx +123 -0
- package/site-templates/{minimalism-site → shapes/organization-service}/content/en/ServicesList/services.mdx +3 -4
- package/site-templates/shapes/organization-service/provenance.json +4 -0
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +478 -0
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +353 -0
- package/site-templates/shapes/person-service/ailk-template.json +10 -0
- package/site-templates/shapes/person-service/content/_site.mdx +85 -0
- package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +39 -0
- package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +97 -0
- package/site-templates/shapes/person-service/content/en/NewsletterSignup/newsletter.mdx +59 -0
- package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +171 -0
- package/site-templates/{simple-service → shapes/person-service}/content/en/PurchasePolicyPage/purchase-policy.mdx +10 -11
- package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +38 -0
- package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +38 -0
- package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +38 -0
- package/site-templates/{simple-service → shapes/person-service}/content/en/ServicesList/services.mdx +16 -16
- package/site-templates/shapes/person-service/provenance.json +4 -0
- package/templates/.claude/rules/architecture.md +7 -0
- package/templates/.claude/skills/README.md +5 -3
- package/templates/.claude/skills/add-auth/references/env-vars.md +22 -15
- package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +3 -2
- package/templates/.claude/skills/add-page/SKILL.md +241 -238
- package/templates/.claude/skills/add-page/references/page-types.md +85 -72
- package/templates/.claude/skills/add-page/scripts/site-pages.mjs +87 -0
- package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +99 -0
- package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +8 -18
- package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +43 -0
- package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +52 -0
- package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +38 -0
- package/templates/.claude/skills/check-site/SKILL.md +23 -0
- package/templates/.claude/skills/fill-page/SKILL.md +26 -7
- package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +1 -1
- package/templates/.claude/skills/setup-database/SKILL.md +156 -0
- package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +154 -0
- package/templates/.claude/skills/setup-deploy/SKILL.md +64 -32
- package/templates/.claude/skills/setup-deploy/references/env-vars-template.md +44 -36
- package/templates/.claude/skills/setup-deploy/references/runbook-template.md +58 -102
- package/templates/.claude/skills/update-page/SKILL.md +117 -0
- package/templates/.claude/skills/update-page/scripts/update-page.ts +640 -0
- package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +31 -0
- package/templates/.claude/skills/upgrade-plan/SKILL.md +12 -8
- package/templates/.github/workflows/ci.yml +4 -0
- package/templates/.prettierignore +1 -0
- package/templates/CLAUDE.md +146 -103
- package/templates/DESIGN.md +103 -6
- package/templates/README.md +63 -43
- package/templates/apps/api/.env.example +2 -1
- package/templates/apps/api/CLAUDE.md +3 -2
- package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +2 -0
- package/templates/apps/api/src/__tests__/server.test.ts +116 -0
- package/templates/apps/api/src/config/__tests__/index.test.ts +115 -14
- package/templates/apps/api/src/config/index.ts +35 -16
- package/templates/apps/api/src/lib/__tests__/lead-capture-store.test.ts +30 -0
- package/templates/apps/api/src/lib/__tests__/lead-delivery.test.ts +96 -0
- package/templates/apps/api/src/lib/lead-capture-store.ts +12 -0
- package/templates/apps/api/src/lib/lead-delivery.ts +52 -0
- package/templates/apps/api/src/lib/stripe.ts +9 -0
- package/templates/apps/api/src/middleware/__tests__/auth.optional-cookie.test.ts +140 -0
- package/templates/apps/api/src/middleware/auth.ts +54 -0
- package/templates/apps/api/src/openapi/spec.ts +63 -12
- package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +5 -2
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +628 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +222 -24
- package/templates/apps/api/src/routes/leads/__tests__/capture.test.ts +88 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +100 -0
- package/templates/apps/api/src/routes/leads/index.ts +46 -1
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +1 -1
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +5 -1
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +521 -20
- package/templates/apps/api/src/routes/webhooks/stripe.ts +124 -32
- package/templates/apps/api/src/server.ts +35 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +194 -0
- package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +124 -0
- package/templates/apps/api/src/services/__tests__/revalidation.test.ts +90 -15
- package/templates/apps/api/src/services/checkout-buyer.ts +72 -0
- package/templates/apps/api/src/services/lead-routing.ts +140 -30
- package/templates/apps/api/src/services/leads-inbox.ts +48 -11
- package/templates/apps/api/src/services/revalidation.ts +60 -15
- package/templates/apps/mcp/__tests__/parity.test.ts +5 -4
- package/templates/apps/mcp/__tests__/tools/create_project.test.ts +30 -24
- package/templates/apps/mcp/src/tools/create_project.ts +21 -6
- package/templates/apps/mcp/src/tools/purchase.ts +4 -2
- package/templates/apps/web/.env.example +13 -0
- package/templates/apps/web/CLAUDE.md +22 -28
- package/templates/apps/web/app/[locale]/(auth)/layout.tsx +1 -1
- package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +24 -0
- package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +17 -6
- package/templates/apps/web/app/[locale]/[slug]/[detail]/__tests__/page.test.tsx +110 -0
- package/templates/apps/web/app/[locale]/[slug]/[detail]/page.tsx +60 -0
- package/templates/apps/web/app/[locale]/[slug]/page.tsx +1 -1
- package/templates/apps/web/app/[locale]/alternatives/__tests__/page.test.tsx +161 -0
- package/templates/apps/web/app/[locale]/alternatives/page.tsx +104 -0
- package/templates/apps/web/app/[locale]/contact/ConversationalIntakeWrapper.tsx +14 -6
- package/templates/apps/web/app/[locale]/contact/__tests__/ConversationalIntakeWrapper.test.tsx +10 -9
- package/templates/apps/web/app/[locale]/contact/__tests__/contact-form-text.test.ts +32 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/contact.actions.test.ts +129 -0
- package/templates/apps/web/app/[locale]/contact/__tests__/page-renderer-migration.test.tsx +227 -84
- package/templates/apps/web/app/[locale]/contact/contact-form-text.ts +50 -0
- package/templates/apps/web/app/[locale]/contact/contact.actions.ts +73 -20
- package/templates/apps/web/app/[locale]/contact/page.tsx +105 -15
- package/templates/apps/web/app/[locale]/contact/site-contact-email.ts +54 -0
- package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +64 -0
- package/templates/apps/web/app/[locale]/features/page.tsx +52 -0
- package/templates/apps/web/app/[locale]/{use-cases → for}/[slug]/page.tsx +21 -5
- package/templates/apps/web/app/[locale]/for/__tests__/page-renderer-migration.test.tsx +73 -0
- package/templates/apps/web/app/[locale]/{use-cases → for}/page.tsx +8 -7
- package/templates/apps/web/app/[locale]/glossary/page.tsx +1 -1
- package/templates/apps/web/app/[locale]/layout.tsx +65 -17
- package/templates/apps/web/app/[locale]/newsletter/__tests__/newsletter.actions.test.ts +75 -0
- package/templates/apps/web/app/[locale]/newsletter/__tests__/page.test.tsx +163 -0
- package/templates/apps/web/app/[locale]/newsletter/newsletter.actions.ts +66 -0
- package/templates/apps/web/app/[locale]/newsletter/page.tsx +106 -14
- package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +59 -0
- package/templates/apps/web/app/[locale]/{book-a-call → portfolio}/page.tsx +12 -13
- package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +112 -0
- package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +70 -0
- package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +236 -44
- package/templates/apps/web/app/api/revalidate/route.ts +78 -36
- package/templates/apps/web/lib/__tests__/site-brand.test.ts +79 -0
- package/templates/apps/web/lib/__tests__/site-theme.test.ts +104 -11
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +21 -4
- package/templates/apps/web/lib/locale-guard.ts +18 -0
- package/templates/apps/web/lib/meet-placeholder.ts +5 -0
- package/templates/apps/web/lib/nav-config.ts +50 -37
- package/templates/apps/web/lib/site-brand.tsx +13 -9
- package/templates/apps/web/lib/site-identity.ts +14 -0
- package/templates/apps/web/lib/site-logo.tsx +36 -0
- package/templates/apps/web/lib/site-theme.ts +46 -26
- package/templates/apps/web/messages/en.json +45 -5
- package/templates/apps/web/middleware.ts +28 -4
- package/templates/content/_site.mdx +4 -2
- package/templates/content/en/BlogList/blog.mdx +37 -16
- package/templates/content/en/BookCall/book-a-call.mdx +80 -0
- package/templates/content/en/BookCall/onsite-estimate.mdx +56 -0
- package/templates/content/en/BookCall/onsite-service.mdx +56 -0
- package/templates/content/en/BookCall/start-project.mdx +56 -0
- package/templates/content/en/ContactPage/contact.mdx +43 -34
- package/templates/content/en/HomePage/home.mdx +10 -22
- package/templates/content/en/LandingPage/meet.mdx +59 -0
- package/templates/content/en/PurchasePolicyPage/purchase-policy.mdx +0 -1
- package/templates/content/en/UseCasesList/{use-cases.mdx → for.mdx} +19 -18
- package/templates/database/CHANGELOG.md +14 -0
- package/templates/database/package.json +1 -1
- package/templates/package.json +2 -1
- package/templates/tools/check-claude-md.ts +128 -0
- package/versions.json +33 -33
- package/site-templates/_base/content/en/BookCall/book-call.mdx +0 -53
- package/site-templates/_base/content/en/UseCase/first-use-case.mdx +0 -23
- package/site-templates/_base/content/en/UseCase/second-use-case.mdx +0 -23
- package/site-templates/_base/content/en/UseCase/third-use-case.mdx +0 -23
- package/site-templates/minimalism-site/DESIGN.md +0 -162
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +0 -470
- package/site-templates/minimalism-site/ailk-template.json +0 -23
- package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +0 -110
- package/site-templates/minimalism-site/content/en/BookCall/book-call.mdx +0 -53
- package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +0 -34
- package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +0 -57
- package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +0 -77
- package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +0 -73
- package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +0 -52
- package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +0 -52
- package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +0 -52
- package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +0 -52
- package/site-templates/minimalism-site/flows/referral.flow.json +0 -71
- package/site-templates/minimalism-site/provenance.json +0 -4
- package/site-templates/simple-service/DESIGN.md +0 -162
- package/site-templates/simple-service/TEMPLATE-MANIFEST.md +0 -333
- package/site-templates/simple-service/ailk-template.json +0 -11
- package/site-templates/simple-service/content/en/BookCall/book-call.mdx +0 -53
- package/site-templates/simple-service/content/en/ContactPage/contact.mdx +0 -32
- package/site-templates/simple-service/content/en/FAQPage/faq.mdx +0 -56
- package/site-templates/simple-service/content/en/HomePage/home.mdx +0 -85
- package/site-templates/simple-service/content/en/Service/landscape-design.mdx +0 -40
- package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +0 -40
- package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +0 -40
- package/site-templates/simple-service/provenance.json +0 -4
- package/templates/.claude/skills/add-page/templates/route.tsx.tmpl +0 -28
- package/templates/apps/web/app/[locale]/contact/ContactForm.tsx +0 -211
- package/templates/apps/web/app/[locale]/contact/__tests__/ContactForm.test.tsx +0 -96
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +0 -72
- package/templates/content/en/SoftwareProduct/product.mdx +0 -175
- /package/site-templates/{minimalism-site → designs/minimalism/sample}/content/en/HomePage/home.mdx +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-1.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-2.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-3.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-4.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-5.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/avatar-placeholder-6.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/hero-backdrop.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-1.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-2.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/logo-placeholder-3.svg +0 -0
- /package/site-templates/{minimalism-site/assets → designs/minimalism/sample/public}/wordmark-placeholder.svg +0 -0
- /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/first-engagement.mdx +0 -0
- /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/second-engagement.mdx +0 -0
- /package/site-templates/{minimalism-site → shapes/organization-service}/content/en/Service/third-engagement.mdx +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "PortfolioList"
|
|
3
|
+
slug: "portfolio"
|
|
4
|
+
title: "{Before and after, compared} | {Your Name}"
|
|
5
|
+
description: "{Every project shown as a comparison — what the client had, what they have now, and what changed in between.}"
|
|
6
|
+
sections:
|
|
7
|
+
[
|
|
8
|
+
{
|
|
9
|
+
"id": "cases-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"data":
|
|
12
|
+
{
|
|
13
|
+
"variant": "default",
|
|
14
|
+
"size": "display",
|
|
15
|
+
"surface": "wash-secondary",
|
|
16
|
+
"gapBelow": "tight",
|
|
17
|
+
"eyebrow": "{Portfolio}",
|
|
18
|
+
"eyebrowTone": "brand",
|
|
19
|
+
"headline": "{My work, before and after.}",
|
|
20
|
+
"subheadline": "{Two or three sentences on why the comparison is the honest proof — what the before cost the client, what the after changed, and how a reader can check it.}",
|
|
21
|
+
"subtitleSize": "lead",
|
|
22
|
+
"ctaSize": "xl",
|
|
23
|
+
"primaryCta":
|
|
24
|
+
{ "label": "{Book a call}", "href": "/meet/book-a-call" },
|
|
25
|
+
"secondaryCta": { "label": "{Get in touch}", "href": "/contact" },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "cases-tiles",
|
|
30
|
+
"type": "items",
|
|
31
|
+
"data":
|
|
32
|
+
{
|
|
33
|
+
"variant": "tile",
|
|
34
|
+
"tileHover": "outline",
|
|
35
|
+
"columns": 2,
|
|
36
|
+
"surface": "none",
|
|
37
|
+
"items":
|
|
38
|
+
[
|
|
39
|
+
{
|
|
40
|
+
"title": "{Example one}: before and after",
|
|
41
|
+
"description": "{One sentence on what example one had, and what they have now}",
|
|
42
|
+
"rows":
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
"label": "THE CLIENT",
|
|
46
|
+
"body": "{Who they are and the market they sell into}",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"label": "WHAT CHANGED",
|
|
50
|
+
"body": "{The one thing the after does that the before could not}",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
"link":
|
|
54
|
+
{
|
|
55
|
+
"label": "See the comparison →",
|
|
56
|
+
"href": "/portfolio/sample-one",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"title": "{Example two}: before and after",
|
|
61
|
+
"description": "{One sentence on what example two had, and what they have now}",
|
|
62
|
+
"rows":
|
|
63
|
+
[
|
|
64
|
+
{
|
|
65
|
+
"label": "THE CLIENT",
|
|
66
|
+
"body": "{Who they are and the market they sell into}",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"label": "WHAT CHANGED",
|
|
70
|
+
"body": "{The one thing the after does that the before could not}",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
"link":
|
|
74
|
+
{
|
|
75
|
+
"label": "See the comparison →",
|
|
76
|
+
"href": "/portfolio/sample-two",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"title": "{Example three}: before and after",
|
|
81
|
+
"description": "{One sentence on what example three had, and what they have now}",
|
|
82
|
+
"rows":
|
|
83
|
+
[
|
|
84
|
+
{
|
|
85
|
+
"label": "THE CLIENT",
|
|
86
|
+
"body": "{Who they are and the market they sell into}",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"label": "WHAT CHANGED",
|
|
90
|
+
"body": "{The one thing the after does that the before could not}",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
"link":
|
|
94
|
+
{
|
|
95
|
+
"label": "See the comparison →",
|
|
96
|
+
"href": "/portfolio/sample-three",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"title": "{Example four}: before and after",
|
|
101
|
+
"description": "{One sentence on what example four had, and what they have now}",
|
|
102
|
+
"rows":
|
|
103
|
+
[
|
|
104
|
+
{
|
|
105
|
+
"label": "THE CLIENT",
|
|
106
|
+
"body": "{Who they are and the market they sell into}",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"label": "WHAT CHANGED",
|
|
110
|
+
"body": "{The one thing the after does that the before could not}",
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
"link":
|
|
114
|
+
{
|
|
115
|
+
"label": "See the comparison →",
|
|
116
|
+
"href": "/portfolio/sample-four",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "cases-close",
|
|
124
|
+
"type": "cta",
|
|
125
|
+
"data":
|
|
126
|
+
{
|
|
127
|
+
"variant": "beam",
|
|
128
|
+
"headline": "{Is your project the before or the after?}",
|
|
129
|
+
"description": "{One line offering the reader the same comparison for their own project.}",
|
|
130
|
+
"primaryCta":
|
|
131
|
+
{ "label": "{Book a call}", "href": "/meet/book-a-call" },
|
|
132
|
+
"secondaryCta": { "label": "{Get in touch}", "href": "/contact" },
|
|
133
|
+
"chips":
|
|
134
|
+
[
|
|
135
|
+
"{Proof you can check}",
|
|
136
|
+
"{Every project shown both ways}",
|
|
137
|
+
"{Re-checked every quarter}",
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"id": "cases-faq",
|
|
143
|
+
"type": "faq",
|
|
144
|
+
"data":
|
|
145
|
+
{
|
|
146
|
+
"headline": "Frequently Asked Questions",
|
|
147
|
+
"variant": "centered",
|
|
148
|
+
"presentation": "accordion",
|
|
149
|
+
"questionSize": "body-lg",
|
|
150
|
+
"initialOpen": "first",
|
|
151
|
+
"containerWidth": "default",
|
|
152
|
+
"surface": "gray-100",
|
|
153
|
+
"items":
|
|
154
|
+
[
|
|
155
|
+
{
|
|
156
|
+
"question": "{How do you pick which projects to show?}",
|
|
157
|
+
"answer": "{Two or three sentences.}",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"question": "{Are the before screenshots real?}",
|
|
161
|
+
"answer": "{Two or three sentences.}",
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"question": "{Can I see the numbers behind a comparison?}",
|
|
165
|
+
"answer": "{Two or three sentences.}",
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
]
|
|
171
|
+
---
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
type: "PurchasePolicyPage"
|
|
3
3
|
slug: "purchase-policy"
|
|
4
4
|
title: "Purchase Policy"
|
|
5
|
-
description: "How cancellations, reschedules and refunds work for
|
|
6
|
-
placeholder: true
|
|
5
|
+
description: "How cancellations, reschedules and refunds work for engagements booked on this site. Placeholder policy — replace every section before you launch."
|
|
7
6
|
sections:
|
|
8
7
|
[
|
|
9
8
|
{
|
|
@@ -24,11 +23,11 @@ sections:
|
|
|
24
23
|
[
|
|
25
24
|
{
|
|
26
25
|
"kind": "paragraph",
|
|
27
|
-
"text": "This page is starter content that shipped with your site. It is not a purchase policy, it makes no commitment on behalf of Your
|
|
26
|
+
"text": "This page is starter content that shipped with your site. It is not a purchase policy, it makes no commitment on behalf of Your Name, and it is not legal advice. Replace every section with the policy you actually operate, and have someone qualified read it before you publish.",
|
|
28
27
|
},
|
|
29
28
|
{
|
|
30
29
|
"kind": "paragraph",
|
|
31
|
-
"text": "This section explains how cancellations and reschedules work for
|
|
30
|
+
"text": "This section explains how cancellations and reschedules work for engagements booked on this site. The headings are the ones a client and an agent both look for, so keep them and fill in your own terms.",
|
|
32
31
|
},
|
|
33
32
|
],
|
|
34
33
|
"subsections":
|
|
@@ -40,7 +39,7 @@ sections:
|
|
|
40
39
|
[
|
|
41
40
|
{
|
|
42
41
|
"kind": "paragraph",
|
|
43
|
-
"text": "State the notice period in hours before the
|
|
42
|
+
"text": "State the notice period in hours before the session, and say how it is measured. A client reading at midnight should be able to work out, without arithmetic you have not shown them, whether they are still inside it.",
|
|
44
43
|
},
|
|
45
44
|
],
|
|
46
45
|
},
|
|
@@ -62,18 +61,18 @@ sections:
|
|
|
62
61
|
[
|
|
63
62
|
{
|
|
64
63
|
"kind": "paragraph",
|
|
65
|
-
"text": "Say what a late cancellation costs and what a no-show costs, as a figure or a share of the
|
|
64
|
+
"text": "Say what a late cancellation costs and what a no-show costs, as a figure or a share of the engagement, and when each is charged. If you hold a deposit, say what happens to it in each case.",
|
|
66
65
|
},
|
|
67
66
|
],
|
|
68
67
|
},
|
|
69
68
|
{
|
|
70
69
|
"id": "our-cancellations",
|
|
71
|
-
"heading": "If
|
|
70
|
+
"heading": "If I cancel",
|
|
72
71
|
"blocks":
|
|
73
72
|
[
|
|
74
73
|
{
|
|
75
74
|
"kind": "paragraph",
|
|
76
|
-
"text": "Set out what a
|
|
75
|
+
"text": "Set out what a client gets if you cancel or move a session — a full refund, a rebooking, or both — and how quickly you tell them. A policy that only binds one side reads as one.",
|
|
77
76
|
},
|
|
78
77
|
],
|
|
79
78
|
},
|
|
@@ -84,7 +83,7 @@ sections:
|
|
|
84
83
|
[
|
|
85
84
|
{
|
|
86
85
|
"kind": "paragraph",
|
|
87
|
-
"text": "Name the circumstances in which you waive a fee — illness, bereavement, severe weather — and say what you need from the
|
|
86
|
+
"text": "Name the circumstances in which you waive a fee — illness, bereavement, severe weather — and say what you need from the client to apply the waiver. Vague discretion is worse for you than a short written list.",
|
|
88
87
|
},
|
|
89
88
|
],
|
|
90
89
|
},
|
|
@@ -97,7 +96,7 @@ sections:
|
|
|
97
96
|
[
|
|
98
97
|
{
|
|
99
98
|
"kind": "paragraph",
|
|
100
|
-
"text": "Say what a
|
|
99
|
+
"text": "Say what a client gets back after a cancellation — the session price, the deposit, or both, and how long the refund takes to reach the payment method it came from. If you offer credit toward a future engagement instead, describe when that applies.",
|
|
101
100
|
},
|
|
102
101
|
],
|
|
103
102
|
"subsections":
|
|
@@ -109,7 +108,7 @@ sections:
|
|
|
109
108
|
[
|
|
110
109
|
{
|
|
111
110
|
"kind": "paragraph",
|
|
112
|
-
"text": "Point to the one place a
|
|
111
|
+
"text": "Point to the one place a client should write, and say roughly how quickly you answer. A policy nobody can ask a question about is a policy that generates disputes.",
|
|
113
112
|
},
|
|
114
113
|
],
|
|
115
114
|
},
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "Service"
|
|
3
|
+
slug: "first-engagement"
|
|
4
|
+
title: "{First engagement}"
|
|
5
|
+
description: "{One line on what this engagement is and who it suits. Replace before you launch.}"
|
|
6
|
+
schema:
|
|
7
|
+
serviceType: "{First engagement}"
|
|
8
|
+
provider:
|
|
9
|
+
"@type": Person
|
|
10
|
+
name: "Your Name"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# {First engagement}
|
|
14
|
+
|
|
15
|
+
{Open with the situation a reader is in when they come looking for this. Two or
|
|
16
|
+
three sentences, no more — the detail belongs under the headings below.}
|
|
17
|
+
|
|
18
|
+
## What it covers
|
|
19
|
+
|
|
20
|
+
- {The first thing you actually do}
|
|
21
|
+
- {The second thing you actually do}
|
|
22
|
+
- {The third thing you actually do}
|
|
23
|
+
|
|
24
|
+
## How it runs
|
|
25
|
+
|
|
26
|
+
{One paragraph on the shape of the engagement: how it starts, how long it runs,
|
|
27
|
+
who is involved, and what a week looks like.}
|
|
28
|
+
|
|
29
|
+
## What you end up with
|
|
30
|
+
|
|
31
|
+
{One paragraph on the deliverable. Be concrete — name the artefact, not the
|
|
32
|
+
feeling.}
|
|
33
|
+
|
|
34
|
+
## What it costs
|
|
35
|
+
|
|
36
|
+
{One line on the pricing shape — fixed fee, retainer, day rate — and what it
|
|
37
|
+
excludes. Replace with your real numbers, or delete this section and let the
|
|
38
|
+
call do it.}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "Service"
|
|
3
|
+
slug: "second-engagement"
|
|
4
|
+
title: "{Second engagement}"
|
|
5
|
+
description: "{One line on what this engagement is and who it suits. Replace before you launch.}"
|
|
6
|
+
schema:
|
|
7
|
+
serviceType: "{Second engagement}"
|
|
8
|
+
provider:
|
|
9
|
+
"@type": Person
|
|
10
|
+
name: "Your Name"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# {Second engagement}
|
|
14
|
+
|
|
15
|
+
{Open with the situation a reader is in when they come looking for this. Two or
|
|
16
|
+
three sentences, no more — the detail belongs under the headings below.}
|
|
17
|
+
|
|
18
|
+
## What it covers
|
|
19
|
+
|
|
20
|
+
- {The first thing you actually do}
|
|
21
|
+
- {The second thing you actually do}
|
|
22
|
+
- {The third thing you actually do}
|
|
23
|
+
|
|
24
|
+
## How it runs
|
|
25
|
+
|
|
26
|
+
{One paragraph on the shape of the engagement: how it starts, how long it runs,
|
|
27
|
+
who is involved, and what a week looks like.}
|
|
28
|
+
|
|
29
|
+
## What you end up with
|
|
30
|
+
|
|
31
|
+
{One paragraph on the deliverable. Be concrete — name the artefact, not the
|
|
32
|
+
feeling.}
|
|
33
|
+
|
|
34
|
+
## What it costs
|
|
35
|
+
|
|
36
|
+
{One line on the pricing shape — fixed fee, retainer, day rate — and what it
|
|
37
|
+
excludes. Replace with your real numbers, or delete this section and let the
|
|
38
|
+
call do it.}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: "Service"
|
|
3
|
+
slug: "third-engagement"
|
|
4
|
+
title: "{Third engagement}"
|
|
5
|
+
description: "{One line on what this engagement is and who it suits. Replace before you launch.}"
|
|
6
|
+
schema:
|
|
7
|
+
serviceType: "{Third engagement}"
|
|
8
|
+
provider:
|
|
9
|
+
"@type": Person
|
|
10
|
+
name: "Your Name"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# {Third engagement}
|
|
14
|
+
|
|
15
|
+
{Open with the situation a reader is in when they come looking for this. Two or
|
|
16
|
+
three sentences, no more — the detail belongs under the headings below.}
|
|
17
|
+
|
|
18
|
+
## What it covers
|
|
19
|
+
|
|
20
|
+
- {The first thing you actually do}
|
|
21
|
+
- {The second thing you actually do}
|
|
22
|
+
- {The third thing you actually do}
|
|
23
|
+
|
|
24
|
+
## How it runs
|
|
25
|
+
|
|
26
|
+
{One paragraph on the shape of the engagement: how it starts, how long it runs,
|
|
27
|
+
who is involved, and what a week looks like.}
|
|
28
|
+
|
|
29
|
+
## What you end up with
|
|
30
|
+
|
|
31
|
+
{One paragraph on the deliverable. Be concrete — name the artefact, not the
|
|
32
|
+
feeling.}
|
|
33
|
+
|
|
34
|
+
## What it costs
|
|
35
|
+
|
|
36
|
+
{One line on the pricing shape — fixed fee, retainer, day rate — and what it
|
|
37
|
+
excludes. Replace with your real numbers, or delete this section and let the
|
|
38
|
+
call do it.}
|
package/site-templates/{simple-service → shapes/person-service}/content/en/ServicesList/services.mdx
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type: "ServicesList"
|
|
3
3
|
slug: "services"
|
|
4
4
|
title: "Services"
|
|
5
|
-
description: "The three
|
|
5
|
+
description: "The three engagements {Your Name} offers. Placeholder copy — replace before you launch."
|
|
6
6
|
sections:
|
|
7
7
|
[
|
|
8
8
|
{
|
|
@@ -12,44 +12,44 @@ sections:
|
|
|
12
12
|
{
|
|
13
13
|
"variant": "centered",
|
|
14
14
|
"eyebrow": "Services",
|
|
15
|
-
"headline": "Three
|
|
15
|
+
"headline": "Three ways to work together",
|
|
16
16
|
"subheadline": "{One line on how to choose between them. Name the question a reader is actually asking.}",
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
|
-
"id": "
|
|
20
|
+
"id": "engagements",
|
|
21
21
|
"type": "items",
|
|
22
22
|
"data":
|
|
23
23
|
{
|
|
24
|
-
"headline": "
|
|
24
|
+
"headline": "Engagements",
|
|
25
25
|
"columns": 3,
|
|
26
26
|
"items":
|
|
27
27
|
[
|
|
28
28
|
{
|
|
29
|
-
"title": "{
|
|
30
|
-
"description": "{One line on
|
|
29
|
+
"title": "{First engagement}",
|
|
30
|
+
"description": "{One line on what it is and who it suits.}",
|
|
31
31
|
"link":
|
|
32
32
|
{
|
|
33
33
|
"label": "Read more",
|
|
34
|
-
"href": "/services/
|
|
34
|
+
"href": "/services/first-engagement",
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
|
-
"title": "{
|
|
39
|
-
"description": "{One line on
|
|
38
|
+
"title": "{Second engagement}",
|
|
39
|
+
"description": "{One line on what it is and who it suits.}",
|
|
40
40
|
"link":
|
|
41
41
|
{
|
|
42
42
|
"label": "Read more",
|
|
43
|
-
"href": "/services/
|
|
43
|
+
"href": "/services/second-engagement",
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
|
-
"title": "{
|
|
48
|
-
"description": "{One line on
|
|
47
|
+
"title": "{Third engagement}",
|
|
48
|
+
"description": "{One line on what it is and who it suits.}",
|
|
49
49
|
"link":
|
|
50
50
|
{
|
|
51
51
|
"label": "Read more",
|
|
52
|
-
"href": "/services/
|
|
52
|
+
"href": "/services/third-engagement",
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
],
|
|
@@ -62,11 +62,11 @@ sections:
|
|
|
62
62
|
{
|
|
63
63
|
"variant": "minimal",
|
|
64
64
|
"headline": "Not sure which one?",
|
|
65
|
-
"description": "{One line inviting the reader to
|
|
66
|
-
"primaryCta": { "label": "Book a
|
|
65
|
+
"description": "{One line inviting the reader to ask instead of guessing.}",
|
|
66
|
+
"primaryCta": { "label": "Book a call", "href": "/meet/book-a-call" },
|
|
67
67
|
},
|
|
68
68
|
},
|
|
69
69
|
]
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
Placeholder copy. The three detail pages under `content/en/Service/` carry the long form
|
|
72
|
+
Placeholder copy. The three detail pages under `content/en/Service/` carry the long form; this page is the chooser.
|
|
@@ -61,6 +61,13 @@ These never appear in source code:
|
|
|
61
61
|
and future prefixes included, by being absent from the list rather than
|
|
62
62
|
by being named on a ban-list. Live keys live in your deployment
|
|
63
63
|
platform's secrets store, never in source files or `.env`.
|
|
64
|
+
`@working-theory/stripe-client` does export one opt-in,
|
|
65
|
+
`admitLiveRestrictedKey()`: a server process that calls it once at
|
|
66
|
+
startup lets `getStripeClient()` accept a restricted live key
|
|
67
|
+
(`rk_live_`) — never `sk_live_` or `pk_live_`. Nothing in this site
|
|
68
|
+
calls it, so the default refusal stands; calling it is a deliberate
|
|
69
|
+
go-live decision, and `assertSandboxKey()` stays sandbox-only even
|
|
70
|
+
then.
|
|
64
71
|
- Direct vendor SDK imports outside the wrapper packages
|
|
65
72
|
(`import 'resend'` outside `@working-theory/email`, etc.).
|
|
66
73
|
- Hardcoded production database URLs in committed files.
|
|
@@ -4,16 +4,18 @@ Skills are reusable Claude Code workflows scoped to this project. Each
|
|
|
4
4
|
lives in its own subdirectory with a `SKILL.md` describing when to use
|
|
5
5
|
it and how it works.
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The eight skills below ship with this project. Claude Code discovers
|
|
8
8
|
them automatically at session start — nothing to install or enable.
|
|
9
9
|
|
|
10
10
|
## Available skills
|
|
11
11
|
|
|
12
12
|
| Skill | Purpose |
|
|
13
13
|
| -------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
14
|
-
| `add-page` |
|
|
14
|
+
| `add-page` | Add a page this site can serve — its content file, structured data and nav link — adding a missing route with `create-ailk add-route` first. Also documents the `schema:` frontmatter override for any page. |
|
|
15
|
+
| `update-page` | Rename a page — give it a new URL and/or a new title — in one plan-then-confirm pass: its content files, its own route folder, exact internal links and the manifest row move together, and the old URL gets a permanent redirect. |
|
|
15
16
|
| `add-auth` | Activate auth providers — magic-link via Resend, Google OAuth, GitHub OAuth. |
|
|
16
|
-
| `setup-deploy` | Emit deploy configuration — `vercel.json`, `.env.example`, and `RUNBOOK.md` — for a Vercel deploy.
|
|
17
|
+
| `setup-deploy` | Emit deploy configuration — `vercel.json`, `.env.example`, and `RUNBOOK.md` — for a Vercel deploy. Asks where leads go (email or a database) and warns when neither is set. |
|
|
18
|
+
| `setup-database` | Take the site from no database to a working lead inbox: provision Postgres, create the tables, pin the owner, and verify one test message lands in `/leads`. |
|
|
17
19
|
| `check-site` | Run `ailk-audit --json` and explain the score and findings in plain language. |
|
|
18
20
|
| `fill-page` | Fill one page's section content from a category profile: labelled sample content (tier 1) or your own first draft from a short intake (tier 2). |
|
|
19
21
|
| `upgrade-plan` | Compare Free, Pro, Pro Plus, Agency and the commerce add-on side by side, with the prices the public pricing page publishes right now, and recommend one option for this site with a reason. |
|
|
@@ -8,35 +8,43 @@ The activation logic lives in `apps/web/lib/auth-env.ts` →
|
|
|
8
8
|
`getActiveProviderIds()`. A provider is active **only when every
|
|
9
9
|
required var is set to a non-empty value**. Partial wiring (e.g.,
|
|
10
10
|
`GOOGLE_CLIENT_ID` set but `GOOGLE_CLIENT_SECRET` missing) is treated
|
|
11
|
-
as inactive —
|
|
11
|
+
as inactive — `apps/web/auth.ts` never constructs that provider.
|
|
12
|
+
|
|
13
|
+
The site's auth library is **Better Auth** (`apps/web/auth.ts`,
|
|
14
|
+
`betterAuth({ secret, baseURL, socialProviders, … })`).
|
|
12
15
|
|
|
13
16
|
## Provider activation table
|
|
14
17
|
|
|
15
18
|
| Provider ID | Required env vars | Source |
|
|
16
19
|
| ----------- | -------------------------------------------- | ---------------------------- |
|
|
17
|
-
| `email` | `AUTH_EMAIL_SERVER` + `AUTH_EMAIL_FROM` |
|
|
20
|
+
| `email` | `AUTH_EMAIL_SERVER` + `AUTH_EMAIL_FROM` | Email sign-in (Resend)¹ |
|
|
18
21
|
| `google` | `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` | Google OAuth |
|
|
19
22
|
| `github` | `GITHUB_CLIENT_ID` + `GITHUB_CLIENT_SECRET` | GitHub OAuth |
|
|
20
23
|
|
|
24
|
+
¹ Better Auth core ships no magic-link provider, so `email` is an
|
|
25
|
+
env-presence signal: it switches on the password method
|
|
26
|
+
(`emailAndPassword`) in `apps/web/auth.ts`, not a wired magic link.
|
|
27
|
+
|
|
21
28
|
## Auxiliary auth env vars
|
|
22
29
|
|
|
23
30
|
| Var | Default | Effect |
|
|
24
31
|
| ---------------------- | ------- | ------------------------------------------------------------------------------------- |
|
|
25
|
-
| `AILK_AUTH_REQUIRED` | unset |
|
|
26
|
-
| `
|
|
27
|
-
| `
|
|
32
|
+
| `AILK_AUTH_REQUIRED` | unset | Read by `isAuthRequired()` in `apps/web/lib/auth-env.ts` (`"1"` or `"true"`). Default is auth-disabled / public, so a fresh scaffold boots without requiring any auth wiring. |
|
|
33
|
+
| `BETTER_AUTH_URL` | unset | The site's public origin (e.g. `https://your-domain.com`). Better Auth builds OAuth callback URLs on it and it is the one trusted origin; unset, Better Auth derives both from each request. Set it in production. Local dev can leave it unset. |
|
|
34
|
+
| `BETTER_AUTH_SECRET` | unset | Signs session cookies and email-verification tokens. **Required in production** — `apps/web/auth.ts` throws when it is unset there, rather than fall back to the development secret published in the source. Generate with `openssl rand -base64 32`. Optional for `next dev`. |
|
|
28
35
|
|
|
29
36
|
The skill writes none of these auxiliary vars on its own. It mentions
|
|
30
37
|
them in the closing summary so the consumer is aware:
|
|
31
38
|
|
|
32
39
|
- `AILK_AUTH_REQUIRED` is the consumer's call (skill always defaults
|
|
33
40
|
to leaving it unset).
|
|
34
|
-
- `
|
|
35
|
-
setup (`setup-deploy`
|
|
41
|
+
- `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET` are deferred to
|
|
42
|
+
production-time setup (`setup-deploy`), and a production deploy
|
|
43
|
+
fails without `BETTER_AUTH_SECRET`.
|
|
36
44
|
|
|
37
45
|
## Env-var formats — what valid values look like
|
|
38
46
|
|
|
39
|
-
### `AUTH_EMAIL_SERVER` (
|
|
47
|
+
### `AUTH_EMAIL_SERVER` (email sign-in via Resend)
|
|
40
48
|
|
|
41
49
|
```
|
|
42
50
|
smtp://resend:<RESEND_API_KEY>@smtp.resend.com:465
|
|
@@ -46,7 +54,7 @@ The Resend API key starts with `re_`. The literal username is the
|
|
|
46
54
|
string `resend` (Resend's SMTP convention). Port 465 is implicit-TLS
|
|
47
55
|
SMTP.
|
|
48
56
|
|
|
49
|
-
### `AUTH_EMAIL_FROM` (
|
|
57
|
+
### `AUTH_EMAIL_FROM` (email sign-in via Resend)
|
|
50
58
|
|
|
51
59
|
A verified sender address on the consumer's Resend account. For
|
|
52
60
|
development, `onboarding@resend.dev` works without verification.
|
|
@@ -73,7 +81,7 @@ The skill's Step 1 menu marks providers as `[x]` when both required
|
|
|
73
81
|
vars are set in `.env.local`. The detection is presence-only — the
|
|
74
82
|
skill does not validate that the values actually work (no Google
|
|
75
83
|
API ping, no GitHub API ping, no test SMTP connection). A consumer
|
|
76
|
-
who pasted typos will get a runtime auth error from
|
|
84
|
+
who pasted typos will get a runtime auth error from Better Auth on
|
|
77
85
|
their first sign-in attempt; the fix is to re-run the skill and
|
|
78
86
|
overwrite.
|
|
79
87
|
|
|
@@ -81,11 +89,10 @@ overwrite.
|
|
|
81
89
|
|
|
82
90
|
- `apps/web/lib/auth-env.ts` — `getActiveProviderIds()` and
|
|
83
91
|
`isAuthRequired()`.
|
|
84
|
-
- `apps/web/auth.
|
|
85
|
-
active-provider list and
|
|
86
|
-
the matching env vars
|
|
87
|
-
|
|
88
|
-
redirect unauthenticated users.
|
|
92
|
+
- `apps/web/auth.ts` — `buildSocialProviders()` consumes the
|
|
93
|
+
active-provider list and builds Better Auth's `socialProviders`
|
|
94
|
+
from the matching env vars; `resolveSecret()` reads
|
|
95
|
+
`BETTER_AUTH_SECRET`, and `baseURL` is `BETTER_AUTH_URL`.
|
|
89
96
|
|
|
90
97
|
The skill never modifies any of those files. All activation is
|
|
91
98
|
env-var-driven.
|
|
@@ -62,7 +62,7 @@ Google sign-in is activated when both env vars are present in
|
|
|
62
62
|
2. If you haven't yet, configure the OAuth consent screen:
|
|
63
63
|
- User type: **External** (unless you're inside a Workspace org).
|
|
64
64
|
- Fill in app name, support email, and developer contact email.
|
|
65
|
-
- Scopes are
|
|
65
|
+
- Scopes are requested by Better Auth at runtime — leave the
|
|
66
66
|
consent screen scope list empty.
|
|
67
67
|
3. Click **Create Credentials → OAuth client ID**.
|
|
68
68
|
4. Application type: **Web application**.
|
|
@@ -158,7 +158,8 @@ The Client ID stays the same.
|
|
|
158
158
|
|
|
159
159
|
A provider is **active** when both required env vars are set in
|
|
160
160
|
`.env.local`. The provider list is computed at server startup from env
|
|
161
|
-
vars only
|
|
161
|
+
vars only (`getActiveProviderIds()` in `apps/web/lib/auth-env.ts`) — there
|
|
162
|
+
are no `apps/web/auth.ts` edits to make.
|
|
162
163
|
|
|
163
164
|
To require sign-in for protected routes, set in `.env.local`:
|
|
164
165
|
|