bootstrap-project
Invariants
- Use the canonical stack: Next.js 16 App Router, Sanity v5, Tailwind 4, shadcn/ui, TypeScript, npm. Do not offer alternatives.
- Source code comes from
eljun/kt-monorepo-template via git clone --depth 1. Do not generate boilerplate inline as a fallback if the clone fails.
- Design tokens are an INPUT (file path or paste-in). Do not invent or generate them.
- Stop and confirm before each irreversible cloud action: GitHub repo creation, Vercel project link, git push. Never auto-create Sanity projects.
- Do not run
npm run dev automatically — leave it for the user.
- Emit a one-line status message before each major step so the user sees progress.
Prerequisites
Run these checks first. If any fail, stop and report which one.
| Tool |
Check |
Expected |
| Node |
node --version |
v20.x or higher |
| npm |
npm --version |
v10.x or higher |
| gh |
gh auth status |
Logged in to github.com |
| vercel |
vercel whoami |
Returns a username |
| Sanity |
npx -y sanity@latest --version |
Returns a version (no global install needed) |
Inputs (ask the user, in order)
- Project slug — kebab-case, used for directory name and repo names. Example:
acme-wellness-spa.
- Project display name — used in copy and
package.json. Example: Acme Wellness Spa.
- Project description — one-line tagline used in
package.json description, CLAUDE.md, and <title> metadata. Example: Boutique wellness studio in Brooklyn.
- Project directory — default:
~/Code/Personal/{slug}.
- Design tokens source — one of:
- Absolute path to a CSS file containing the
@theme block to inject into app/globals.css
skip — keep the template's placeholder palette
- GitHub visibility —
private (default) or public.
- Sanity project — one of:
existing — user provides project ID + dataset name
new — user creates a project at https://sanity.io/manage in a new tab, then provides the project ID + dataset name (skill never creates Sanity projects automatically)
- Vercel project name — default: same as slug.
Workflow
- Verify prerequisites. Run all checks. Stop on failure.
- Confirm inputs. Echo answers back as a summary. Wait for explicit "go" before any side effects.
- Clone template. Status: "Cloning kt-monorepo-template..."
git clone --depth 1 https://github.com/eljun/kt-monorepo-template.git {target_dir}
rm -rf {target_dir}/.git
- Substitute placeholders. Status: "Substituting project placeholders..."
- Find files containing placeholders:
grep -rl '{{PROJECT_' {target_dir}
- Replace
{{PROJECT_SLUG}}, {{PROJECT_NAME}}, {{PROJECT_DESCRIPTION}} across all matches.
- The template's README documents the expected substitution surface — verify the grep result is non-empty before continuing.
- Inject design tokens. Status: "Injecting design tokens..." (skip if user chose
skip)
- Read user's tokens file.
- Replace the
@theme { ... } block in {target_dir}/app/globals.css with the user's contents. Preserve everything else in globals.css.
- Wire Sanity config. Status: "Wiring Sanity config..."
- Copy
.env.example → .env.local in {target_dir}.
- In
.env.local, replace your-project-id with the user-provided Sanity project ID.
- If the dataset name differs from
production, update the NEXT_PUBLIC_SANITY_DATASET line accordingly.
- No code edits required:
sanity/sanity.config.ts and sanity.cli.ts read NEXT_PUBLIC_SANITY_PROJECT_ID and NEXT_PUBLIC_SANITY_DATASET from the environment at runtime.
- Install dependencies. Status: "Installing dependencies (this may take a minute)..."
cd {target_dir} && npm install
- Initial commit. Status: "Creating initial commit..."
cd {target_dir} && git init && git add . && git commit -m "feat: initial scaffold from kt-monorepo-template"
- Confirm GitHub repo creation. Show user: "About to run
gh repo create eljun/{slug} --{visibility} --source . --remote origin. OK?" Wait for explicit confirmation.
- Create GitHub repo. Status: "Creating GitHub repo..." Run the confirmed command.
- Confirm Vercel link. Show user: "About to run
vercel link (interactive, may ask scope and project name). OK?" Wait for confirmation.
- Link Vercel. Status: "Linking Vercel project..."
cd {target_dir} && vercel link
The CLI prompts the user for scope and project — do not try to script around it.
- Pull Vercel env.
cd {target_dir} && vercel env pull .env.local
The file may be empty if no env vars are set yet — that is fine.
- Confirm push. Show user: "About to push to GitHub. OK?" Wait for confirmation.
- Push to GitHub. Status: "Pushing to GitHub..."
cd {target_dir} && git push -u origin main
- Final report. Print a structured summary with these fields:
- Local directory
- GitHub URL:
https://github.com/eljun/{slug}
- Vercel project URL (from
vercel link output)
- Sanity project ID + dataset
- Sanity Studio URL:
http://localhost:3000/studio (once dev runs)
- Next steps:
cd {target_dir} && npm run dev
Status messages (emit before each step)
| Step |
Message |
| 1 |
Checking prerequisites... |
| 3 |
Cloning kt-monorepo-template... |
| 4 |
Substituting project placeholders... |
| 5 |
Injecting design tokens... |
| 6 |
Wiring Sanity config... |
| 7 |
Installing dependencies (this may take a minute)... |
| 8 |
Creating initial commit... |
| 10 |
Creating GitHub repo... |
| 12 |
Linking Vercel project... |
| 15 |
Pushing to GitHub... |
Failure handling
| Failure |
Action |
| Template clone fails |
The eljun/kt-monorepo-template repo may not exist or be private. Stop and tell the user — do not generate inline boilerplate as a fallback. |
| Placeholder substitution finds zero matches |
Warn but continue — template may have evolved past placeholders. |
npm install fails |
Stop. Leave the directory in place. Show the install error. |
gh repo create collision |
Stop and ask for an alternative slug. Do not auto-suffix. |
vercel link fails |
Skip step 13. Leave a TODO: vercel link note in the final report. The project is still functional locally. |
git push fails |
Stop. Local repo is intact. Show the push error so the user can debug (auth, branch protection, etc.). |
Out of scope (v1)
- Stack alternatives (Svelte, Supabase, Material UI, Pages Router, etc.)
- Automatic Sanity project creation
- Automatic dev server startup
- CI/CD workflow configuration
- Custom domain setup on Vercel
- Sanity content seeding or migration
Handoff
End with the structured report from step 16, plus:
Project bootstrapped: {target_dir}
Status: ready for first dev session
Next: cd {target_dir} && npm run dev
1---2name: bootstrap-project3description: Use this skill when the user wants to bootstrap a new web project from the kt-monorepo-template (Next.js 16 + Sanity v5 + Tailwind 4 + shadcn/ui). Walks through project naming, design token import, GitHub/Vercel/Sanity wiring, and an initial commit. Stops with a runnable scaffold and a final URL report.4---56# bootstrap-project78## Invariants910- Use the canonical stack: Next.js 16 App Router, Sanity v5, Tailwind 4, shadcn/ui, TypeScript, npm. Do not offer alternatives.11- Source code comes from `eljun/kt-monorepo-template` via `git clone --depth 1`. Do not generate boilerplate inline as a fallback if the clone fails.12- Design tokens are an INPUT (file path or paste-in). Do not invent or generate them.13- Stop and confirm before each irreversible cloud action: GitHub repo creation, Vercel project link, git push. Never auto-create Sanity projects.14- Do not run `npm run dev` automatically — leave it for the user.15- Emit a one-line status message before each major step so the user sees progress.1617## Prerequisites1819Run these checks first. If any fail, stop and report which one.2021| Tool | Check | Expected |22|------|-------|----------|23| Node | `node --version` | v20.x or higher |24| npm | `npm --version` | v10.x or higher |25| gh | `gh auth status` | Logged in to github.com |26| vercel | `vercel whoami` | Returns a username |27| Sanity | `npx -y sanity@latest --version` | Returns a version (no global install needed) |2829## Inputs (ask the user, in order)30311. **Project slug** — kebab-case, used for directory name and repo names. Example: `acme-wellness-spa`.322. **Project display name** — used in copy and `package.json`. Example: `Acme Wellness Spa`.333. **Project description** — one-line tagline used in `package.json` description, `CLAUDE.md`, and `<title>` metadata. Example: `Boutique wellness studio in Brooklyn`.344. **Project directory** — default: `~/Code/Personal/{slug}`.355. **Design tokens source** — one of:36 - Absolute path to a CSS file containing the `@theme` block to inject into `app/globals.css`37 - `skip` — keep the template's placeholder palette386. **GitHub visibility** — `private` (default) or `public`.397. **Sanity project** — one of:40 - `existing` — user provides project ID + dataset name41 - `new` — user creates a project at https://sanity.io/manage in a new tab, then provides the project ID + dataset name (skill never creates Sanity projects automatically)428. **Vercel project name** — default: same as slug.4344## Workflow45461. **Verify prerequisites.** Run all checks. Stop on failure.472. **Confirm inputs.** Echo answers back as a summary. Wait for explicit "go" before any side effects.483. **Clone template.** Status: "Cloning kt-monorepo-template..."49 ```bash50 git clone --depth 1 https://github.com/eljun/kt-monorepo-template.git {target_dir}51 rm -rf {target_dir}/.git52 ```534. **Substitute placeholders.** Status: "Substituting project placeholders..."54 - Find files containing placeholders: `grep -rl '{{PROJECT_' {target_dir}`55 - Replace `{{PROJECT_SLUG}}`, `{{PROJECT_NAME}}`, `{{PROJECT_DESCRIPTION}}` across all matches.56 - The template's README documents the expected substitution surface — verify the grep result is non-empty before continuing.575. **Inject design tokens.** Status: "Injecting design tokens..." (skip if user chose `skip`)58 - Read user's tokens file.59 - Replace the `@theme { ... }` block in `{target_dir}/app/globals.css` with the user's contents. Preserve everything else in `globals.css`.606. **Wire Sanity config.** Status: "Wiring Sanity config..."61 - Copy `.env.example` → `.env.local` in `{target_dir}`.62 - In `.env.local`, replace `your-project-id` with the user-provided Sanity project ID.63 - If the dataset name differs from `production`, update the `NEXT_PUBLIC_SANITY_DATASET` line accordingly.64 - No code edits required: `sanity/sanity.config.ts` and `sanity.cli.ts` read `NEXT_PUBLIC_SANITY_PROJECT_ID` and `NEXT_PUBLIC_SANITY_DATASET` from the environment at runtime.657. **Install dependencies.** Status: "Installing dependencies (this may take a minute)..."66 ```bash67 cd {target_dir} && npm install68 ```698. **Initial commit.** Status: "Creating initial commit..."70 ```bash71 cd {target_dir} && git init && git add . && git commit -m "feat: initial scaffold from kt-monorepo-template"72 ```739. **Confirm GitHub repo creation.** Show user: "About to run `gh repo create eljun/{slug} --{visibility} --source . --remote origin`. OK?" Wait for explicit confirmation.7410. **Create GitHub repo.** Status: "Creating GitHub repo..." Run the confirmed command.7511. **Confirm Vercel link.** Show user: "About to run `vercel link` (interactive, may ask scope and project name). OK?" Wait for confirmation.7612. **Link Vercel.** Status: "Linking Vercel project..."77 ```bash78 cd {target_dir} && vercel link79 ```80 The CLI prompts the user for scope and project — do not try to script around it.8113. **Pull Vercel env.**82 ```bash83 cd {target_dir} && vercel env pull .env.local84 ```85 The file may be empty if no env vars are set yet — that is fine.8614. **Confirm push.** Show user: "About to push to GitHub. OK?" Wait for confirmation.8715. **Push to GitHub.** Status: "Pushing to GitHub..."88 ```bash89 cd {target_dir} && git push -u origin main90 ```9116. **Final report.** Print a structured summary with these fields:92 - Local directory93 - GitHub URL: `https://github.com/eljun/{slug}`94 - Vercel project URL (from `vercel link` output)95 - Sanity project ID + dataset96 - Sanity Studio URL: `http://localhost:3000/studio` (once dev runs)97 - Next steps: `cd {target_dir} && npm run dev`9899## Status messages (emit before each step)100101| Step | Message |102|------|---------|103| 1 | Checking prerequisites... |104| 3 | Cloning kt-monorepo-template... |105| 4 | Substituting project placeholders... |106| 5 | Injecting design tokens... |107| 6 | Wiring Sanity config... |108| 7 | Installing dependencies (this may take a minute)... |109| 8 | Creating initial commit... |110| 10 | Creating GitHub repo... |111| 12 | Linking Vercel project... |112| 15 | Pushing to GitHub... |113114## Failure handling115116| Failure | Action |117|---------|--------|118| Template clone fails | The `eljun/kt-monorepo-template` repo may not exist or be private. Stop and tell the user — do not generate inline boilerplate as a fallback. |119| Placeholder substitution finds zero matches | Warn but continue — template may have evolved past placeholders. |120| `npm install` fails | Stop. Leave the directory in place. Show the install error. |121| `gh repo create` collision | Stop and ask for an alternative slug. Do not auto-suffix. |122| `vercel link` fails | Skip step 13. Leave a `TODO: vercel link` note in the final report. The project is still functional locally. |123| `git push` fails | Stop. Local repo is intact. Show the push error so the user can debug (auth, branch protection, etc.). |124125## Out of scope (v1)126127- Stack alternatives (Svelte, Supabase, Material UI, Pages Router, etc.)128- Automatic Sanity project creation129- Automatic dev server startup130- CI/CD workflow configuration131- Custom domain setup on Vercel132- Sanity content seeding or migration133134## Handoff135136End with the structured report from step 16, plus:137138```text139Project bootstrapped: {target_dir}140Status: ready for first dev session141Next: cd {target_dir} && npm run dev142```