create-ailk 0.9.0 → 0.10.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 +3 -3
- package/dist/cli.js +12 -1
- package/dist/lib/module-license-gate.d.ts +29 -23
- package/dist/lib/module-license-gate.js +98 -0
- package/dist/module-architecture.js +5 -4
- package/dist/programmatic.js +12 -4
- package/dist/starter-grid.d.ts +4 -67
- package/dist/starter-grid.js +6 -84
- package/dist/template-manifest.d.ts +1 -1
- package/dist/template-manifest.js +5 -5
- package/package.json +4 -2
- package/release-scope.json +25 -0
- package/site-templates/designs/minimalism/sample/README.md +2 -2
- package/site-templates/designs/minimalism/sample/content/en/HomePage/home.mdx +1 -1
- package/templates/.claude/agents/web.md +10 -8
- package/templates/.claude/rules/architecture.md +10 -7
- package/templates/.claude/skills/add-auth/SKILL.md +142 -90
- package/templates/.claude/skills/add-auth/references/env-vars.md +9 -1
- package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +14 -6
- package/templates/.claude/skills/add-page/references/page-types.md +9 -10
- package/templates/.claude/skills/check-site/SKILL.md +28 -18
- package/templates/.claude/skills/check-site/references/common-errors.md +12 -9
- package/templates/.claude/skills/check-site/references/findings-glossary.md +4 -4
- package/templates/.claude/skills/check-site/references/severity-levels.md +3 -3
- package/templates/.claude/skills/setup-deploy/SKILL.md +75 -38
- package/templates/.claude/skills/update-page/SKILL.md +1 -1
- package/templates/.env.example +23 -2
- package/templates/CLAUDE.md +1 -1
- package/templates/package.json +2 -0
- package/dist/modules/commerce/0.6.0.tar.gz +0 -0
- package/dist/modules/commerce/0.6.1.tar.gz +0 -0
- package/dist/modules/docs-blog/0.6.0.tar.gz +0 -0
- package/dist/modules/docs-blog/0.6.1.tar.gz +0 -0
- package/dist/modules/marketing-site/0.6.1.tar.gz +0 -0
- package/dist/modules/minimalism-site/0.6.1.tar.gz +0 -0
- package/dist/modules/multi-tenant/0.6.0.tar.gz +0 -0
- package/dist/modules/multi-tenant/0.6.1.tar.gz +0 -0
- package/dist/modules/saas-product/0.6.1.tar.gz +0 -0
- package/dist/modules/scheduling/0.6.0.tar.gz +0 -0
- package/dist/modules/scheduling/0.6.1.tar.gz +0 -0
- package/dist/modules/signal-collectors/0.6.0.tar.gz +0 -0
- package/dist/modules/signal-collectors/0.6.1.tar.gz +0 -0
- package/dist/modules/simple-service/0.6.1.tar.gz +0 -0
- package/dist/modules/workspace/0.6.0.tar.gz +0 -0
- package/dist/modules/workspace/0.6.1.tar.gz +0 -0
- package/site-templates/aliases/minimalism-site.TEMPLATE-MANIFEST.json +0 -538
- package/templates/.claude/skills/setup-deploy/references/env-vars-template.md +0 -192
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +0 -8
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +0 -12
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +0 -12
|
@@ -22,8 +22,8 @@ upstream packages; don't try to edit them locally.
|
|
|
22
22
|
## Read before edit
|
|
23
23
|
|
|
24
24
|
1. `.claude/rules/architecture.md` — confirm what `apps/web` may
|
|
25
|
-
import
|
|
26
|
-
|
|
25
|
+
import, including its one database exception (the Better Auth
|
|
26
|
+
adapter). Everything else server-side goes through `apps/api`.
|
|
27
27
|
2. The page or component you're modifying, plus any sibling files in
|
|
28
28
|
the same directory.
|
|
29
29
|
3. Any project-local theme override file before touching styles —
|
|
@@ -46,7 +46,8 @@ Run `pnpm preflight` before opening a PR.
|
|
|
46
46
|
- Need a new content type? Add it under `content/<TypeName>/` and
|
|
47
47
|
reference the schema from `@working-theory/schema`.
|
|
48
48
|
- Need a database read? Wrong layer — `apps/web` does not read the
|
|
49
|
-
database
|
|
49
|
+
database outside the one exception `.claude/rules/architecture.md`
|
|
50
|
+
names. Route through `apps/api`.
|
|
50
51
|
|
|
51
52
|
## Domain conventions
|
|
52
53
|
|
|
@@ -55,23 +56,24 @@ Run `pnpm preflight` before opening a PR.
|
|
|
55
56
|
Adding `'use client'` to a file that just renders JSX is the
|
|
56
57
|
default failure mode — resist it.
|
|
57
58
|
- **Tailwind tokens only.** No raw hex, rgb, or arbitrary colors.
|
|
58
|
-
Use semantic tokens from `@working-theory/theme` (`bg-
|
|
59
|
+
Use semantic tokens from `@working-theory/theme` (`bg-surface`, `text-fg`,
|
|
59
60
|
`border-border`, etc.). If a token doesn't exist, extend the theme;
|
|
60
61
|
don't bypass.
|
|
61
62
|
- **Mobile-first responsive.** Default styles target mobile;
|
|
62
63
|
`md:`/`lg:` modifiers for larger viewports.
|
|
63
64
|
- **MDX rendering** uses `next-mdx-remote/rsc`, never `@next/mdx`
|
|
64
65
|
(the latter requires runtime config that fights Server Components).
|
|
65
|
-
- **
|
|
66
|
-
—
|
|
66
|
+
- **Better Auth's route handler** is the only API-shaped code in
|
|
67
|
+
`apps/web` — it lives at `apps/web/app/api/auth/[...all]/route.ts`.
|
|
67
68
|
Everything else goes to `apps/api`.
|
|
68
69
|
|
|
69
70
|
## Forbidden
|
|
70
71
|
|
|
71
72
|
- Importing from `apps/api` or `apps/mcp` — these are peer apps;
|
|
72
73
|
speak to the API via `@working-theory/api-client`.
|
|
73
|
-
- Importing `@working-theory/database`
|
|
74
|
-
route through
|
|
74
|
+
- Importing `@working-theory/database` outside the Better Auth adapter
|
|
75
|
+
(the exception `.claude/rules/architecture.md` names) — route through
|
|
76
|
+
`apps/api`.
|
|
75
77
|
- Importing `resend`, `@react-email/*` directly — wrap through
|
|
76
78
|
`@working-theory/email`, server-side via `apps/api`.
|
|
77
79
|
- Adding a `utils.ts`, `helpers.ts`, `common.ts`, or `misc.ts` file
|
|
@@ -25,13 +25,16 @@ other.
|
|
|
25
25
|
or `@working-theory/schema` (schema.org types).
|
|
26
26
|
- Need an HTTP call from `apps/web` to `apps/api`? Use
|
|
27
27
|
`@working-theory/api-client`. Don't import API route handlers directly.
|
|
28
|
-
- Need database access?
|
|
29
|
-
`@working-theory/database`. `apps/web`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
- Need database access? `apps/api` and `apps/mcp` import
|
|
29
|
+
`@working-theory/database`. `apps/web` does not read the database — it goes
|
|
30
|
+
through `apps/api` via the published HTTP client. The one exception is the
|
|
31
|
+
Better Auth adapter (`apps/web/lib/prisma-for-auth.ts`, typed in
|
|
32
|
+
`apps/web/auth.ts`).
|
|
33
|
+
- Cross-cutting integrations (email, analytics) go through their
|
|
34
|
+
wrapper packages: `@working-theory/email`, `@working-theory/analytics`.
|
|
35
|
+
Never import `resend`, etc. directly. Auth has no wrapper package: it is
|
|
36
|
+
Better Auth, configured in `apps/web/auth.ts` and mounted at
|
|
37
|
+
`apps/web/app/api/auth/[...all]/route.ts`.
|
|
35
38
|
|
|
36
39
|
## What you can verify, what you can't
|
|
37
40
|
|
|
@@ -1,68 +1,95 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: add-auth
|
|
3
|
-
description: Activate
|
|
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
4
|
---
|
|
5
5
|
|
|
6
6
|
# add-auth
|
|
7
7
|
|
|
8
|
-
Activate one or more
|
|
9
|
-
vars
|
|
10
|
-
the OAuth-app-creation
|
|
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`.
|
|
11
15
|
|
|
12
16
|
## When to use
|
|
13
17
|
|
|
14
18
|
The user has a working AILK site (post-`pnpm create ailk`) and wants
|
|
15
|
-
to gate routes behind sign-in
|
|
16
|
-
|
|
19
|
+
to gate routes behind sign-in or accept email, Google or GitHub
|
|
20
|
+
sign-in. Phrases that should trigger this skill:
|
|
17
21
|
|
|
18
22
|
- "wire up auth" / "add login" / "set up sign-in"
|
|
19
23
|
- "I want users to log in"
|
|
20
24
|
- "enable Google sign-in" / "enable GitHub login"
|
|
21
|
-
- "set up magic-link auth"
|
|
25
|
+
- "set up email login" / "set up magic-link auth"
|
|
22
26
|
- "add OAuth"
|
|
23
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
|
+
|
|
24
33
|
Skip this skill when:
|
|
25
34
|
|
|
26
|
-
- The user wants a
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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.
|
|
32
42
|
- The user is in production and needs production callback URLs. v1
|
|
33
43
|
ships dev-mode callbacks (`http://localhost:3000`) only —
|
|
34
44
|
production callback setup is deferred to `setup-deploy`
|
|
35
45
|
or a future deploy skill. Note this and stop.
|
|
36
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
|
+
|
|
37
64
|
## What this skill does (and does not do)
|
|
38
65
|
|
|
39
66
|
**Does:**
|
|
40
67
|
|
|
41
|
-
- Reads `.env.local` to see which
|
|
42
|
-
- Asks the consumer which of the three
|
|
43
|
-
|
|
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_.
|
|
44
71
|
- For each picked provider, walks the consumer through
|
|
45
|
-
OAuth-app
|
|
46
|
-
(
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
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.
|
|
50
77
|
- Writes (or merges) a `RUNBOOK.md` in the consumer's repo root
|
|
51
78
|
with the same setup instructions the consumer just followed, so
|
|
52
79
|
they can refer back later or hand to a collaborator.
|
|
53
80
|
|
|
54
81
|
**Does not:**
|
|
55
82
|
|
|
56
|
-
- Modify `auth.
|
|
57
|
-
—
|
|
58
|
-
|
|
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.
|
|
59
86
|
- Create any new files under `app/`, `pages/`, or `content/`. The
|
|
60
87
|
emit is limited to `.env.local` writes and a `RUNBOOK.md` write.
|
|
61
88
|
- Set up production callback URLs. Dev-mode (`http://localhost:3000`)
|
|
62
89
|
only at v1.
|
|
63
|
-
- Add, remove, or modify any provider
|
|
64
|
-
|
|
65
|
-
|
|
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.
|
|
66
93
|
- Accept production OAuth credentials. If the consumer pastes a
|
|
67
94
|
production-looking secret, that's acceptable, but the runbook still
|
|
68
95
|
documents only the dev callback URL.
|
|
@@ -71,28 +98,28 @@ Skip this skill when:
|
|
|
71
98
|
|
|
72
99
|
### Step 1 — Show the menu
|
|
73
100
|
|
|
74
|
-
Greet the consumer and present the three
|
|
75
|
-
which are already
|
|
101
|
+
Greet the consumer and present the three provider ids, marking
|
|
102
|
+
which are already active (env vars present in `.env.local`):
|
|
76
103
|
|
|
77
104
|
```
|
|
78
|
-
Which
|
|
105
|
+
Which sign-in providers do you want to activate?
|
|
79
106
|
|
|
80
|
-
[ ]
|
|
81
|
-
[ ] Google OAuth
|
|
82
|
-
[ ] GitHub OAuth
|
|
107
|
+
[ ] email (email-and-password sign-in)
|
|
108
|
+
[ ] google (Google OAuth)
|
|
109
|
+
[ ] github (GitHub OAuth)
|
|
83
110
|
|
|
84
111
|
You can pick any subset, including "none of the above" (in which case
|
|
85
112
|
this skill exits without writing anything). You can also re-run this
|
|
86
|
-
skill later to activate more providers — already-
|
|
113
|
+
skill later to activate more providers — already-active providers
|
|
87
114
|
will be skipped automatically.
|
|
88
115
|
```
|
|
89
116
|
|
|
90
|
-
If `.env.local` already has any of these
|
|
117
|
+
If `.env.local` already has any of these active, mark them:
|
|
91
118
|
|
|
92
119
|
```
|
|
93
|
-
[x]
|
|
94
|
-
[ ] Google OAuth
|
|
95
|
-
[ ] GitHub OAuth
|
|
120
|
+
[x] email (already active — AUTH_EMAIL_SERVER + AUTH_EMAIL_FROM are set)
|
|
121
|
+
[ ] google (Google OAuth)
|
|
122
|
+
[ ] github (GitHub OAuth)
|
|
96
123
|
```
|
|
97
124
|
|
|
98
125
|
Wait for the consumer to pick a subset. Then, for each picked
|
|
@@ -100,12 +127,13 @@ provider, run the matching sub-flow.
|
|
|
100
127
|
|
|
101
128
|
### Step 2 — Run per-provider sub-flows
|
|
102
129
|
|
|
103
|
-
####
|
|
130
|
+
#### `email` sub-flow
|
|
104
131
|
|
|
105
|
-
1. Tell the consumer: _"
|
|
106
|
-
|
|
107
|
-
You'll need a Resend API key
|
|
108
|
-
Get one at
|
|
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>."_
|
|
109
137
|
2. Wait for the consumer to paste the API key.
|
|
110
138
|
3. Ask for the `AUTH_EMAIL_FROM` address. This must be a verified
|
|
111
139
|
sender on the consumer's Resend account. For development it's
|
|
@@ -118,16 +146,33 @@ provider, run the matching sub-flow.
|
|
|
118
146
|
AUTH_EMAIL_SERVER=smtp://resend:re_...@smtp.resend.com:465
|
|
119
147
|
AUTH_EMAIL_FROM=onboarding@resend.dev
|
|
120
148
|
```
|
|
121
|
-
|
|
122
|
-
|
|
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
|
|
123
168
|
|
|
124
169
|
1. Tell the consumer the steps in chat AND queue the same content for
|
|
125
170
|
the runbook (see Step 3). Steps:
|
|
126
171
|
- Go to <https://console.cloud.google.com/apis/credentials>.
|
|
127
172
|
- Click **Create Credentials → OAuth client ID**. If prompted,
|
|
128
173
|
configure the OAuth consent screen first (**External** → fill
|
|
129
|
-
name, support email, developer contact email;
|
|
130
|
-
|
|
174
|
+
name, support email, developer contact email; Better Auth
|
|
175
|
+
requests the scopes at runtime, so leave the scope list empty).
|
|
131
176
|
- Application type: **Web application**.
|
|
132
177
|
- Name: anything (e.g., "AILK dev").
|
|
133
178
|
- **Authorized redirect URIs** — add exactly:
|
|
@@ -141,7 +186,7 @@ provider, run the matching sub-flow.
|
|
|
141
186
|
GOOGLE_CLIENT_SECRET=...
|
|
142
187
|
```
|
|
143
188
|
|
|
144
|
-
####
|
|
189
|
+
#### `github` sub-flow
|
|
145
190
|
|
|
146
191
|
1. Tell the consumer the steps in chat AND queue the same content for
|
|
147
192
|
the runbook. Steps:
|
|
@@ -171,49 +216,56 @@ or refer back later.
|
|
|
171
216
|
Use `references/oauth-app-setup.md` as the template. Replace
|
|
172
217
|
`<provider>` headings as appropriate, and only include sections for
|
|
173
218
|
providers actually activated this session. If `RUNBOOK.md` already
|
|
174
|
-
exists with sections for already-
|
|
219
|
+
exists with sections for already-active providers, do not
|
|
175
220
|
duplicate — add only the new sections beneath any existing content.
|
|
176
221
|
|
|
177
|
-
### Step 4 —
|
|
222
|
+
### Step 4 — Check the database
|
|
178
223
|
|
|
179
|
-
|
|
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:
|
|
180
228
|
|
|
181
|
-
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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`.
|
|
185
238
|
|
|
186
|
-
State
|
|
239
|
+
State what you found in the closing summary so the consumer is never
|
|
187
240
|
surprised:
|
|
188
241
|
|
|
189
|
-
> "
|
|
190
|
-
>
|
|
191
|
-
>
|
|
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."
|
|
192
245
|
|
|
193
|
-
or
|
|
246
|
+
or, when `DATABASE_URL` is unset:
|
|
194
247
|
|
|
195
|
-
> "
|
|
196
|
-
>
|
|
197
|
-
> sessions, install `@working-theory/database` and add the `User` / `Session`
|
|
198
|
-
> models from `database/prisma/schema.prisma`."
|
|
248
|
+
> "Sign-in needs a database and none is configured yet. Run the
|
|
249
|
+
> `setup-database` skill before you try to sign in."
|
|
199
250
|
|
|
200
251
|
### Step 5 — Closing summary
|
|
201
252
|
|
|
202
253
|
Print:
|
|
203
254
|
|
|
204
|
-
- Which
|
|
205
|
-
already-
|
|
206
|
-
-
|
|
255
|
+
- Which provider ids are now active (subset picked this session +
|
|
256
|
+
already-active providers).
|
|
257
|
+
- What Step 4 found about the database.
|
|
207
258
|
- A reminder to set `AILK_AUTH_REQUIRED=1` in `.env.local` if they
|
|
208
259
|
want protected routes (default is auth-disabled / public).
|
|
209
260
|
- A pointer to `RUNBOOK.md` for future reference.
|
|
210
|
-
- A pointer to `setup-deploy` for production callback
|
|
211
|
-
|
|
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`.
|
|
212
264
|
|
|
213
265
|
## Re-invocation
|
|
214
266
|
|
|
215
267
|
The skill is idempotent. On a second run, the menu in Step 1 marks
|
|
216
|
-
already-
|
|
268
|
+
already-active providers with `[x]` (read from `.env.local`), and
|
|
217
269
|
the per-provider sub-flows skip those and only run for the new ones.
|
|
218
270
|
The closing summary lists everything, not just what changed this
|
|
219
271
|
session.
|
|
@@ -225,37 +277,37 @@ existing values in `.env.local`. Confirm before overwriting.
|
|
|
225
277
|
|
|
226
278
|
## Customization preservation
|
|
227
279
|
|
|
228
|
-
If `auth.
|
|
280
|
+
If `apps/web/auth.ts` has been modified by the consumer to add a
|
|
229
281
|
third-party provider (e.g., Apple), this skill leaves that file
|
|
230
|
-
completely untouched. The skill never
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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.
|
|
234
286
|
|
|
235
287
|
## What "activation" means under the hood
|
|
236
288
|
|
|
237
|
-
- **
|
|
238
|
-
`apps/web/auth.
|
|
239
|
-
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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).
|
|
243
296
|
- A site with zero auth env vars boots cleanly with no active
|
|
244
|
-
providers (`
|
|
297
|
+
providers (`getActiveProviderIds()` returns an empty array).
|
|
245
298
|
|
|
246
299
|
This means the skill's job is purely env-var wiring + documentation.
|
|
247
300
|
|
|
248
301
|
## References
|
|
249
302
|
|
|
250
303
|
- `references/oauth-app-setup.md` — RUNBOOK template the skill instantiates per session.
|
|
251
|
-
- `references/env-vars.md` — env-var contract (which vars activate which provider).
|
|
304
|
+
- `references/env-vars.md` — env-var contract (which vars activate which provider id).
|
|
252
305
|
|
|
253
306
|
## Coordination
|
|
254
307
|
|
|
255
|
-
- **`add-page`** —
|
|
256
|
-
|
|
257
|
-
- **`setup-
|
|
258
|
-
|
|
259
|
-
-
|
|
260
|
-
|
|
261
|
-
sessions.
|
|
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.
|
|
@@ -32,12 +32,20 @@ env-presence signal: it switches on the password method
|
|
|
32
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
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
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. |
|
|
35
38
|
|
|
36
|
-
The skill writes none of these auxiliary vars
|
|
39
|
+
The skill writes none of these auxiliary vars unasked. It mentions
|
|
37
40
|
them in the closing summary so the consumer is aware:
|
|
38
41
|
|
|
39
42
|
- `AILK_AUTH_REQUIRED` is the consumer's call (skill always defaults
|
|
40
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.
|
|
41
49
|
- `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET` are deferred to
|
|
42
50
|
production-time setup (`setup-deploy`), and a production deploy
|
|
43
51
|
fails without `BETTER_AUTH_SECRET`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# OAuth +
|
|
1
|
+
# OAuth + Email Sign-In Setup — RUNBOOK Template
|
|
2
2
|
|
|
3
3
|
The `add-auth` skill writes (or merges into) `RUNBOOK.md` at the
|
|
4
4
|
consumer's repo root using the per-provider sections below. Only the
|
|
@@ -10,13 +10,13 @@ sections appear in the final runbook.
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## Provider section:
|
|
13
|
+
## Provider section: email (Resend)
|
|
14
14
|
|
|
15
15
|
```markdown
|
|
16
|
-
## Auth —
|
|
16
|
+
## Auth — email sign-in (Resend)
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
Email-and-password sign-in is activated when both env vars are present
|
|
19
|
+
in `.env.local`:
|
|
20
20
|
|
|
21
21
|
- `AUTH_EMAIL_SERVER` — `smtp://resend:<API_KEY>@smtp.resend.com:465`
|
|
22
22
|
- `AUTH_EMAIL_FROM` — verified sender address on your Resend account
|
|
@@ -30,6 +30,14 @@ keyed off two env vars in `.env.local`:
|
|
|
30
30
|
Resend's shared dev sender and works without verification. For
|
|
31
31
|
production, verify your own sending domain in the Resend dashboard.
|
|
32
32
|
|
|
33
|
+
`AUTH_EMAIL_SERVER` is read for its presence only. The auth mail
|
|
34
|
+
(verification, password reset) is sent by `apps/api` with
|
|
35
|
+
`RESEND_API_KEY` from `AUTH_EMAIL_FROM`, so set both for the API, and
|
|
36
|
+
set `AUTH_EMAIL_WEBHOOK_SECRET` to the same random value for both apps.
|
|
37
|
+
|
|
38
|
+
Public sign-up stays closed until you set `AILK_AUTH_SIGNUP_OPEN=1` in
|
|
39
|
+
`.env.local`.
|
|
40
|
+
|
|
33
41
|
### `.env.local` entries
|
|
34
42
|
|
|
35
43
|
\`\`\`
|
|
@@ -152,7 +160,7 @@ The Client ID stays the same.
|
|
|
152
160
|
|
|
153
161
|
| Provider | Env vars | Active |
|
|
154
162
|
| ----------- | ------------------------------------------------- | ------ |
|
|
155
|
-
|
|
|
163
|
+
| email | `AUTH_EMAIL_SERVER` + `AUTH_EMAIL_FROM` | <fill> |
|
|
156
164
|
| Google | `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` | <fill> |
|
|
157
165
|
| GitHub | `GITHUB_CLIENT_ID` + `GITHUB_CLIENT_SECRET` | <fill> |
|
|
158
166
|
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
<!-- GENERATED — do not hand-edit.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Generator: packages/create-ailk/scripts/generate-page-types-reference.ts
|
|
1
|
+
<!-- GENERATED — do not hand-edit. AI Launch Kit generates this file
|
|
2
|
+
from its page-type registry and ships it with the scaffold. The
|
|
3
|
+
source of record for this site's own page-type registry is `pageTypeRegistry` in the installed `@working-theory/schema` package.
|
|
5
4
|
-->
|
|
6
5
|
|
|
7
6
|
# Page-Type → schema.org Registry Reference
|
|
8
7
|
|
|
9
8
|
The full page-type catalog the `add-page` skill reads at runtime to
|
|
10
9
|
resolve a slug or page-purpose hint to a family, chassis, schema.org
|
|
11
|
-
`@type`, and route convention. Generated from
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
`@type`, and route convention. Generated from the page-type registry
|
|
11
|
+
`@working-theory/schema` exports — every registered page type appears
|
|
12
|
+
exactly once, list/detail pairs are shown together, and no row here
|
|
13
|
+
can name a type the registry doesn't have.
|
|
15
14
|
|
|
16
15
|
The skill resolves in this order:
|
|
17
16
|
|
|
@@ -30,8 +29,8 @@ levels). The level is the module's, never a claim about this site's key.
|
|
|
30
29
|
`<slug>` in a route below is the page's own slug (e.g. `hello-world`);
|
|
31
30
|
`<Type>` families using two-layer builders route supplementary schema
|
|
32
31
|
through the `schema:` frontmatter override — see this skill's
|
|
33
|
-
[Adding schema to an existing page](../SKILL.md#adding-schema-to-an-existing-page) section, or
|
|
34
|
-
override contract.
|
|
32
|
+
[Adding schema to an existing page](../SKILL.md#adding-schema-to-an-existing-page) section, or the installed `@working-theory/schema`
|
|
33
|
+
package's README for the full override contract.
|
|
35
34
|
|
|
36
35
|
## Core
|
|
37
36
|
|