create-ailk 0.8.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 +68 -0
- package/component-catalog.json +279 -45
- 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 +92 -4
- 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/license-key-files.d.ts +9 -0
- package/dist/lib/license-key-files.js +2 -2
- package/dist/lib/module-license-gate.d.ts +19 -9
- package/dist/lib/module-license-gate.js +19 -8
- 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 +12 -2
- package/dist/parse-args.js +74 -13
- package/dist/programmatic.d.ts +30 -6
- package/dist/programmatic.js +206 -17
- 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 +141 -8
- package/dist/starter-grid.d.ts +32 -16
- package/dist/starter-grid.js +129 -33
- package/dist/surfaces.d.ts +41 -9
- package/dist/surfaces.js +200 -83
- package/dist/template-manifest.d.ts +30 -13
- package/dist/template-manifest.js +49 -24
- package/package.json +5 -4
- package/site-templates/_base/content/en/UseCase/persona-1.mdx +7 -6
- package/site-templates/_base/content/en/UseCase/persona-2.mdx +7 -6
- package/site-templates/_base/content/en/UseCase/persona-3.mdx +7 -6
- 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 +98 -6
- package/site-templates/marketing-site/DESIGN.md +98 -6
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +60 -27
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +50 -30
- package/site-templates/marketing-site-free/DESIGN.md +98 -6
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +60 -24
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +44 -27
- package/site-templates/marketing-site-free/ailk-template.json +1 -1
- package/site-templates/saas-product/DESIGN.md +98 -6
- package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.json +127 -18
- package/site-templates/shapes/local-business-service/TEMPLATE-MANIFEST.md +74 -20
- package/site-templates/shapes/local-business-service/ailk-template.json +1 -1
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.json +127 -18
- package/site-templates/shapes/organization-service/TEMPLATE-MANIFEST.md +74 -20
- package/site-templates/shapes/organization-service/ailk-template.json +1 -1
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.json +127 -18
- package/site-templates/shapes/person-service/TEMPLATE-MANIFEST.md +75 -21
- package/site-templates/shapes/person-service/ailk-template.json +1 -1
- package/site-templates/shapes/person-service/content/en/AboutPage/about.mdx +1 -1
- package/site-templates/shapes/person-service/content/en/HomePage/home.mdx +2 -2
- package/site-templates/shapes/person-service/content/en/PortfolioList/portfolio.mdx +4 -2
- package/site-templates/shapes/person-service/content/en/ServicesList/services.mdx +1 -1
- package/templates/.claude/rules/architecture.md +7 -0
- package/templates/.claude/skills/README.md +3 -2
- 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 -76
- 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-deploy/references/env-vars-template.md +28 -11
- 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 +98 -6
- package/templates/README.md +50 -38
- package/templates/apps/api/.env.example +2 -1
- 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/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/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/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 +28 -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/revalidation.ts +60 -15
- package/templates/apps/mcp/__tests__/tools/create_project.test.ts +30 -24
- 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]/{use-cases → for}/[slug]/page.tsx +4 -3
- 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 +35 -19
- package/templates/apps/web/app/[locale]/newsletter/page.tsx +1 -1
- package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +1 -1
- package/templates/apps/web/app/[locale]/portfolio/page.tsx +1 -1
- 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 +14 -13
- package/templates/apps/web/lib/site-brand.tsx +13 -9
- 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 +23 -9
- package/templates/apps/web/middleware.ts +28 -4
- 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 +40 -1
- package/templates/content/en/HomePage/home.mdx +2 -6
- package/templates/content/en/LandingPage/meet.mdx +59 -0
- package/templates/content/en/UseCasesList/{use-cases.mdx → for.mdx} +19 -18
- package/templates/database/CHANGELOG.md +7 -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 -52
- package/site-templates/minimalism-site/DESIGN.md +0 -162
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +0 -458
- 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 -52
- 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/PurchasePolicyPage/purchase-policy.mdx +0 -123
- 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/content/en/Service/first-engagement.mdx +0 -38
- package/site-templates/minimalism-site/content/en/Service/second-engagement.mdx +0 -38
- package/site-templates/minimalism-site/content/en/Service/third-engagement.mdx +0 -38
- package/site-templates/minimalism-site/content/en/ServicesList/services.mdx +0 -73
- package/site-templates/minimalism-site/flows/referral.flow.json +0 -71
- package/site-templates/minimalism-site/provenance.json +0 -4
- package/templates/.claude/skills/add-page/templates/route.tsx.tmpl +0 -28
- package/templates/apps/web/app/[locale]/book-a-call/page.tsx +0 -50
- package/templates/apps/web/app/[locale]/use-cases/__tests__/page-renderer-migration.test.tsx +0 -72
- /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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"categories": ["consulting"],
|
|
5
5
|
"shape": "person-service",
|
|
6
6
|
"design": "standard",
|
|
7
|
-
"generatedHash": "
|
|
7
|
+
"generatedHash": "a763acef14c0c36649ad99dd4a4fea566ebdf64257bddb2f553ab8823349c309",
|
|
8
8
|
"layout": {
|
|
9
9
|
"nav": "full",
|
|
10
10
|
"footer": "columns",
|
|
@@ -111,6 +111,61 @@
|
|
|
111
111
|
"chrome": "on",
|
|
112
112
|
"sections": []
|
|
113
113
|
},
|
|
114
|
+
{
|
|
115
|
+
"route": "/for",
|
|
116
|
+
"kind": "page",
|
|
117
|
+
"pageType": "UseCasesList",
|
|
118
|
+
"schema": "UseCasesList",
|
|
119
|
+
"shell": "MarketingShell",
|
|
120
|
+
"chrome": "on",
|
|
121
|
+
"sections": [
|
|
122
|
+
{
|
|
123
|
+
"type": "hero",
|
|
124
|
+
"component": "Hero"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"type": "items",
|
|
128
|
+
"component": "Items",
|
|
129
|
+
"options": {
|
|
130
|
+
"columns": 3
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"type": "logoCloud",
|
|
135
|
+
"component": "LogoCloud",
|
|
136
|
+
"options": {
|
|
137
|
+
"layout": "inline"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"type": "testimonials",
|
|
142
|
+
"component": "Testimonials"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"type": "cta",
|
|
146
|
+
"component": "CTA"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"type": "faq",
|
|
150
|
+
"component": "FAQ"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"route": "/for/[slug]",
|
|
156
|
+
"kind": "page",
|
|
157
|
+
"contentDir": "content/en/UseCase",
|
|
158
|
+
"seeds": [
|
|
159
|
+
"content/en/UseCase/persona-1.mdx",
|
|
160
|
+
"content/en/UseCase/persona-2.mdx",
|
|
161
|
+
"content/en/UseCase/persona-3.mdx"
|
|
162
|
+
],
|
|
163
|
+
"pageType": "UseCase",
|
|
164
|
+
"schema": "UseCase",
|
|
165
|
+
"shell": "MarketingShell",
|
|
166
|
+
"chrome": "on",
|
|
167
|
+
"sections": []
|
|
168
|
+
},
|
|
114
169
|
{
|
|
115
170
|
"route": "/about",
|
|
116
171
|
"kind": "page",
|
|
@@ -143,6 +198,13 @@
|
|
|
143
198
|
{
|
|
144
199
|
"type": "hero",
|
|
145
200
|
"component": "Hero"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"type": "items",
|
|
204
|
+
"component": "Items",
|
|
205
|
+
"options": {
|
|
206
|
+
"columns": 2
|
|
207
|
+
}
|
|
146
208
|
}
|
|
147
209
|
]
|
|
148
210
|
},
|
|
@@ -208,25 +270,22 @@
|
|
|
208
270
|
]
|
|
209
271
|
},
|
|
210
272
|
{
|
|
211
|
-
"route": "/
|
|
212
|
-
"kind": "
|
|
213
|
-
"pageType":
|
|
214
|
-
"schema":
|
|
273
|
+
"route": "/sign-in",
|
|
274
|
+
"kind": "route",
|
|
275
|
+
"pageType": null,
|
|
276
|
+
"schema": null,
|
|
215
277
|
"shell": "MarketingShell",
|
|
216
278
|
"chrome": "on",
|
|
217
|
-
"sections": [
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
]
|
|
279
|
+
"sections": []
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"route": "/sign-up",
|
|
283
|
+
"kind": "route",
|
|
284
|
+
"pageType": null,
|
|
285
|
+
"schema": null,
|
|
286
|
+
"shell": "MarketingShell",
|
|
287
|
+
"chrome": "on",
|
|
288
|
+
"sections": []
|
|
230
289
|
},
|
|
231
290
|
{
|
|
232
291
|
"route": "/purchase-policy",
|
|
@@ -311,6 +370,56 @@
|
|
|
311
370
|
}
|
|
312
371
|
]
|
|
313
372
|
},
|
|
373
|
+
{
|
|
374
|
+
"route": "/meet",
|
|
375
|
+
"kind": "page",
|
|
376
|
+
"pageType": "LandingPage",
|
|
377
|
+
"schema": "WebPage",
|
|
378
|
+
"shell": "MarketingShell",
|
|
379
|
+
"chrome": "on",
|
|
380
|
+
"sections": [
|
|
381
|
+
{
|
|
382
|
+
"type": "hero",
|
|
383
|
+
"component": "Hero"
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"type": "items",
|
|
387
|
+
"component": "Items",
|
|
388
|
+
"options": {
|
|
389
|
+
"columns": 2
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"route": "/meet/[slug]",
|
|
396
|
+
"kind": "page",
|
|
397
|
+
"pageType": "BookCall",
|
|
398
|
+
"schema": "BookCall",
|
|
399
|
+
"shell": "MarketingShell",
|
|
400
|
+
"chrome": "on",
|
|
401
|
+
"sections": [
|
|
402
|
+
{
|
|
403
|
+
"type": "hero",
|
|
404
|
+
"component": "Hero"
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"type": "cta",
|
|
408
|
+
"component": "CTA"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
"type": "items",
|
|
412
|
+
"component": "Items",
|
|
413
|
+
"options": {
|
|
414
|
+
"columns": 3
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"type": "content-block",
|
|
419
|
+
"component": "ContentBlock"
|
|
420
|
+
}
|
|
421
|
+
]
|
|
422
|
+
},
|
|
314
423
|
{
|
|
315
424
|
"route": "/portfolio",
|
|
316
425
|
"kind": "page",
|
|
@@ -96,6 +96,28 @@ One `page=<route>` region per roster row, generated from the seed file the compo
|
|
|
96
96
|
_Detail route over `content/en/Service/` — 3 seed pages: `first-engagement.mdx`, `second-engagement.mdx`, `third-engagement.mdx`._
|
|
97
97
|
<!-- generated:end -->
|
|
98
98
|
|
|
99
|
+
`/for` (the persona hub — every shape carries the family now, #6878 D7):
|
|
100
|
+
|
|
101
|
+
<!-- generated:begin page=/for -->
|
|
102
|
+
|
|
103
|
+
| # | Section | Component | Copy (first line) |
|
|
104
|
+
| --- | -------------------------------------------------------- | -------------- | ----------------------------------------------------------------- |
|
|
105
|
+
| 1 | `hero` (eyebrow "Customers" · 2 CTAs) | `Hero` | {Customers: who your product or service is for} |
|
|
106
|
+
| 2 | `items` (columns=3 · items ×3) | `Items` | {The jobs customers hire your product or service to do} |
|
|
107
|
+
| 3 | `logoCloud` (layout=inline · logos ×6) | `LogoCloud` | Don’t just take our word for it |
|
|
108
|
+
| 4 | `testimonials` (quote · items ×1) | `Testimonials` | {A customer quote, in their own words, about the result they got} |
|
|
109
|
+
| 5 | `cta` (box · checklist ×3 · 2 CTAs · closingLine) | `CTA` | {Switch to your product or service in time amount or less} |
|
|
110
|
+
| 6 | `faq` (accordion · items ×5 · 1 CTA · initialOpen first) | `FAQ` | FAQs |
|
|
111
|
+
|
|
112
|
+
<!-- generated:end -->
|
|
113
|
+
|
|
114
|
+
`/for/[slug]`:
|
|
115
|
+
|
|
116
|
+
<!-- generated:begin page=/for/[slug] -->
|
|
117
|
+
|
|
118
|
+
_Detail route over `content/en/UseCase/` — 3 seed pages: `persona-1.mdx`, `persona-2.mdx`, `persona-3.mdx`._
|
|
119
|
+
<!-- generated:end -->
|
|
120
|
+
|
|
99
121
|
`/about`:
|
|
100
122
|
|
|
101
123
|
<!-- generated:begin page=/about -->
|
|
@@ -111,9 +133,10 @@ _Detail route over `content/en/Service/` — 3 seed pages: `first-engagement.mdx
|
|
|
111
133
|
|
|
112
134
|
<!-- generated:begin page=/contact -->
|
|
113
135
|
|
|
114
|
-
| # | Section | Component | Copy (first line)
|
|
115
|
-
| --- | --------------------------------------------------------- | --------- |
|
|
116
|
-
| 1 | `hero` (split · eyebrow "Contact" · checklist ×3 · 1 CTA) | `Hero` | Get every message in your email, free
|
|
136
|
+
| # | Section | Component | Copy (first line) |
|
|
137
|
+
| --- | --------------------------------------------------------- | --------- | ----------------------------------------- |
|
|
138
|
+
| 1 | `hero` (split · eyebrow "Contact" · checklist ×3 · 1 CTA) | `Hero` | Get every message in your email, free |
|
|
139
|
+
| 2 | `items` (tiles · columns=2 · items ×4) | `Items` | {Add appointment scheduling to your site} |
|
|
117
140
|
|
|
118
141
|
<!-- generated:end -->
|
|
119
142
|
|
|
@@ -129,7 +152,7 @@ _Detail route over `content/en/Service/` — 3 seed pages: `first-engagement.mdx
|
|
|
129
152
|
|
|
130
153
|
<!-- generated:end -->
|
|
131
154
|
|
|
132
|
-
`/glossary`, `/newsletter
|
|
155
|
+
`/glossary`, `/newsletter` (base-layer seeds every starter carries, #6658 D5 — `/newsletter` is this tree's own byte copy of the Free newsletter, D4/D9), plus the always-copied overlay's `/meet` hub and `/meet/[slug]` BookCall detail seeds (#6897 D3-D5):
|
|
133
156
|
|
|
134
157
|
<!-- generated:begin page=/glossary -->
|
|
135
158
|
|
|
@@ -149,15 +172,38 @@ _Detail route over `content/en/Service/` — 3 seed pages: `first-engagement.mdx
|
|
|
149
172
|
|
|
150
173
|
<!-- generated:end -->
|
|
151
174
|
|
|
152
|
-
<!-- generated:begin page=/
|
|
175
|
+
<!-- generated:begin page=/meet -->
|
|
153
176
|
|
|
154
|
-
| # | Section | Component | Copy (first line)
|
|
155
|
-
| --- | -------------------------------------- | --------- |
|
|
156
|
-
| 1 | `hero` (eyebrow "
|
|
157
|
-
| 2 | `items` (columns=
|
|
177
|
+
| # | Section | Component | Copy (first line) |
|
|
178
|
+
| --- | -------------------------------------- | --------- | --------------------- |
|
|
179
|
+
| 1 | `hero` (eyebrow "Meet") | `Hero` | {Book a time with us} |
|
|
180
|
+
| 2 | `items` (tiles · columns=2 · items ×4) | `Items` | |
|
|
158
181
|
|
|
159
182
|
<!-- generated:end -->
|
|
160
183
|
|
|
184
|
+
<!-- generated:begin page=/meet/[slug] -->
|
|
185
|
+
|
|
186
|
+
| # | Section | Component | Copy (first line) |
|
|
187
|
+
| --- | -------------------------------------- | -------------- | ------------------------------------------------ |
|
|
188
|
+
| 1 | `hero` (eyebrow "Book a Call" · 1 CTA) | `Hero` | Book a Call |
|
|
189
|
+
| 2 | `cta` (box · 1 CTA) | `CTA` | {What booking a call would do for your visitors} |
|
|
190
|
+
| 3 | `items` (columns=3 · items ×3) | `Items` | What happens on the call? |
|
|
191
|
+
| 4 | `content-block` (1 CTA) | `ContentBlock` | |
|
|
192
|
+
|
|
193
|
+
<!-- generated:end -->
|
|
194
|
+
|
|
195
|
+
`/sign-in`, `/sign-up` (code routes — the `SignInCard` island and the sign-up form inside the locale layout, whose header links both; listed so the manifest is a complete install record, #6797):
|
|
196
|
+
|
|
197
|
+
<!-- generated:begin page=/sign-in -->
|
|
198
|
+
|
|
199
|
+
_Code route — no content, no sections._
|
|
200
|
+
<!-- generated:end -->
|
|
201
|
+
|
|
202
|
+
<!-- generated:begin page=/sign-up -->
|
|
203
|
+
|
|
204
|
+
_Code route — no content, no sections._
|
|
205
|
+
<!-- generated:end -->
|
|
206
|
+
|
|
161
207
|
`/purchase-policy` (this tree's own service-shape override — cancellation and refunds, D4):
|
|
162
208
|
|
|
163
209
|
<!-- generated:begin page=/purchase-policy -->
|
|
@@ -199,7 +245,7 @@ _Detail route over `content/en/Service/` — 3 seed pages: `first-engagement.mdx
|
|
|
199
245
|
|
|
200
246
|
<!-- generated:end -->
|
|
201
247
|
|
|
202
|
-
`/portfolio` (this tree's own override of the `_base` seed — re-voiced for one person, both CTAs `/book-a-call` and `/contact`, D4):
|
|
248
|
+
`/portfolio` (this tree's own override of the `_base` seed — re-voiced for one person, both CTAs `/meet/book-a-call` and `/contact`, D4):
|
|
203
249
|
|
|
204
250
|
<!-- generated:begin page=/portfolio -->
|
|
205
251
|
|
|
@@ -230,19 +276,21 @@ The standard page set for this shape (`derive-roster.py --shape person-service -
|
|
|
230
276
|
| `ProjectsList` · `Project` | the portfolio pair (`/portfolio`) is the proof of past work; `/projects` is the paid signal-collectors sample listing |
|
|
231
277
|
| `Pricing` | a consultant sells named engagements, each priced on its own `Service` page or quoted on a call — not a pricing table |
|
|
232
278
|
| `CaseStudiesList` · `CaseStudy` · `TestimonialsList` · `ClientsList` | proof pages need real clients (#6658's reason for Free, unchanged); the portfolio pages carry placeholder before/after proof |
|
|
233
|
-
| `UseCasesList` · `UseCase` | each `Service` page names who it is for; the `_base` persona seeds are product copy that links `/pricing` |
|
|
234
279
|
| `EventsList` · `Event` · `DownloadsList` | a placeholder starter has no events or downloads |
|
|
235
280
|
| `ResourcesHub` · `ResourceDetail` · `HowTo` · `Whitepaper` | the Resources content system is the goal-driven default a site grows into, not a starter page |
|
|
236
281
|
|
|
237
282
|
**Rows added:**
|
|
238
283
|
|
|
239
|
-
| Row added | Reason
|
|
240
|
-
| --------------------------------- |
|
|
241
|
-
| `PurchasePolicyPage` | every shape carries one purchase policy with its shape's sections — service: cancellation and refunds (#6646 D3, contract R2.3)
|
|
242
|
-
| `PortfolioList` · `PortfolioItem` | the portfolio pair belongs to every shape's standard roster (operator, 2026-09-25; roadmap § 4)
|
|
243
|
-
| `BlogList` | every Free scaffold's nav links `/blog` unconditionally (`renderNavConfig`, operator ruling 2026-09-23); the Free teaser serves it, as on organization-product (#6753 D3)
|
|
284
|
+
| Row added | Reason |
|
|
285
|
+
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
286
|
+
| `PurchasePolicyPage` | every shape carries one purchase policy with its shape's sections — service: cancellation and refunds (#6646 D3, contract R2.3) |
|
|
287
|
+
| `PortfolioList` · `PortfolioItem` | the portfolio pair belongs to every shape's standard roster (operator, 2026-09-25; roadmap § 4) |
|
|
288
|
+
| `BlogList` | every Free scaffold's nav links `/blog` unconditionally (`renderNavConfig`, operator ruling 2026-09-23); the Free teaser serves it, as on organization-product (#6753 D3) |
|
|
289
|
+
| `LandingPage` | the Free `/meet` meeting-types hub is a LandingPage seed, the same generic `[slug]` route serves it through (#6897 D3); the four `/meet/[slug]` BookCall detail seeds ride the `BookCall` type already in the standard roster |
|
|
290
|
+
|
|
291
|
+
`|S − D| = 13` and `|R| = 18`.
|
|
244
292
|
|
|
245
|
-
|
|
293
|
+
`/sign-in` and `/sign-up` are also rostered (#6797) — code routes (`kind: route`) with no page type, so they sit outside this set equation: the locale layout's header links both, and the roster of record lists every page the scaffold serves.
|
|
246
294
|
|
|
247
295
|
## 4. Roster, as the registry declares it
|
|
248
296
|
|
|
@@ -260,16 +308,21 @@ person-service:
|
|
|
260
308
|
- { route: "/", kind: page, content: ["content/en/HomePage/home.mdx"] }
|
|
261
309
|
- { route: "/services", kind: page, content: ["content/en/ServicesList/services.mdx"] }
|
|
262
310
|
- { route: "/services/[slug]", kind: page, contentDir: "content/en/Service" }
|
|
311
|
+
- { route: "/for", kind: page, content: ["content/en/UseCasesList/for.mdx"] }
|
|
312
|
+
- { route: "/for/[slug]", kind: page, contentDir: "content/en/UseCase" }
|
|
263
313
|
- { route: "/about", kind: page, content: ["content/en/AboutPage/about.mdx"] }
|
|
264
314
|
- { route: "/contact", kind: page, content: ["content/en/ContactPage/contact.mdx"] }
|
|
265
315
|
- { route: "/faq", kind: page, content: ["content/en/FAQPage/faq.mdx"] }
|
|
266
316
|
- { route: "/glossary", kind: page, content: ["content/en/GlossaryList/glossary.mdx"] }
|
|
267
317
|
- { route: "/newsletter", kind: page, content: ["content/en/NewsletterSignup/newsletter.mdx"] }
|
|
268
|
-
- { route: "/
|
|
318
|
+
- { route: "/sign-in", kind: route }
|
|
319
|
+
- { route: "/sign-up", kind: route }
|
|
269
320
|
- { route: "/purchase-policy", kind: page, content: ["content/en/PurchasePolicyPage/purchase-policy.mdx"] }
|
|
270
321
|
- { route: "/privacy", kind: page, content: ["content/en/PrivacyPage/privacy.mdx"] }
|
|
271
322
|
- { route: "/terms", kind: page, content: ["content/en/TermsPage/terms.mdx"] }
|
|
272
323
|
- { route: "/blog", kind: page, content: ["content/en/BlogList/blog.mdx"] }
|
|
324
|
+
- { route: "/meet", kind: page, content: ["content/en/LandingPage/meet.mdx"] }
|
|
325
|
+
- { route: "/meet/[slug]", kind: page, content: ["content/en/BookCall/book-a-call.mdx", "content/en/BookCall/onsite-estimate.mdx", "content/en/BookCall/start-project.mdx", "content/en/BookCall/onsite-service.mdx"] }
|
|
273
326
|
- { route: "/portfolio", kind: page, content: ["content/en/PortfolioList/portfolio.mdx"] }
|
|
274
327
|
- { route: "/portfolio/[slug]", kind: page, contentDir: "content/en/PortfolioItem" }
|
|
275
328
|
```
|
|
@@ -280,11 +333,12 @@ By source:
|
|
|
280
333
|
|
|
281
334
|
```
|
|
282
335
|
starter: / · /services · /services/<slug> · /about · /contact · /faq
|
|
283
|
-
/glossary · /newsletter · /
|
|
284
|
-
/privacy · /terms · /blog · /
|
|
336
|
+
/glossary · /newsletter · /sign-in · /sign-up
|
|
337
|
+
/purchase-policy · /privacy · /terms · /blog · /meet · /meet/<slug>
|
|
338
|
+
/portfolio · /portfolio/<slug>
|
|
285
339
|
```
|
|
286
340
|
|
|
287
|
-
Every row is module-less: `requires` is `[marketing]` alone, so `mergeRoster` contributes nothing beyond this tree's own
|
|
341
|
+
Every row is module-less: `requires` is `[marketing]` alone, so `mergeRoster` contributes nothing beyond this tree's own seventeen rows.
|
|
288
342
|
|
|
289
343
|
## 5. Component inventory
|
|
290
344
|
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
"provenance.json": ".ailk-template.json",
|
|
7
7
|
"TEMPLATE-MANIFEST.json": ".ailk-site-manifest.json"
|
|
8
8
|
},
|
|
9
|
-
"postInstall": "Starter person-service installed. Its /faq, /contact and /
|
|
9
|
+
"postInstall": "Starter person-service installed. Its /faq, /contact, /blog, /meet and its four /meet/<slug> seed pages came with the always-copied overlay; /glossary, /newsletter, /privacy and /terms with the base layer it extends (content/en/). This tree's own /, /about, /services (+ three engagements), /purchase-policy and /portfolio pages are its own compositions, written for one person. Every line of copy is a placeholder \u2014 replace it before you launch."
|
|
10
10
|
}
|
|
@@ -24,7 +24,7 @@ sections:
|
|
|
24
24
|
{
|
|
25
25
|
"variant": "minimal",
|
|
26
26
|
"headline": "Work with me",
|
|
27
|
-
"primaryCta": { "label": "Book a call", "href": "/book-a-call" },
|
|
27
|
+
"primaryCta": { "label": "Book a call", "href": "/meet/book-a-call" },
|
|
28
28
|
"secondaryCta":
|
|
29
29
|
{
|
|
30
30
|
"label": "Get in touch",
|
|
@@ -14,7 +14,7 @@ sections:
|
|
|
14
14
|
"eyebrow": "{Your Name}",
|
|
15
15
|
"headline": "{One line on the outcome you deliver for clients}",
|
|
16
16
|
"subheadline": "{One line on who you work with and what makes working with you different.}",
|
|
17
|
-
"primaryCta": { "label": "Book a call", "href": "/book-a-call" },
|
|
17
|
+
"primaryCta": { "label": "Book a call", "href": "/meet/book-a-call" },
|
|
18
18
|
"secondaryCta":
|
|
19
19
|
{
|
|
20
20
|
"label": "Get in touch",
|
|
@@ -82,7 +82,7 @@ sections:
|
|
|
82
82
|
"variant": "minimal",
|
|
83
83
|
"headline": "Ready to talk about your project?",
|
|
84
84
|
"description": "{One line inviting the reader to start the conversation.}",
|
|
85
|
-
"primaryCta": { "label": "Book a call", "href": "/book-a-call" },
|
|
85
|
+
"primaryCta": { "label": "Book a call", "href": "/meet/book-a-call" },
|
|
86
86
|
"secondaryCta":
|
|
87
87
|
{
|
|
88
88
|
"label": "Get in touch",
|
|
@@ -20,7 +20,8 @@ sections:
|
|
|
20
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
21
|
"subtitleSize": "lead",
|
|
22
22
|
"ctaSize": "xl",
|
|
23
|
-
"primaryCta":
|
|
23
|
+
"primaryCta":
|
|
24
|
+
{ "label": "{Book a call}", "href": "/meet/book-a-call" },
|
|
24
25
|
"secondaryCta": { "label": "{Get in touch}", "href": "/contact" },
|
|
25
26
|
},
|
|
26
27
|
},
|
|
@@ -126,7 +127,8 @@ sections:
|
|
|
126
127
|
"variant": "beam",
|
|
127
128
|
"headline": "{Is your project the before or the after?}",
|
|
128
129
|
"description": "{One line offering the reader the same comparison for their own project.}",
|
|
129
|
-
"primaryCta":
|
|
130
|
+
"primaryCta":
|
|
131
|
+
{ "label": "{Book a call}", "href": "/meet/book-a-call" },
|
|
130
132
|
"secondaryCta": { "label": "{Get in touch}", "href": "/contact" },
|
|
131
133
|
"chips":
|
|
132
134
|
[
|
|
@@ -63,7 +63,7 @@ sections:
|
|
|
63
63
|
"variant": "minimal",
|
|
64
64
|
"headline": "Not sure which one?",
|
|
65
65
|
"description": "{One line inviting the reader to ask instead of guessing.}",
|
|
66
|
-
"primaryCta": { "label": "Book a call", "href": "/book-a-call" },
|
|
66
|
+
"primaryCta": { "label": "Book a call", "href": "/meet/book-a-call" },
|
|
67
67
|
},
|
|
68
68
|
},
|
|
69
69
|
]
|
|
@@ -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,14 +4,15 @@ 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
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. |
|
|
17
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`. |
|
|
@@ -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
|
|