create-ailk 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +7 -2
  2. package/dist/cli.js +5 -1
  3. package/dist/content-payloads.d.ts +37 -0
  4. package/dist/content-payloads.js +64 -0
  5. package/dist/lib/fetch-module.d.ts +3 -3
  6. package/dist/lib/fetch-module.js +11 -5
  7. package/dist/lib/fetch-template.d.ts +1 -1
  8. package/dist/lib/fetch-template.js +7 -4
  9. package/dist/lib/scaffold-render-sweep.d.ts +16 -0
  10. package/dist/lib/scaffold-render-sweep.js +52 -3
  11. package/dist/module-architecture.d.ts +9 -0
  12. package/dist/module-architecture.js +43 -12
  13. package/dist/parse-args.d.ts +2 -0
  14. package/dist/parse-args.js +7 -0
  15. package/dist/surfaces.js +2 -3
  16. package/package.json +3 -3
  17. package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +4 -3
  18. package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +8 -8
  19. package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +8 -8
  20. package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +8 -8
  21. package/site-templates/shapes/organization-service/content/en/Service/first-engagement.mdx +8 -8
  22. package/site-templates/shapes/organization-service/content/en/Service/second-engagement.mdx +8 -8
  23. package/site-templates/shapes/organization-service/content/en/Service/third-engagement.mdx +8 -8
  24. package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +8 -8
  25. package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +8 -8
  26. package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +8 -8
  27. package/templates/.claude/settings.json +12 -0
  28. package/templates/.env.example +1 -5
  29. package/templates/CLAUDE.md +38 -22
  30. package/templates/README.md +12 -12
  31. package/templates/apps/api/jest.config.cjs +1 -0
  32. package/templates/apps/api/package.json +2 -1
  33. package/templates/apps/mcp/CLAUDE.md +23 -10
  34. package/templates/apps/mcp/__tests__/catalog-drift.test.ts +160 -17
  35. package/templates/apps/mcp/__tests__/index.test.ts +118 -1
  36. package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +425 -5
  37. package/templates/apps/mcp/__tests__/module-exclusion.test.ts +67 -3
  38. package/templates/apps/mcp/__tests__/server.test.ts +162 -1
  39. package/templates/apps/mcp/package.json +1 -1
  40. package/templates/apps/mcp/src/index.ts +35 -3
  41. package/templates/apps/mcp/src/lib/commerce-claim.ts +193 -24
  42. package/templates/apps/mcp/src/server.ts +77 -5
  43. package/templates/apps/mcp/src/tools/purchase.ts +1 -1
  44. package/templates/apps/web/CLAUDE.md +1 -1
  45. package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +15 -0
  46. package/templates/apps/web/app/.well-known/mcp.json/route.ts +10 -3
  47. package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +0 -10
  48. package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +0 -10
  49. package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +1 -14
  50. package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +0 -10
  51. package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +0 -10
  52. package/templates/apps/web/app/[locale]/for/[slug]/page.tsx +0 -10
  53. package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +1 -14
  54. package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +0 -10
  55. package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +0 -10
  56. package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +0 -10
  57. package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +0 -10
  58. package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +1 -15
  59. package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +0 -10
  60. package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +0 -10
  61. package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +0 -10
  62. package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +1 -14
  63. package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +4 -16
  64. package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +3 -15
  65. package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +0 -10
  66. package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +1 -14
  67. package/templates/apps/web/src/lib/commerce-claim.ts +15 -6
  68. package/templates/content/_site.mdx +23 -4
  69. package/templates/database/CHANGELOG.md +7 -0
  70. package/templates/database/package.json +1 -1
  71. package/versions.json +34 -34
  72. package/templates/.claude/skills/README.md +0 -37
  73. package/templates/.claude/skills/add-auth/SKILL.md +0 -313
  74. package/templates/.claude/skills/add-auth/references/env-vars.md +0 -106
  75. package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +0 -180
  76. package/templates/.claude/skills/add-page/SKILL.md +0 -260
  77. package/templates/.claude/skills/add-page/references/page-types.md +0 -123
  78. package/templates/.claude/skills/add-page/scripts/site-pages.mjs +0 -87
  79. package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +0 -99
  80. package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +0 -18
  81. package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +0 -43
  82. package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +0 -52
  83. package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +0 -38
  84. package/templates/.claude/skills/check-site/SKILL.md +0 -245
  85. package/templates/.claude/skills/check-site/references/common-errors.md +0 -116
  86. package/templates/.claude/skills/check-site/references/findings-glossary.md +0 -140
  87. package/templates/.claude/skills/check-site/references/severity-levels.md +0 -114
  88. package/templates/.claude/skills/fill-page/SKILL.md +0 -199
  89. package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +0 -80
  90. package/templates/.claude/skills/fill-page/references/section-sources.md +0 -41
  91. package/templates/.claude/skills/setup-database/SKILL.md +0 -156
  92. package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +0 -154
  93. package/templates/.claude/skills/setup-deploy/SKILL.md +0 -312
  94. package/templates/.claude/skills/setup-deploy/references/runbook-template.md +0 -204
  95. package/templates/.claude/skills/setup-deploy/references/vercel-json-template.md +0 -98
  96. package/templates/.claude/skills/update-page/SKILL.md +0 -117
  97. package/templates/.claude/skills/update-page/scripts/update-page.ts +0 -640
  98. package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +0 -31
  99. package/templates/.claude/skills/upgrade-plan/SKILL.md +0 -121
  100. package/templates/.claude/skills/upgrade-plan/references/options.md +0 -24
  101. package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +0 -527
  102. package/templates/apps/mcp/__tests__/lib/require-paid-tier.test.ts +0 -75
  103. package/templates/apps/mcp/src/lib/require-paid-tier.ts +0 -44
@@ -49,11 +49,13 @@ theme:
49
49
  This file is your site's canonical configuration. Edit the frontmatter above to
50
50
  set your site name, base URL, default locale, and identity.
51
51
 
52
- `siteIdentity.kind` takes one of three values:
52
+ `siteIdentity.kind` takes one of four values:
53
53
 
54
- - Organization — a company, agency, nonprofit, or team
55
- - Person — a solo practitioner, consultant, or personal site
56
- - LocalBusiness — a business with a physical location customers visit
54
+ - Organization — a company, agency, nonprofit, or team
55
+ - Person — a solo practitioner, consultant, or personal site
56
+ - LocalBusiness — a business with a physical location customers visit
57
+ - SoftwareApplication — a product's own site, when its maker has a site of
58
+ its own (see below)
57
59
 
58
60
  `siteIdentity.secondary` (optional) names a second entity the site is about, and
59
61
  every page's structured data carries it:
@@ -73,6 +75,23 @@ For example, nested under `siteIdentity:`
73
75
  name: Acme App
74
76
  url: https://example.com/app
75
77
 
78
+ `kind: SoftwareApplication` is the inverse of that product secondary: the
79
+ product is the site's entity, and its maker — whose own site already declares
80
+ it — is named as `publisher` by the stable `@id` that site publishes. It takes
81
+ the product's `name` and `url` (optional `logo`, `description`,
82
+ `applicationCategory`, `operatingSystem`, `sameAs`) and a required `publisher`
83
+ with an `id` URL and an optional `name`; it takes no `secondary`. No second
84
+ Organization is declared here — every page's structured data points at the
85
+ maker's `@id`, and the home page's main entity is the product. For example:
86
+
87
+ siteIdentity:
88
+ kind: SoftwareApplication
89
+ name: Acme App
90
+ url: https://acme-app.example
91
+ publisher:
92
+ id: https://acme.example/#organization
93
+ name: Acme Inc.
94
+
76
95
  `sameAs` is the list of URLs that are unambiguously the same entity as you —
77
96
  your LinkedIn company page, your GitHub org, your X profile. Answer engines use
78
97
  it to reconcile your site with the rest of your presence, so it is worth
@@ -1,5 +1,12 @@
1
1
  # @working-theory/database
2
2
 
3
+ ## 0.30.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies []:
8
+ - @working-theory/validation@0.30.0
9
+
3
10
  ## 0.29.0
4
11
 
5
12
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@working-theory/database",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "license": "Apache-2.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/versions.json CHANGED
@@ -1,52 +1,52 @@
1
1
  {
2
- "@working-theory/admin-ui": "0.29.0",
3
- "@working-theory/aeo": "0.29.0",
4
- "@working-theory/agent-context": "0.29.0",
2
+ "@working-theory/admin-ui": "0.30.0",
3
+ "@working-theory/aeo": "0.30.0",
4
+ "@working-theory/agent-context": "0.30.0",
5
5
  "@working-theory/agent-contract": "0.1.0",
6
6
  "@working-theory/agent-memory": "0.0.0",
7
7
  "@working-theory/ai": "0.1.0",
8
- "@working-theory/analytics": "0.29.0",
9
- "@working-theory/api-client": "0.29.0",
8
+ "@working-theory/analytics": "0.30.0",
9
+ "@working-theory/api-client": "0.30.0",
10
10
  "@working-theory/cda-filesystem": "0.0.0",
11
- "@working-theory/cli": "0.29.0",
12
- "@working-theory/common": "0.29.0",
11
+ "@working-theory/cli": "0.30.0",
12
+ "@working-theory/common": "0.30.0",
13
13
  "@working-theory/consent": "0.1.0",
14
- "@working-theory/content-adapters": "0.29.0",
15
- "@working-theory/content-projection": "0.29.0",
16
- "@working-theory/email": "0.29.0",
14
+ "@working-theory/content-adapters": "0.30.0",
15
+ "@working-theory/content-projection": "0.30.0",
16
+ "@working-theory/email": "0.30.0",
17
17
  "@working-theory/env": "0.0.0",
18
- "@working-theory/eslint-config": "0.29.0",
19
- "@working-theory/fumadocs-schema": "0.29.0",
18
+ "@working-theory/eslint-config": "0.30.0",
19
+ "@working-theory/fumadocs-schema": "0.30.0",
20
20
  "@working-theory/ids": "0.8.0",
21
- "@working-theory/jsonld": "0.29.0",
22
- "@working-theory/license": "0.29.0",
23
- "@working-theory/metadata": "0.29.0",
24
- "@working-theory/observability": "0.29.0",
25
- "@working-theory/page-renderer": "0.29.0",
26
- "@working-theory/schema": "0.29.0",
27
- "@working-theory/schema-pack-registry": "0.29.0",
28
- "@working-theory/schema-validator": "0.29.0",
29
- "@working-theory/sections-registry": "0.29.0",
30
- "@working-theory/site-config": "0.29.0",
31
- "@working-theory/stripe-client": "0.29.0",
32
- "@working-theory/templates": "0.29.0",
33
- "@working-theory/theme": "0.29.0",
34
- "@working-theory/ui": "0.29.0",
35
- "@working-theory/validation": "0.29.0",
36
- "@working-theory/web-i18n": "0.29.0",
21
+ "@working-theory/jsonld": "0.30.0",
22
+ "@working-theory/license": "0.30.0",
23
+ "@working-theory/metadata": "0.30.0",
24
+ "@working-theory/observability": "0.30.0",
25
+ "@working-theory/page-renderer": "0.30.0",
26
+ "@working-theory/plugin-mcp": "0.1.1",
27
+ "@working-theory/schema": "0.30.0",
28
+ "@working-theory/schema-pack-registry": "0.30.0",
29
+ "@working-theory/schema-validator": "0.30.0",
30
+ "@working-theory/sections-registry": "0.30.0",
31
+ "@working-theory/site-config": "0.30.0",
32
+ "@working-theory/stripe-client": "0.30.0",
33
+ "@working-theory/templates": "0.30.0",
34
+ "@working-theory/theme": "0.30.0",
35
+ "@working-theory/ui": "0.30.0",
36
+ "@working-theory/validation": "0.30.0",
37
+ "@working-theory/web-i18n": "0.30.0",
37
38
  "@working-theory/billing-client": "0.0.0",
38
39
  "@working-theory/branding": "0.0.0",
39
40
  "@working-theory/license-client": "0.0.0",
40
41
  "@working-theory/license-manifest": "0.0.0",
41
- "@working-theory/marketing-api-client": "0.0.0",
42
42
  "@working-theory/partner-session": "0.0.0",
43
43
  "@working-theory/preview-protocol": "0.0.0",
44
- "@working-theory/ui-commerce": "0.23.6",
45
- "@working-theory/ui-docs-blog": "0.23.6",
46
- "@working-theory/ui-scheduling": "0.23.6",
47
- "@working-theory/ui-signal-collectors": "0.24.4",
44
+ "@working-theory/ui-commerce": "0.23.7",
45
+ "@working-theory/ui-docs-blog": "0.23.7",
46
+ "@working-theory/ui-scheduling": "0.23.7",
47
+ "@working-theory/ui-signal-collectors": "0.24.5",
48
48
  "@working-theory/web": "0.0.0",
49
49
  "@working-theory/api": "1.0.0",
50
50
  "@working-theory/mcp": "0.0.0",
51
- "@working-theory/database": "0.29.0"
51
+ "@working-theory/database": "0.30.0"
52
52
  }
@@ -1,37 +0,0 @@
1
- # Skills
2
-
3
- Skills are reusable Claude Code workflows scoped to this project. Each
4
- lives in its own subdirectory with a `SKILL.md` describing when to use
5
- it and how it works.
6
-
7
- The eight skills below ship with this project. Claude Code discovers
8
- them automatically at session start — nothing to install or enable.
9
-
10
- ## Available skills
11
-
12
- | Skill | Purpose |
13
- | -------------- | -------------------------------------------------------------------------------------------------------------- |
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. |
16
- | `add-auth` | Activate auth providers — magic-link via Resend, Google OAuth, GitHub OAuth. |
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`. |
19
- | `check-site` | Run `ailk-audit --json` and explain the score and findings in plain language. |
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). |
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. |
22
-
23
- `scaffold-commerce` is delivered with the commerce module (`--modules commerce`, licensed).
24
-
25
- ## How a skill works
26
-
27
- Each subdirectory holds:
28
-
29
- - `SKILL.md` — when to invoke, what it produces, what it requires.
30
- - Any supporting prompt fragments, code templates, or reference
31
- files the skill loads at runtime.
32
-
33
- ## Adding your own
34
-
35
- To add a project-specific skill, create a folder here with a
36
- `SKILL.md` describing it. Claude Code will discover it automatically
37
- on session start. See the skills above for examples of the format.
@@ -1,313 +0,0 @@
1
- ---
2
- name: add-auth
3
- description: Activate the site's sign-in providers (email-and-password, Google OAuth, GitHub OAuth) on an AILK consumer site. Use when the user says "wire up auth", "add login", "set up sign-in", "I need users to log in", or asks how to enable email / Google / GitHub sign-in on their AILK site. The skill writes env vars for whichever subset of providers the consumer activates and prints (plus saves) an OAuth-app-setup runbook. It does NOT modify `apps/web/auth.ts` and does NOT emit any pages.
4
- ---
5
-
6
- # add-auth
7
-
8
- Activate one or more sign-in providers on an AILK site by writing the
9
- env vars `getActiveProviderIds()` (`apps/web/lib/auth-env.ts`) reads
10
- to detect them, plus a `RUNBOOK.md` that documents the OAuth-app-creation
11
- steps for the consumer's records.
12
-
13
- The site's auth library is **Better Auth**, configured in
14
- `apps/web/auth.ts` and mounted at `apps/web/app/api/auth/[...all]/route.ts`.
15
-
16
- ## When to use
17
-
18
- The user has a working AILK site (post-`pnpm create ailk`) and wants
19
- to gate routes behind sign-in or accept email, Google or GitHub
20
- sign-in. Phrases that should trigger this skill:
21
-
22
- - "wire up auth" / "add login" / "set up sign-in"
23
- - "I want users to log in"
24
- - "enable Google sign-in" / "enable GitHub login"
25
- - "set up email login" / "set up magic-link auth"
26
- - "add OAuth"
27
-
28
- A magic link is not wired: Better Auth core ships no magic-link
29
- provider, so the `email` provider id switches on email-and-password
30
- sign-in instead. Say so when the consumer asks for a magic link, and
31
- offer `email` on those terms.
32
-
33
- Skip this skill when:
34
-
35
- - The user wants a new page. The site already ships its sign-in and
36
- sign-up pages (`apps/web/app/[locale]/(auth)/`), which list whichever
37
- providers are active. Any other page is `add-page`'s job.
38
- - The user is asking about a third-party provider outside the three
39
- provider ids below (Apple, Microsoft, Twitter, etc.). Adding one is a
40
- code change to `apps/web/auth.ts`, not env wiring. Acknowledge the
41
- request and stop.
42
- - The user is in production and needs production callback URLs. v1
43
- ships dev-mode callbacks (`http://localhost:3000`) only —
44
- production callback setup is deferred to `setup-deploy`
45
- or a future deploy skill. Note this and stop.
46
-
47
- ## The provider ids
48
-
49
- `getActiveProviderIds()` in `apps/web/lib/auth-env.ts` returns a
50
- provider id only when every one of its env vars is set to a non-empty
51
- value:
52
-
53
- | Provider id | Env vars | What it switches on |
54
- | ----------- | ------------------------------------------- | --------------------------------------------------------------- |
55
- | `email` | `AUTH_EMAIL_SERVER` + `AUTH_EMAIL_FROM` | Email-and-password sign-in (Better Auth's `emailAndPassword`) |
56
- | `google` | `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` | Google OAuth (Better Auth's `socialProviders.google`) |
57
- | `github` | `GITHUB_CLIENT_ID` + `GITHUB_CLIENT_SECRET` | GitHub OAuth (Better Auth's `socialProviders.github`) |
58
-
59
- `references/env-vars.md` is the full contract, including the auxiliary
60
- vars (`BETTER_AUTH_URL`, `BETTER_AUTH_SECRET`, `AILK_AUTH_REQUIRED`,
61
- `AILK_AUTH_SIGNUP_OPEN`, `AILK_AUTH_PASSWORD_RESET`,
62
- `AUTH_EMAIL_WEBHOOK_SECRET`).
63
-
64
- ## What this skill does (and does not do)
65
-
66
- **Does:**
67
-
68
- - Reads `.env.local` to see which provider ids are already active.
69
- - Asks the consumer which of the three provider ids (`email`,
70
- `google`, `github`) they want to activate _this session_.
71
- - For each picked provider, walks the consumer through
72
- OAuth-app creation (`google` / `github`) or the Resend sender setup
73
- (`email`), then writes the resulting values to `.env.local`.
74
- - Checks that sign-in has a database to write to. Better Auth always
75
- runs its Prisma adapter with database sessions, so sign-in needs
76
- `DATABASE_URL` and the auth tables in place.
77
- - Writes (or merges) a `RUNBOOK.md` in the consumer's repo root
78
- with the same setup instructions the consumer just followed, so
79
- they can refer back later or hand to a collaborator.
80
-
81
- **Does not:**
82
-
83
- - Modify `apps/web/auth.ts`. The three provider ids are env-var-driven
84
- — `apps/web/auth.ts` reads `getActiveProviderIds()` at startup and
85
- builds only the providers it returns. No code changes are needed.
86
- - Create any new files under `app/`, `pages/`, or `content/`. The
87
- emit is limited to `.env.local` writes and a `RUNBOOK.md` write.
88
- - Set up production callback URLs. Dev-mode (`http://localhost:3000`)
89
- only at v1.
90
- - Add, remove, or modify any provider in `apps/web/auth.ts`. A
91
- provider the consumer added there by hand (e.g., Apple) is preserved
92
- as-is and never touched by this skill.
93
- - Accept production OAuth credentials. If the consumer pastes a
94
- production-looking secret, that's acceptable, but the runbook still
95
- documents only the dev callback URL.
96
-
97
- ## The mechanic
98
-
99
- ### Step 1 — Show the menu
100
-
101
- Greet the consumer and present the three provider ids, marking
102
- which are already active (env vars present in `.env.local`):
103
-
104
- ```
105
- Which sign-in providers do you want to activate?
106
-
107
- [ ] email (email-and-password sign-in)
108
- [ ] google (Google OAuth)
109
- [ ] github (GitHub OAuth)
110
-
111
- You can pick any subset, including "none of the above" (in which case
112
- this skill exits without writing anything). You can also re-run this
113
- skill later to activate more providers — already-active providers
114
- will be skipped automatically.
115
- ```
116
-
117
- If `.env.local` already has any of these active, mark them:
118
-
119
- ```
120
- [x] email (already active — AUTH_EMAIL_SERVER + AUTH_EMAIL_FROM are set)
121
- [ ] google (Google OAuth)
122
- [ ] github (GitHub OAuth)
123
- ```
124
-
125
- Wait for the consumer to pick a subset. Then, for each picked
126
- provider, run the matching sub-flow.
127
-
128
- ### Step 2 — Run per-provider sub-flows
129
-
130
- #### `email` sub-flow
131
-
132
- 1. Tell the consumer: _"The `email` provider turns on
133
- email-and-password sign-in. It switches on when `AUTH_EMAIL_SERVER`
134
- and `AUTH_EMAIL_FROM` are both set. You'll need a Resend API key
135
- (free tier is fine for development). Get one at
136
- <https://resend.com/api-keys>."_
137
- 2. Wait for the consumer to paste the API key.
138
- 3. Ask for the `AUTH_EMAIL_FROM` address. This must be a verified
139
- sender on the consumer's Resend account. For development it's
140
- common to use `onboarding@resend.dev` (Resend's shared dev
141
- sender). Mention that.
142
- 4. Construct `AUTH_EMAIL_SERVER` as
143
- `smtp://resend:<API_KEY>@smtp.resend.com:465`.
144
- 5. Write to `.env.local`:
145
- ```
146
- AUTH_EMAIL_SERVER=smtp://resend:re_...@smtp.resend.com:465
147
- AUTH_EMAIL_FROM=onboarding@resend.dev
148
- ```
149
- 6. Tell the consumer who actually sends the mail. `apps/web` sends
150
- none: `AUTH_EMAIL_SERVER` is read for its presence only, and
151
- `apps/web/lib/auth-email.ts` relays each auth email (verification,
152
- password reset) to `apps/api`, which sends it with `RESEND_API_KEY`
153
- from `AUTH_EMAIL_FROM`. For that mail to go out, `RESEND_API_KEY`
154
- and `AUTH_EMAIL_FROM` must be set for `apps/api`, and
155
- `AUTH_EMAIL_WEBHOOK_SECRET` (any long random string, the same value)
156
- for both apps. Password reset — and the verification mail with it —
157
- is off until `AILK_AUTH_PASSWORD_RESET=1`, and also needs
158
- `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET` (`resetSendConfigured()`
159
- in `apps/web/lib/auth-env.ts`).
160
- 7. Tell the consumer that public sign-up stays closed until they set
161
- `AILK_AUTH_SIGNUP_OPEN=1` (read by `isSignUpOpen()` in
162
- `apps/web/lib/auth-env.ts`). With sign-up closed and `email` the only
163
- provider, nobody can create the first account — so either open
164
- sign-up long enough to create it, or activate `google` or `github`
165
- as well. Ask which they want; leave the flag unset otherwise.
166
-
167
- #### `google` sub-flow
168
-
169
- 1. Tell the consumer the steps in chat AND queue the same content for
170
- the runbook (see Step 3). Steps:
171
- - Go to <https://console.cloud.google.com/apis/credentials>.
172
- - Click **Create Credentials → OAuth client ID**. If prompted,
173
- configure the OAuth consent screen first (**External** → fill
174
- name, support email, developer contact email; Better Auth
175
- requests the scopes at runtime, so leave the scope list empty).
176
- - Application type: **Web application**.
177
- - Name: anything (e.g., "AILK dev").
178
- - **Authorized redirect URIs** — add exactly:
179
- `http://localhost:3000/api/auth/callback/google`
180
- - Click **Create**. Copy the **Client ID** and **Client secret**
181
- from the dialog.
182
- 2. Wait for the consumer to paste both values.
183
- 3. Write to `.env.local`:
184
- ```
185
- GOOGLE_CLIENT_ID=...
186
- GOOGLE_CLIENT_SECRET=...
187
- ```
188
-
189
- #### `github` sub-flow
190
-
191
- 1. Tell the consumer the steps in chat AND queue the same content for
192
- the runbook. Steps:
193
- - Go to <https://github.com/settings/developers>.
194
- - Click **New OAuth App**.
195
- - Application name: anything (e.g., "AILK dev").
196
- - Homepage URL: `http://localhost:3000`
197
- - **Authorization callback URL** — add exactly:
198
- `http://localhost:3000/api/auth/callback/github`
199
- - Click **Register application**. Generate a new client secret.
200
- Copy the **Client ID** and **Client secret**.
201
- 2. Wait for the consumer to paste both values.
202
- 3. Write to `.env.local`:
203
- ```
204
- GITHUB_CLIENT_ID=...
205
- GITHUB_CLIENT_SECRET=...
206
- ```
207
-
208
- ### Step 3 — Write the RUNBOOK
209
-
210
- After all picked providers are activated, write
211
- `RUNBOOK.md` (or merge into existing) at the consumer's repo root.
212
- The runbook captures the OAuth-app-creation steps and Resend setup
213
- the consumer just walked through, so they can hand it to a teammate
214
- or refer back later.
215
-
216
- Use `references/oauth-app-setup.md` as the template. Replace
217
- `<provider>` headings as appropriate, and only include sections for
218
- providers actually activated this session. If `RUNBOOK.md` already
219
- exists with sections for already-active providers, do not
220
- duplicate — add only the new sections beneath any existing content.
221
-
222
- ### Step 4 — Check the database
223
-
224
- Sign-in always reads and writes the database: `apps/web/auth.ts`
225
- runs Better Auth's Prisma adapter, and sessions are rows, not
226
- cookie-only tokens. There is no database-free mode. Before printing
227
- the closing summary, check:
228
-
229
- - `DATABASE_URL` (and `DATABASE_URL_NON_POOLED`, which the migrations
230
- use) is set in `.env.local`. If it is not, sign-in will fail on its
231
- first request — point the consumer at the `setup-database` skill,
232
- which sets both and creates the tables.
233
- - The auth tables exist. The Prisma schema is `database/schema.prisma`
234
- (Prisma reads the whole `database/` folder; the `User`, `Session`,
235
- `Account` and `Verification` models are in `database/auth/schema.prisma`).
236
- If the consumer has not applied the migrations yet, they run
237
- `pnpm db:migrate:deploy`.
238
-
239
- State what you found in the closing summary so the consumer is never
240
- surprised:
241
-
242
- > "Sign-in stores its users and sessions in your database (the
243
- > `User` and `Session` tables). Run `pnpm db:migrate:deploy` if you
244
- > haven't applied the migrations yet."
245
-
246
- or, when `DATABASE_URL` is unset:
247
-
248
- > "Sign-in needs a database and none is configured yet. Run the
249
- > `setup-database` skill before you try to sign in."
250
-
251
- ### Step 5 — Closing summary
252
-
253
- Print:
254
-
255
- - Which provider ids are now active (subset picked this session +
256
- already-active providers).
257
- - What Step 4 found about the database.
258
- - A reminder to set `AILK_AUTH_REQUIRED=1` in `.env.local` if they
259
- want protected routes (default is auth-disabled / public).
260
- - A pointer to `RUNBOOK.md` for future reference.
261
- - A pointer to `setup-deploy` for production callback URLs and
262
- `BETTER_AUTH_URL` / `BETTER_AUTH_SECRET` when the consumer is ready
263
- to deploy — a production deploy fails without `BETTER_AUTH_SECRET`.
264
-
265
- ## Re-invocation
266
-
267
- The skill is idempotent. On a second run, the menu in Step 1 marks
268
- already-active providers with `[x]` (read from `.env.local`), and
269
- the per-provider sub-flows skip those and only run for the new ones.
270
- The closing summary lists everything, not just what changed this
271
- session.
272
-
273
- If the consumer wants to _change_ a previously-activated provider's
274
- secrets (e.g., rotated their Google Client Secret), they should pick
275
- that provider in the menu and the sub-flow will overwrite the
276
- existing values in `.env.local`. Confirm before overwriting.
277
-
278
- ## Customization preservation
279
-
280
- If `apps/web/auth.ts` has been modified by the consumer to add a
281
- third-party provider (e.g., Apple), this skill leaves that file
282
- completely untouched. The skill never edits `apps/web/auth.ts`.
283
- Activation of the three provider ids happens entirely through env
284
- vars — `getActiveProviderIds()` in `apps/web/lib/auth-env.ts` is what
285
- reads them at startup.
286
-
287
- ## What "activation" means under the hood
288
-
289
- - **The provider list is computed at startup from env-var presence**
290
- by `getActiveProviderIds()` in `apps/web/lib/auth-env.ts`.
291
- - `apps/web/auth.ts` consumes that list: `google` and `github` become
292
- Better Auth `socialProviders` entries built from their env vars, and
293
- `email` switches `emailAndPassword` on.
294
- - A provider id is returned only when every one of its env vars is set
295
- (the table under § The provider ids).
296
- - A site with zero auth env vars boots cleanly with no active
297
- providers (`getActiveProviderIds()` returns an empty array).
298
-
299
- This means the skill's job is purely env-var wiring + documentation.
300
-
301
- ## References
302
-
303
- - `references/oauth-app-setup.md` — RUNBOOK template the skill instantiates per session.
304
- - `references/env-vars.md` — env-var contract (which vars activate which provider id).
305
-
306
- ## Coordination
307
-
308
- - **`add-page`** — any new page. This skill emits no pages; the
309
- sign-in and sign-up pages already ship.
310
- - **`setup-database`** — `DATABASE_URL` and the tables sign-in
311
- needs.
312
- - **`setup-deploy`** — production callback URLs and the production
313
- auth env vars. v1 of this skill is dev-only.
@@ -1,106 +0,0 @@
1
- # Auth Env-Var Contract
2
-
3
- Source of truth for which env vars activate which auth provider on
4
- an AILK consumer site. Read by the `add-auth` skill before
5
- asking the consumer to paste secrets.
6
-
7
- The activation logic lives in `apps/web/lib/auth-env.ts` →
8
- `getActiveProviderIds()`. A provider is active **only when every
9
- required var is set to a non-empty value**. Partial wiring (e.g.,
10
- `GOOGLE_CLIENT_ID` set but `GOOGLE_CLIENT_SECRET` missing) is treated
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, … })`).
15
-
16
- ## Provider activation table
17
-
18
- | Provider ID | Required env vars | Source |
19
- | ----------- | -------------------------------------------- | ---------------------------- |
20
- | `email` | `AUTH_EMAIL_SERVER` + `AUTH_EMAIL_FROM` | Email sign-in (Resend)¹ |
21
- | `google` | `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` | Google OAuth |
22
- | `github` | `GITHUB_CLIENT_ID` + `GITHUB_CLIENT_SECRET` | GitHub OAuth |
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
-
28
- ## Auxiliary auth env vars
29
-
30
- | Var | Default | Effect |
31
- | ---------------------- | ------- | ------------------------------------------------------------------------------------- |
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`. |
35
- | `AILK_AUTH_SIGNUP_OPEN` | unset | Read by `isSignUpOpen()` in `apps/web/lib/auth-env.ts` (`"1"` or `"true"`). Unset, public sign-up is closed: with `email` active, the password form signs existing accounts in but creates none. |
36
- | `AILK_AUTH_PASSWORD_RESET` | unset | Read by `isResetAvailable()` (`"1"` or `"true"`). Password reset also needs `BETTER_AUTH_URL`, `BETTER_AUTH_SECRET` and `AUTH_EMAIL_WEBHOOK_SECRET` (`resetSendConfigured()`). |
37
- | `AUTH_EMAIL_WEBHOOK_SECRET` | unset | Signs the auth-mail relay from `apps/web` to `apps/api`, which sends with `RESEND_API_KEY` from `AUTH_EMAIL_FROM`. Set the same value for both apps; unset, no auth mail is sent. |
38
-
39
- The skill writes none of these auxiliary vars unasked. It mentions
40
- them in the closing summary so the consumer is aware:
41
-
42
- - `AILK_AUTH_REQUIRED` is the consumer's call (skill always defaults
43
- to leaving it unset).
44
- - `AILK_AUTH_SIGNUP_OPEN` is the consumer's call too; the skill asks
45
- when `email` is active, because with sign-up closed and no OAuth
46
- provider nobody can create the first account.
47
- - `AILK_AUTH_PASSWORD_RESET` and `AUTH_EMAIL_WEBHOOK_SECRET` are the
48
- auth-mail setup the `email` sub-flow describes.
49
- - `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET` are deferred to
50
- production-time setup (`setup-deploy`), and a production deploy
51
- fails without `BETTER_AUTH_SECRET`.
52
-
53
- ## Env-var formats — what valid values look like
54
-
55
- ### `AUTH_EMAIL_SERVER` (email sign-in via Resend)
56
-
57
- ```
58
- smtp://resend:<RESEND_API_KEY>@smtp.resend.com:465
59
- ```
60
-
61
- The Resend API key starts with `re_`. The literal username is the
62
- string `resend` (Resend's SMTP convention). Port 465 is implicit-TLS
63
- SMTP.
64
-
65
- ### `AUTH_EMAIL_FROM` (email sign-in via Resend)
66
-
67
- A verified sender address on the consumer's Resend account. For
68
- development, `onboarding@resend.dev` works without verification.
69
-
70
- ### `GOOGLE_CLIENT_ID` / `GITHUB_CLIENT_ID`
71
-
72
- Public identifiers issued by Google / GitHub. Typically:
73
-
74
- - Google: ends in `.apps.googleusercontent.com`
75
- - GitHub: 20-character hex string
76
-
77
- Either can be safely committed to a public template; production
78
- secrets stay in `.env.local`.
79
-
80
- ### `GOOGLE_CLIENT_SECRET` / `GITHUB_CLIENT_SECRET`
81
-
82
- Sensitive values. Treat as passwords. Never commit. The skill writes
83
- these only to `.env.local` (which is in the consumer scaffold's
84
- `.gitignore` by default).
85
-
86
- ## Detection of "already activated"
87
-
88
- The skill's Step 1 menu marks providers as `[x]` when both required
89
- vars are set in `.env.local`. The detection is presence-only — the
90
- skill does not validate that the values actually work (no Google
91
- API ping, no GitHub API ping, no test SMTP connection). A consumer
92
- who pasted typos will get a runtime auth error from Better Auth on
93
- their first sign-in attempt; the fix is to re-run the skill and
94
- overwrite.
95
-
96
- ## Where these vars are read
97
-
98
- - `apps/web/lib/auth-env.ts` — `getActiveProviderIds()` and
99
- `isAuthRequired()`.
100
- - `apps/web/auth.ts` — `buildSocialProviders()` consumes the
101
- active-provider list and builds Better Auth's `socialProviders`
102
- from the matching env vars; `resolveSecret()` reads
103
- `BETTER_AUTH_SECRET`, and `baseURL` is `BETTER_AUTH_URL`.
104
-
105
- The skill never modifies any of those files. All activation is
106
- env-var-driven.