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.
- package/README.md +7 -2
- package/dist/cli.js +5 -1
- package/dist/content-payloads.d.ts +37 -0
- package/dist/content-payloads.js +64 -0
- package/dist/lib/fetch-module.d.ts +3 -3
- package/dist/lib/fetch-module.js +11 -5
- package/dist/lib/fetch-template.d.ts +1 -1
- package/dist/lib/fetch-template.js +7 -4
- package/dist/lib/scaffold-render-sweep.d.ts +16 -0
- package/dist/lib/scaffold-render-sweep.js +52 -3
- package/dist/module-architecture.d.ts +9 -0
- package/dist/module-architecture.js +43 -12
- package/dist/parse-args.d.ts +2 -0
- package/dist/parse-args.js +7 -0
- package/dist/surfaces.js +2 -3
- package/package.json +3 -3
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +4 -3
- package/site-templates/shapes/local-business-service/content/en/Service/first-job.mdx +8 -8
- package/site-templates/shapes/local-business-service/content/en/Service/second-job.mdx +8 -8
- package/site-templates/shapes/local-business-service/content/en/Service/third-job.mdx +8 -8
- package/site-templates/shapes/organization-service/content/en/Service/first-engagement.mdx +8 -8
- package/site-templates/shapes/organization-service/content/en/Service/second-engagement.mdx +8 -8
- package/site-templates/shapes/organization-service/content/en/Service/third-engagement.mdx +8 -8
- package/site-templates/shapes/person-service/content/en/Service/first-engagement.mdx +8 -8
- package/site-templates/shapes/person-service/content/en/Service/second-engagement.mdx +8 -8
- package/site-templates/shapes/person-service/content/en/Service/third-engagement.mdx +8 -8
- package/templates/.claude/settings.json +12 -0
- package/templates/.env.example +1 -5
- package/templates/CLAUDE.md +38 -22
- package/templates/README.md +12 -12
- package/templates/apps/api/jest.config.cjs +1 -0
- package/templates/apps/api/package.json +2 -1
- package/templates/apps/mcp/CLAUDE.md +23 -10
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +160 -17
- package/templates/apps/mcp/__tests__/index.test.ts +118 -1
- package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +425 -5
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +67 -3
- package/templates/apps/mcp/__tests__/server.test.ts +162 -1
- package/templates/apps/mcp/package.json +1 -1
- package/templates/apps/mcp/src/index.ts +35 -3
- package/templates/apps/mcp/src/lib/commerce-claim.ts +193 -24
- package/templates/apps/mcp/src/server.ts +77 -5
- package/templates/apps/mcp/src/tools/purchase.ts +1 -1
- package/templates/apps/web/CLAUDE.md +1 -1
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +15 -0
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +10 -3
- package/templates/apps/web/app/[locale]/careers/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/case-studies/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/courses/[slug]/page.tsx +1 -14
- package/templates/apps/web/app/[locale]/events/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/features/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/for/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/how-to/[slug]/page.tsx +1 -14
- package/templates/apps/web/app/[locale]/integrations/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/partners/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/portfolio/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/products/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/projects/[slug]/page.tsx +1 -15
- package/templates/apps/web/app/[locale]/resources/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/services/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/software/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/tech-articles/[slug]/page.tsx +1 -14
- package/templates/apps/web/app/[locale]/thanks/[slug]/page.tsx +4 -16
- package/templates/apps/web/app/[locale]/vs/[slug]/__tests__/page.test.tsx +3 -15
- package/templates/apps/web/app/[locale]/vs/[slug]/page.tsx +0 -10
- package/templates/apps/web/app/[locale]/whitepapers/[slug]/page.tsx +1 -14
- package/templates/apps/web/src/lib/commerce-claim.ts +15 -6
- package/templates/content/_site.mdx +23 -4
- package/templates/database/CHANGELOG.md +7 -0
- package/templates/database/package.json +1 -1
- package/versions.json +34 -34
- package/templates/.claude/skills/README.md +0 -37
- package/templates/.claude/skills/add-auth/SKILL.md +0 -313
- package/templates/.claude/skills/add-auth/references/env-vars.md +0 -106
- package/templates/.claude/skills/add-auth/references/oauth-app-setup.md +0 -180
- package/templates/.claude/skills/add-page/SKILL.md +0 -260
- package/templates/.claude/skills/add-page/references/page-types.md +0 -123
- package/templates/.claude/skills/add-page/scripts/site-pages.mjs +0 -87
- package/templates/.claude/skills/add-page/templates/comparison-page.mdx.tmpl +0 -99
- package/templates/.claude/skills/add-page/templates/content.mdx.tmpl +0 -18
- package/templates/.claude/skills/add-page/templates/flow-landing-page.mdx.tmpl +0 -43
- package/templates/.claude/skills/add-page/templates/report-page.mdx.tmpl +0 -52
- package/templates/.claude/skills/add-page/templates/reports-list.mdx.tmpl +0 -38
- package/templates/.claude/skills/check-site/SKILL.md +0 -245
- package/templates/.claude/skills/check-site/references/common-errors.md +0 -116
- package/templates/.claude/skills/check-site/references/findings-glossary.md +0 -140
- package/templates/.claude/skills/check-site/references/severity-levels.md +0 -114
- package/templates/.claude/skills/fill-page/SKILL.md +0 -199
- package/templates/.claude/skills/fill-page/profiles/plumbing.yaml +0 -80
- package/templates/.claude/skills/fill-page/references/section-sources.md +0 -41
- package/templates/.claude/skills/setup-database/SKILL.md +0 -156
- package/templates/.claude/skills/setup-database/scripts/verify-inbox.ts +0 -154
- package/templates/.claude/skills/setup-deploy/SKILL.md +0 -312
- package/templates/.claude/skills/setup-deploy/references/runbook-template.md +0 -204
- package/templates/.claude/skills/setup-deploy/references/vercel-json-template.md +0 -98
- package/templates/.claude/skills/update-page/SKILL.md +0 -117
- package/templates/.claude/skills/update-page/scripts/update-page.ts +0 -640
- package/templates/.claude/skills/update-page/templates/redirects.mjs.tmpl +0 -31
- package/templates/.claude/skills/upgrade-plan/SKILL.md +0 -121
- package/templates/.claude/skills/upgrade-plan/references/options.md +0 -24
- package/templates/.claude/skills/upgrade-plan/scripts/upgrade-plan.ts +0 -527
- package/templates/apps/mcp/__tests__/lib/require-paid-tier.test.ts +0 -75
- package/templates/apps/mcp/src/lib/require-paid-tier.ts +0 -44
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
# `RUNBOOK.md` Template
|
|
2
|
-
|
|
3
|
-
The `setup-deploy` skill emits this runbook at the consumer's
|
|
4
|
-
project root. It documents pre-deploy steps and where the site's
|
|
5
|
-
leads go — the two lead destinations, **Email (default)** and
|
|
6
|
-
**Lead inbox (setup-database)**.
|
|
7
|
-
|
|
8
|
-
The skill must verify both lead-destination headings are present
|
|
9
|
-
after emit (per SKILL.md Step 6 validation). If either is missing,
|
|
10
|
-
the skill has a bug.
|
|
11
|
-
|
|
12
|
-
## Template
|
|
13
|
-
|
|
14
|
-
```markdown
|
|
15
|
-
# RUNBOOK — Production Operations
|
|
16
|
-
|
|
17
|
-
This runbook is generated by the `setup-deploy` skill. It covers
|
|
18
|
-
what to do before and after deploying to Vercel, plus the
|
|
19
|
-
operational caveats AILK ships with.
|
|
20
|
-
|
|
21
|
-
If you re-run `setup-deploy`, new sections may be appended at
|
|
22
|
-
the end under "## Added by setup-deploy." Existing sections are
|
|
23
|
-
not modified by the skill.
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Pre-deploy checklist
|
|
28
|
-
|
|
29
|
-
Before you click Deploy in Vercel:
|
|
30
|
-
|
|
31
|
-
- [ ] **Add a Vercel project** pointed at this repo
|
|
32
|
-
(`vercel link` from the CLI, or the dashboard).
|
|
33
|
-
- [ ] **Set environment variables** in Vercel's project dashboard
|
|
34
|
-
(Settings → Environment Variables). Use `.env.example` as the
|
|
35
|
-
contract — every variable listed there should have a value
|
|
36
|
-
set in Vercel before deploy.
|
|
37
|
-
- [ ] **Configure your custom domain** if you have one (Vercel
|
|
38
|
-
Project → Settings → Domains). Vercel handles TLS automatically.
|
|
39
|
-
- [ ] **Pick where leads go** — see "Leads — where messages go"
|
|
40
|
-
below. With neither an email key nor a database, your contact
|
|
41
|
-
page shows your contact email instead of the form in
|
|
42
|
-
production, and no messages are collected.
|
|
43
|
-
- [ ] **On a host other than Vercel**, set `NODE_ENV=production` on
|
|
44
|
-
the API process — that is how it knows it is in production.
|
|
45
|
-
- [ ] **Register production OAuth callbacks** if you used
|
|
46
|
-
`add-auth` and activated Google or GitHub. Each provider
|
|
47
|
-
needs the prod callback URL added to its OAuth app settings.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Leads — where messages go
|
|
52
|
-
|
|
53
|
-
Where a contact-form message goes depends only on what you set on
|
|
54
|
-
the **API** project:
|
|
55
|
-
|
|
56
|
-
| You set | A message… |
|
|
57
|
-
| ----------------------------------------- | -------------------------------------------- |
|
|
58
|
-
| `DATABASE_URL` | lands in your lead inbox at `/leads` |
|
|
59
|
-
| the three email variables, no database | is emailed to you |
|
|
60
|
-
| neither (production) | is not collected — `/contact` shows your contact email instead of the form |
|
|
61
|
-
| neither (`pnpm dev`) | is written to a local file, for testing |
|
|
62
|
-
|
|
63
|
-
A newsletter signup needs the database: without one, `/newsletter`
|
|
64
|
-
offers no signup form. A visitor is never told a message was sent
|
|
65
|
-
when it reached nobody.
|
|
66
|
-
|
|
67
|
-
### Email (default)
|
|
68
|
-
|
|
69
|
-
**When to pick:** you want messages in your inbox with no database
|
|
70
|
-
to run. This is the default for a new site.
|
|
71
|
-
|
|
72
|
-
**Setup:**
|
|
73
|
-
|
|
74
|
-
1. Create an API key at <https://resend.com/api-keys> and verify the
|
|
75
|
-
domain you will send from (Resend Dashboard → Domains).
|
|
76
|
-
2. On the **API** project in Vercel (Settings → Environment
|
|
77
|
-
Variables), set:
|
|
78
|
-
- `RESEND_API_KEY` — the key.
|
|
79
|
-
- `AILK_LEAD_NOTIFICATION_TO` — the address messages go to (yours).
|
|
80
|
-
- `AILK_LEAD_NOTIFICATION_FROM` — a sender on your verified domain.
|
|
81
|
-
3. Redeploy the API.
|
|
82
|
-
|
|
83
|
-
All three are required: a key without both addresses sends nothing.
|
|
84
|
-
If Resend refuses a message, the visitor is told it could not be
|
|
85
|
-
sent, so they can try again or email you directly.
|
|
86
|
-
|
|
87
|
-
### Lead inbox (setup-database)
|
|
88
|
-
|
|
89
|
-
**When to pick:** you want every message kept, searchable, in a
|
|
90
|
-
lead inbox you review signed in — and newsletter signups collected.
|
|
91
|
-
|
|
92
|
-
**Setup:** run the `setup-database` skill ("set up the database"). It
|
|
93
|
-
walks you through provisioning Postgres, setting `DATABASE_URL`,
|
|
94
|
-
running migrations, pinning you as the owner
|
|
95
|
-
(`AILK_OPERATOR_EMAIL`), and sending one test message that must
|
|
96
|
-
appear in `/leads` before it reports done. If the email variables
|
|
97
|
-
are also set, you still get an email for each new lead.
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## Custom domain + DNS
|
|
102
|
-
|
|
103
|
-
Vercel handles TLS automatically once a domain is added to your
|
|
104
|
-
project. Two paths:
|
|
105
|
-
|
|
106
|
-
- **Vercel-managed DNS** — let Vercel handle nameservers. Easiest;
|
|
107
|
-
Vercel Dashboard → Project → Settings → Domains → Add → "Manage
|
|
108
|
-
DNS Records."
|
|
109
|
-
- **External DNS** — add an A record (or CNAME for subdomains)
|
|
110
|
-
pointing at Vercel's IP, then add the domain to your project.
|
|
111
|
-
Vercel docs walk through it.
|
|
112
|
-
|
|
113
|
-
For email-sending domains (Resend, magic-link), you'll also need
|
|
114
|
-
to verify the sending domain in Resend's dashboard before
|
|
115
|
-
production magic-link emails will deliver. Resend Dashboard →
|
|
116
|
-
Domains → Add → DNS records → wait for verification.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Production callbacks for OAuth (if you used `add-auth`)
|
|
121
|
-
|
|
122
|
-
If you activated Google or GitHub OAuth via `add-auth`,
|
|
123
|
-
those activations used dev callback URLs (`localhost:3000`). For
|
|
124
|
-
production, add the prod callback URLs to each OAuth app:
|
|
125
|
-
|
|
126
|
-
### Google
|
|
127
|
-
|
|
128
|
-
1. Open the Google Cloud Console OAuth client you created
|
|
129
|
-
(<https://console.cloud.google.com/apis/credentials>).
|
|
130
|
-
2. Under **Authorized redirect URIs**, add:
|
|
131
|
-
`https://<your-prod-domain>/api/auth/callback/google`
|
|
132
|
-
3. Save.
|
|
133
|
-
|
|
134
|
-
### GitHub
|
|
135
|
-
|
|
136
|
-
1. Open the GitHub OAuth App you created
|
|
137
|
-
(<https://github.com/settings/developers>).
|
|
138
|
-
2. Edit either:
|
|
139
|
-
- The same app's **Authorization callback URL** to add a second
|
|
140
|
-
line for prod (GitHub allows multiple).
|
|
141
|
-
- Or create a separate OAuth App for production.
|
|
142
|
-
3. Update the env vars in Vercel if you created a separate app.
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## When to redeploy
|
|
147
|
-
|
|
148
|
-
- After changing any `NEXT_PUBLIC_*` env var (those bake at build
|
|
149
|
-
time).
|
|
150
|
-
- After running database migrations (data shape changed).
|
|
151
|
-
- After updating `vercel.json` (deploy config changed).
|
|
152
|
-
|
|
153
|
-
You do **not** need to redeploy after:
|
|
154
|
-
|
|
155
|
-
- Adding a non-`NEXT_PUBLIC_*` env var in Vercel's dashboard
|
|
156
|
-
(server-side reads pick it up on next request).
|
|
157
|
-
- Editing MDX content in `content/` and pushing — Vercel rebuilds
|
|
158
|
-
on push.
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Troubleshooting
|
|
163
|
-
|
|
164
|
-
- **"My contact page shows an email address instead of the form"**
|
|
165
|
-
→ the API has no lead destination. Set the three email variables,
|
|
166
|
-
or run `setup-database` (see "Leads — where messages go").
|
|
167
|
-
- **"OAuth login redirects to localhost in production"** → you
|
|
168
|
-
haven't added the production callback URL to the OAuth app
|
|
169
|
-
(see above).
|
|
170
|
-
- **"Magic-link emails aren't arriving in production"** → your
|
|
171
|
-
Resend sender domain isn't verified yet (Resend Dashboard →
|
|
172
|
-
Domains).
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
## Section headings the validation must find
|
|
178
|
-
|
|
179
|
-
After emit, the skill must grep for these two headings (verbatim
|
|
180
|
-
match). Both must be present:
|
|
181
|
-
|
|
182
|
-
- `### Email (default)`
|
|
183
|
-
- `### Lead inbox (setup-database)`
|
|
184
|
-
|
|
185
|
-
If either is missing, the template was edited in a way that broke
|
|
186
|
-
the contract. Surface the failure to the consumer (not silent).
|
|
187
|
-
|
|
188
|
-
## Merge logic
|
|
189
|
-
|
|
190
|
-
If the consumer already has `RUNBOOK.md`, the skill (per SKILL.md
|
|
191
|
-
Step 3) offers merge / overwrite / skip. Merge logic:
|
|
192
|
-
|
|
193
|
-
1. Read the existing file.
|
|
194
|
-
2. Check whether the "Leads — where messages go" section and its two
|
|
195
|
-
lead-destination headings are already present.
|
|
196
|
-
3. Headings already present → not modified.
|
|
197
|
-
4. Headings missing → append at the end of the existing file under:
|
|
198
|
-
```
|
|
199
|
-
## Added by setup-deploy
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
The pre-deploy checklist, custom-domain, and OAuth-prod-callbacks
|
|
203
|
-
sections are also appended if missing. Sections that are already
|
|
204
|
-
present (even with different content) are not modified.
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# `vercel.json` Template
|
|
2
|
-
|
|
3
|
-
The minimal viable Vercel config the `setup-deploy` skill emits.
|
|
4
|
-
Customization beyond this template is the consumer's responsibility —
|
|
5
|
-
the skill's job is to ship the consumer with a working baseline.
|
|
6
|
-
|
|
7
|
-
## Template
|
|
8
|
-
|
|
9
|
-
```json
|
|
10
|
-
{
|
|
11
|
-
"version": 2,
|
|
12
|
-
"framework": "nextjs",
|
|
13
|
-
"buildCommand": "pnpm build",
|
|
14
|
-
"installCommand": "pnpm install --frozen-lockfile",
|
|
15
|
-
"env": {}
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Field-by-field
|
|
20
|
-
|
|
21
|
-
### `version: 2`
|
|
22
|
-
|
|
23
|
-
Required. Vercel config schema version. Always `2` at v1.
|
|
24
|
-
|
|
25
|
-
### `framework: "nextjs"`
|
|
26
|
-
|
|
27
|
-
The skill assumes the consumer's `apps/web` is a Next.js app (the
|
|
28
|
-
AILK scaffold default). Other valid values exist in Vercel's docs
|
|
29
|
-
but the skill emits `nextjs` only. Consumers on bespoke setups can
|
|
30
|
-
overwrite the file post-emission.
|
|
31
|
-
|
|
32
|
-
### `buildCommand`
|
|
33
|
-
|
|
34
|
-
The default `pnpm build` works for single-app deploys (the AILK
|
|
35
|
-
scaffold's `apps/web` is the deploy target). For monorepo deploys
|
|
36
|
-
where the consumer wants Vercel to build the whole tree, suggest
|
|
37
|
-
the consumer change this to:
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
cd ../.. && pnpm install --frozen-lockfile && pnpm --filter ./apps/web build
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
The skill does NOT auto-detect monorepo vs single-app — the consumer
|
|
44
|
-
edits the field if their setup deviates. Surface the alternative as
|
|
45
|
-
a comment in the chat after emit, not in the JSON file (JSON has
|
|
46
|
-
no comments).
|
|
47
|
-
|
|
48
|
-
### `installCommand`
|
|
49
|
-
|
|
50
|
-
Default `pnpm install --frozen-lockfile`. Match the consumer's
|
|
51
|
-
package manager:
|
|
52
|
-
|
|
53
|
-
- pnpm — `pnpm install --frozen-lockfile`
|
|
54
|
-
- npm — `npm ci`
|
|
55
|
-
- yarn — `yarn install --frozen-lockfile`
|
|
56
|
-
|
|
57
|
-
The skill detects the package manager by checking for `pnpm-lock.yaml`,
|
|
58
|
-
`package-lock.json`, or `yarn.lock` at the project root. Default
|
|
59
|
-
to pnpm if none is found (AILK scaffold ships pnpm).
|
|
60
|
-
|
|
61
|
-
### `env: {}`
|
|
62
|
-
|
|
63
|
-
Empty by default. Vercel's project-level env-var dashboard is the
|
|
64
|
-
canonical place to set production values — `.env.example` is the
|
|
65
|
-
contract, the dashboard is the values.
|
|
66
|
-
|
|
67
|
-
If the consumer specifically asks for build-time env-var defaults
|
|
68
|
-
(e.g., `NODE_ENV: "production"`), the skill can populate the field.
|
|
69
|
-
But the default is empty.
|
|
70
|
-
|
|
71
|
-
## What this template intentionally omits
|
|
72
|
-
|
|
73
|
-
- **`routes`** — Next.js App Router handles routing; `vercel.json`
|
|
74
|
-
routing is for non-Next.js apps. AILK is Next.js.
|
|
75
|
-
- **`outputDirectory`** — Vercel auto-detects `.next` for Next.js.
|
|
76
|
-
- **`functions`** — per-function config is rarely needed for AILK's
|
|
77
|
-
shape. Consumers who need it (long-running cron, large payload
|
|
78
|
-
tolerances) edit post-emission.
|
|
79
|
-
- **`regions`** — Vercel's default multi-region routing is fine for
|
|
80
|
-
AILK at v1. Consumers with strict latency requirements add this
|
|
81
|
-
themselves.
|
|
82
|
-
- **`crons`** — AILK doesn't ship scheduled jobs. Consumer-added
|
|
83
|
-
crons go in post-emit edits.
|
|
84
|
-
|
|
85
|
-
The template is small on purpose. A 100-line `vercel.json` carries a
|
|
86
|
-
maintenance cost the consumer didn't ask for. Five fields is enough
|
|
87
|
-
to deploy.
|
|
88
|
-
|
|
89
|
-
## Validation after emit
|
|
90
|
-
|
|
91
|
-
After writing, the skill must:
|
|
92
|
-
|
|
93
|
-
1. Parse the file as JSON. If it fails to parse, the skill has a bug
|
|
94
|
-
(the template is hand-authored JSON; a parse failure means the
|
|
95
|
-
template was edited in a way that broke it).
|
|
96
|
-
2. Confirm the field count matches the template (5 fields). Extra
|
|
97
|
-
fields are fine if the consumer's existing file had more (in
|
|
98
|
-
merge mode, but `vercel.json` doesn't merge — see SKILL.md Step 3).
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: update-page
|
|
3
|
-
description: Rename a page on this AI Launch Kit site — change its URL (/meet to /schedule, /team to /people) and/or its title — safely, in one plan-then-confirm pass. Use this whenever the user wants to move, rename, re-slug or re-title an existing page, even if they don't say "rename" — "make /meet be /schedule", "the booking page should live at /book", "call the team page People", "I don't like this URL". It moves the content file(s), the page's own route folder if it has one, every exact internal link, the site-manifest row, and adds a permanent redirect from the old URL. It refuses pages whose URL is fixed by their type or shipped by the scaffold. Not for adding a page (add-page) or rewriting its words (fill-page).
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# update-page
|
|
7
|
-
|
|
8
|
-
Move a page from `/old` to `/new` (and optionally give it a new title) without
|
|
9
|
-
leaving a dead link, a stale manifest row, or a broken inbound URL behind. A
|
|
10
|
-
bundled helper computes the whole change as a plan; you show the plan, the user
|
|
11
|
-
confirms once, and only then does anything get written.
|
|
12
|
-
|
|
13
|
-
## The one rule
|
|
14
|
-
|
|
15
|
-
**Never run `apply` before the user has seen the plan and confirmed it.** The
|
|
16
|
-
helper enforces this mechanically — `apply` requires the hash the plan printed,
|
|
17
|
-
and refuses any other — but the order is yours to keep:
|
|
18
|
-
plan → show the file list → wait for confirmation → apply with the plan hash.
|
|
19
|
-
|
|
20
|
-
## Step 1 — Plan
|
|
21
|
-
|
|
22
|
-
From the site root:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
pnpm exec tsx .claude/skills/update-page/scripts/update-page.ts plan --from /meet --to /schedule
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Add `--name "Book a time"` to also change the page's title (the `title:` in its
|
|
29
|
-
content file; it sets the English file only and reports other languages as
|
|
30
|
-
"title left as translated").
|
|
31
|
-
|
|
32
|
-
The helper prints:
|
|
33
|
-
|
|
34
|
-
- every file it would touch, tagged `move`, `modify`, `create` or `delete`;
|
|
35
|
-
- `note:` lines a reader should know about (see below);
|
|
36
|
-
- `hash: <sha256>` — the plan's fingerprint.
|
|
37
|
-
|
|
38
|
-
It writes nothing. If it prints `refused: …` and exits 3, stop there and tell
|
|
39
|
-
the user why (the reasons are below). Don't work around a refusal by hand.
|
|
40
|
-
|
|
41
|
-
## Step 2 — Show the plan and wait
|
|
42
|
-
|
|
43
|
-
Show the user the file list and the notes as printed. If they want to see the
|
|
44
|
-
new contents, `plan --json` prints every change with its full new content.
|
|
45
|
-
Then wait for one confirmation. A "yes" to the summary is enough; you don't
|
|
46
|
-
need per-file approval.
|
|
47
|
-
|
|
48
|
-
## Step 3 — Apply
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
pnpm exec tsx .claude/skills/update-page/scripts/update-page.ts apply --from /meet --to /schedule --confirm <hash>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Pass the same `--from`, `--to` and `--name` as the plan. The helper re-plans
|
|
55
|
-
and compares hashes: if anything changed in between (a file was edited, a
|
|
56
|
-
different rename was planned), it exits 1 and writes nothing — run `plan` again
|
|
57
|
-
and confirm the new hash.
|
|
58
|
-
|
|
59
|
-
## Step 4 — Check and report
|
|
60
|
-
|
|
61
|
-
Run `pnpm build` from the site root. Then tell the user:
|
|
62
|
-
|
|
63
|
-
- the new URL (with the locale, e.g. `/en/schedule`), and that `/meet` now
|
|
64
|
-
answers with a permanent redirect (HTTP 308) to it;
|
|
65
|
-
- any `note:` lines that need their attention (below);
|
|
66
|
-
- that the nav label text lives in `apps/web/messages/<locale>.json` if they
|
|
67
|
-
also want the menu wording changed — this skill only re-points the link.
|
|
68
|
-
|
|
69
|
-
## What the plan changes
|
|
70
|
-
|
|
71
|
-
| Surface | What happens |
|
|
72
|
-
|---|---|
|
|
73
|
-
| `content/<locale>/<Type>/old.mdx` (every locale) | Renamed to `new.mdx`; its `slug:` updated; `title:` updated when `--name` is given |
|
|
74
|
-
| The page's own route folder, when a folder under `apps/web/app` serves `/old` and is not a route the scaffold ships (a page the catch-all route serves has none) | Moved to the sibling folder `new/`; the `getPage("old")` literal inside becomes `getPage("new")` |
|
|
75
|
-
| Exact links to `/old` in `content/**` and `apps/web/lib/nav-config.ts` | Rewritten to `/new`. Exact means the whole path: `/meet` is rewritten, `/meet/book-a-call` and `/meeting` are not |
|
|
76
|
-
| `.ailk-site-manifest.json` | The one row whose `route` is `/old` now reads `/new`; no other byte changes |
|
|
77
|
-
| `apps/web/next.config.mjs` `redirects()` | Gains a managed block (`ailk:page-renames`) with `{ from: "/old", to: "/new" }`. Locale-prefixed forms are added for every non-default locale. A second rename collapses chains: renaming `/schedule` to `/book` later re-points the `/meet` row straight to `/book` |
|
|
78
|
-
|
|
79
|
-
Links to `/old` in code files (`apps/web/app`, `lib`, `components`) are
|
|
80
|
-
reported, not rewritten — the redirect covers them, and code edits are the
|
|
81
|
-
owner's call.
|
|
82
|
-
|
|
83
|
-
## The notes, and what to say about them
|
|
84
|
-
|
|
85
|
-
- **"…belongs to the `<module>` module's routes…"** — the old or new URL is a
|
|
86
|
-
route a paid module (scheduling, docs-blog, …) would install if the site
|
|
87
|
-
adds it later. Tell the user: if they add that module, the redirect (for the
|
|
88
|
-
old URL) or the module's folder (for the new URL) will take over, and the
|
|
89
|
-
note says what to remove or rename first.
|
|
90
|
-
- **"add-module `<module>` will keep these edited placeholder files…"** — the
|
|
91
|
-
rename edited seed pages that a module would normally replace; the module
|
|
92
|
-
will now list them for review instead. Nothing is lost.
|
|
93
|
-
- **"add-module will no longer regenerate the nav…"** — the nav is now a
|
|
94
|
-
hand-edited file; later module installs report the nav change they wanted
|
|
95
|
-
rather than applying it.
|
|
96
|
-
- **"the pages under /old … keep their URLs"** — detail pages like
|
|
97
|
-
`/meet/book-a-call` are fixed by their type and stay where they are.
|
|
98
|
-
|
|
99
|
-
## When the helper refuses (exit 3)
|
|
100
|
-
|
|
101
|
-
| Reason | What it means | What to offer instead |
|
|
102
|
-
|---|---|---|
|
|
103
|
-
| `routes must be one lowercase segment` | Only a top-level page moves (`/meet`, not `/meet/book-a-call`) | Detail pages are fixed by their type |
|
|
104
|
-
| `no page at /old` | Nothing on the site is served there | Check the URL; `add-page` adds a page |
|
|
105
|
-
| `/old is a code route with no page content to move` | A route folder exists but no content page backs it | A code change, not a rename |
|
|
106
|
-
| `a <Type> page's URL is fixed by its type` | About, Contact, a Service, a booking page — their URL comes from the page type | Explain that these can't move; the title can still change in the content file |
|
|
107
|
-
| `/old is served by a route the scaffold ships` | The route folder came with the scaffold (e.g. `/pricing`) | Same as above |
|
|
108
|
-
| `/new already exists: …` | A route folder, another page, or a content locale directory owns `/new` | Pick another route |
|
|
109
|
-
| `redirects() has been edited` | Someone hand-edited `redirects()` in `next.config.mjs`, so the helper won't touch it | Add the redirect line the message gives, by hand, or restore the generated method |
|
|
110
|
-
|
|
111
|
-
## What this skill does not do
|
|
112
|
-
|
|
113
|
-
- Add a page (`add-page`) or rewrite its words (`fill-page`).
|
|
114
|
-
- Change the menu label text in `apps/web/messages/*.json` (it re-points the
|
|
115
|
-
link and reports the label key).
|
|
116
|
-
- Edit route literals in code, or anything in `apps/api` / `apps/mcp`.
|
|
117
|
-
- Move detail pages, hubs, or any page whose URL is fixed by its type.
|