Scaffold a complete, self-contained Next.js 15 website with Tailwind CSS, TypeScript, and Vercel deployment. Creates production-ready project structure with design system, components, pages, SEO, and content management — ready to deploy in minutes.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Scaffold a complete, self-contained Next.js 15 website with Tailwind CSS, TypeScript, and Vercel deployment. Creates production-ready project structure with design system, components, pages, SEO, and content management — ready to deploy in minutes.
{"version":"1.3","created":"2026-03-25T00:00:00.000Z","updated":"2026-07-29T00:00:00.000Z","author":"Ability.ai","changelog":["1.3: Field-tested Studio upgrades — repeating item groups + toggles, verbatim-section guard (banner, flagged commits, optional webhook), per-section live links, and a multilingual variant (per-language content with per-key fallback, [lang] editors)","1.2: JSON-backed content layer + optional zero-dependency Studio CMS (/studio) for self-service editing","1.1: Prefer Vercel CLI for deployment; fall back to Vercel MCP, then to manual"]}
Create Website
ℹ️ First, set expectations: before anything else, print one short line with this skill's version and its most recent change — the top entry of metadata.changelog above — e.g. create-website vX.Y — recent: <summary>. Then proceed.
Scaffold a complete, production-ready Next.js 15 website deployable to Vercel.
For tech stack details and component patterns, see reference.md.
Workflow
Step 1: Gather Requirements
If $ARGUMENTS contains a project name or description, use it as context. Otherwise, ask:
Use AskUserQuestion:
Question: "What website are you building?"
Header: "Website Builder"
Gather these details (ask in one prompt, not separately):
Project name — lowercase-with-hyphens (used for directory and package name)
What is it? — One sentence: company site, SaaS landing page, portfolio, docs site, agency site, etc.
Brand basics — Company/product name, tagline, primary color (hex or description like "deep blue")
Destination — Where to create the project directory (default: ./$PROJECT_NAME)
If the description mentions more than one language, also ask which languages
and which is canonical — a multilingual site switches the content layer and
Studio to the multilingual variant
(reference.md → Multilingual sites).
Step 2: Choose Design Direction
Use AskUserQuestion:
Question: "Pick a design direction:"
Header: "Design System"
Show these options:
Minimal Clean — White/light background, subtle borders, no gradients. Swiss-inspired.
Bold Dark — Dark background, vivid accents, glassmorphism cards.
Warm Professional — Warm neutrals, rounded shapes, friendly and approachable.
Also update tailwind.config.ts to reference these CSS variables and add common animations (fade-up, fade-in, blur-fade). See reference.md — Tailwind Config.
components/layout/header.tsx — Sticky header with logo, navigation links, CTA button. Mobile hamburger menu.
components/layout/footer.tsx — Footer with columns: company info, navigation, legal links, copyright.
components/layout/mobile-menu.tsx — Slide-out mobile navigation.
components/ui/button.tsx — Primary and secondary button variants using design system variables.
components/ui/container.tsx — Max-width centered container with responsive padding.
components/ui/section.tsx — Section wrapper with consistent vertical padding.
Step 7: Create Root Layout
Create app/layout.tsx:
Import Google Fonts (Inter for clean, DM Sans for personality — match design direction)
Set up <html>, <body> with font variables and design system classes
Include Header and Footer
Set up comprehensive metadata export with:
Title template: %s | Brand Name
Description, keywords, OpenGraph, Twitter card
Robots configuration
Favicon reference
Step 8: Create Homepage
Create app/page.tsx with sections based on the website type:
For a company/agency site:
Hero section with headline, subtitle, CTA buttons
Problem/solution section
Services/features grid
Social proof / testimonials
CTA section
For a SaaS landing page:
Hero with product screenshot/demo
Features grid (3-4 features with icons)
How it works (3-step process)
Pricing section
FAQ
Final CTA
For a portfolio:
Hero with name and tagline
Featured work grid
About section
Contact CTA
Create each section as a separate component in components/home/.
Step 9: Create Additional Pages
For each page the user requested, create:
app/[page]/page.tsx — Page component with metadata export
Supporting components in components/[page]/ if needed
Common pages and their patterns:
About — Story section, team grid, values
Contact — Contact form, email, location
Blog — List page + [slug] dynamic route with TypeScript data
Pricing — Pricing cards (2-3 tiers)
Step 10: Create Content Data Layer (JSON-backed)
Editable copy lives as JSON under content/, with thin typed wrappers in
lib/ that import it. This keeps content separate from code — so it can be
edited (by a person via the optional Studio CMS in Step 10b, or by an agent)
without touching components or redeploying by hand.
Pretty-print the JSON with 2-space indent + a trailing newline (keeps diffs
clean and matches what Studio writes back). Every section/component renders from
these wrappers — no hardcoded copy in components, which is what makes the
content editable in Step 10b.
Multilingual sites: split content per language (content/en/…,
content/bo/…) with identical keys, keep the canonical language complete, and
merge in the lib/ wrapper with the per-key fallback helper — blank translation
fields fall back to the canonical language by design; never machine-fill
them. See reference.md → Multilingual sites.
Step 10b: Add Studio CMS (optional)
Offer a self-service, in-site content editor at /studio so a non-technical
owner can edit the site's copy themselves — passphrase login, schema-driven
forms (text, textareas, toggles, lists, and repeating item groups for news
posts / announcements / page sections), and each Publish commits the
relevant content/*.json to GitHub (which the host auto-redeploys). It adds
zero npm dependencies (Node crypto + fetch against the GitHub Contents
API) and builds directly on the JSON content layer from Step 10.
Use AskUserQuestion:
Question: "Add Studio — a self-service editor so non-developers can edit the site's copy without touching code?"
Header: "Content Editing"
Show these options:
Yes, add Studio — In-site /studio editor; owner edits copy and publishes from the browser. Needs a GitHub repo + a fine-grained PAT.
No, JSON only — Content stays editable via content/*.json (by a developer or an agent), no in-site editor.
If the user chooses "No", skip to Step 11.
If "Yes", scaffold the Studio stack from
reference.md — Studio CMS. Create exactly these
files (templates are in reference.md):
Mark any word-for-word content (a founder's letter, a historical account, legal
text) with verbatim: true in its schema — the editor shows an "edit with
care" banner, the dashboard badges the section, commits are flagged ⚠️, and the
optional STUDIO_NOTIFY_WEBHOOK pings the maintainer on every such edit.
For a multilingual site, the editor routes become
app/studio/[lang]/[section]/…, the schema gains a lang axis, and translation
editors show canonical values as placeholders — apply the deltas in
reference.md → Multilingual sites.
Then:
Hide Studio from the public site — guard the Header/Footer with
usePathname so they return null on /studio, and add disallow: "/studio"
to app/robots.ts (see reference.md → Hiding Studio).
Add the Studio env vars to .env.example (see reference.md → Environment
variables): STUDIO_PASSWORD, STUDIO_SESSION_SECRET, GITHUB_TOKEN,
GITHUB_REPO, GITHUB_BRANCH, optional STUDIO_COMMIT_NAME/_EMAIL,
STUDIO_LOCAL_WRITE, STUDIO_NOTIFY_WEBHOOK.
Generate the secrets locally so the owner can test immediately:
Write a .env.local (gitignored) with the passphrase + secret and
STUDIO_LOCAL_WRITE=1, so /studio works in dev before any PAT exists.
Flag the committer-email gotcha to the user (see reference.md): the
STUDIO_COMMIT_EMAIL must map to a GitHub account the host (Vercel) is
allowed to deploy from, or the host blocks the deploy and edits silently
never go live. Use the repo owner's GitHub noreply email.
Note for the summary (Step 20): Studio's production env vars
(STUDIO_PASSWORD, STUDIO_SESSION_SECRET, GITHUB_TOKEN, GITHUB_REPO) must
be set in the host's project settings (e.g. Vercel → Settings → Environment
Variables), not just .env.local.
Step 11: SEO Setup
Create these files:
app/sitemap.ts — Dynamic sitemap generation from routes
app/robots.ts — Robots.txt configuration
app/not-found.tsx — Custom 404 page
Step 12: Vercel Configuration
Create vercel.json (minimal — Next.js handles most config):
{"framework":"nextjs"}
Update next.config.ts:
Image optimization (AVIF, WebP)
Cache headers for static assets
Any needed redirects
Step 13: Create Project CLAUDE.md
Create a CLAUDE.md in the project root with:
# CLAUDE.md## Quick Start**Stack:** Next.js 15 (App Router), TypeScript, Tailwind CSS
**Commands:**-`npm run dev` — Start dev server at localhost:3000
-`npm run build` — Production build
-`npm run lint` — Run ESLint
## Project Structure
[List the created directories and their purposes]
## Design System
[Reference the CSS variables in globals.css]
## Content Management
Editable copy lives as JSON under `content/` (e.g. `content/site.json`,
`content/home.json`); `lib/site-data.ts` imports it and re-exports typed values
that components render from. Edit the JSON to change the site — no component
changes needed.
[If Studio was added in Step 10b, also document: owner self-service editing at
`/studio` (passphrase login → publish → host redeploys), the `lib/studio/`
modules, how to add a new editable section (content JSON + `lib/` wrapper +
`SectionSchema` entry), and the required env vars.]
Step 14: Verify Build
npm run build
If the build fails, read the error output, fix the issue, and rebuild. Do not proceed until the build passes.
Step 15: Create GitHub Repository
Initialize git and create a GitHub repository using the GitHub CLI:
This creates the repo, sets the remote, and pushes in one command.
Step 16: Pick Deployment Method
Prefer the Vercel CLI — it deploys directly from the local project without needing the GitHub→Vercel webhook to fire, gives immediate URLs, and works without any MCP setup. Fall back to the Vercel MCP only if the CLI is unavailable and the user doesn't want to install it.
Probe both options in parallel:
vercel --version 2>/dev/null
Also attempt one Vercel MCP call (e.g., mcp__vercel__list_teams) to see if the MCP server is connected.
Decision tree:
CLI available → use CLI path (Step 17a). Skip MCP entirely.
CLI not installed, MCP connected → use MCP path (Step 17b).
Neither available → offer to install the CLI:
## Vercel CLI not installed
The fastest way to deploy is the Vercel CLI:
npm i -g vercel
Then run `vercel login` once. After that, re-run this wizard or deploy manually with `vercel --prod` from the project directory.
Alternative: connect the Vercel MCP server:
claude mcp add --transport http vercel https://mcp.vercel.com
(then restart Claude Code and run `/mcp` to authenticate)
Or deploy via the dashboard:
1. Go to vercel.com/new
2. Import the GitHub repo: $GITHUB_REPO_URL
3. Click Deploy
Skip to Step 20 (Summary).
Step 17a: Deploy via Vercel CLI (preferred)
Use AskUserQuestion:
Question: "Deploy to Vercel now via the CLI?"
Header: "Deployment"
Show these options:
Yes, deploy now — Use vercel CLI to deploy from this directory
Not yet — Skip deployment, I'll deploy later
If user chooses "Not yet", skip to Step 20.
Check auth status first:
vercel whoami 2>&1
If not logged in, the user must run vercel login themselves (it's interactive — open browser flow). Tell them:
You're not logged into Vercel. Run this in your terminal:
vercel login
Then re-run the wizard, or deploy yourself with:
cd $PROJECT_NAME && vercel --prod
Skip to Step 20.
If authenticated, deploy. From the project directory:
# First-time link + production deploy in one shot.# --yes accepts defaults (project name = directory name, scope = personal),# --prod targets production.
vercel --prod --yes
Capture the deployment URL from stdout (last line is typically the production URL).
If the user wants to link to a specific scope/team or override the project name, use vercel link --yes first with --scope <team> and --project <name>, then vercel --prod --yes.
Step 17b: Deploy via Vercel MCP (fallback)
Call mcp__vercel__deploy_to_vercel from the project directory. This connects the GitHub repository to Vercel; future pushes to main trigger automatic deployments.
Step 18: Monitor Deployment
CLI path:vercel --prod --yes blocks until the deployment finishes and prints the result. If it fails, the error is in the command output — read it, fix the issue, commit, and re-run vercel --prod --yes. To inspect a past deployment:
vercel ls# list recent deployments
vercel inspect <deployment-url> # detailed status
vercel logs <deployment-url> # build/runtime logs
MCP path: After deployment is initiated:
Call mcp__vercel__list_teams to get the team ID
Call mcp__vercel__list_projects with the team ID to find the newly created project
Call mcp__vercel__list_deployments with the project ID and team ID to check deployment status
If the deployment state is ERROR or FAILED:
Call mcp__vercel__get_deployment_build_logs with the deployment ID to get error details
Show the relevant error to the user
Fix the build issue, commit, push — the deployment will re-trigger automatically
Step 19: Verify Live Site
Once deployment succeeds:
CLI path: the production URL was printed by vercel --prod --yes. To re-fetch:
vercel ls --prod | head -2
MCP path: Call mcp__vercel__get_project to get the production domain.
Display the live URL to the user.
Step 20: Present Summary
Display:
## Website Created
**Project:** $PROJECT_NAME
**Location:** $DESTINATION/$PROJECT_NAME
**GitHub:** [repo URL if created, or "not created"]
**Pages:** [list of created pages]
**Design:** [chosen direction]
**Studio CMS:** [if added: "/studio (self-service editor)", else "not added"]
**Live URL:** [vercel URL if deployed, or "not yet deployed"]
### What's Next
1. **Start dev server:**
cd $PROJECT_NAME && npm run dev
2. **Edit content:**
- Content (copy): `content/*.json` (e.g. `content/site.json`, `content/home.json`)
- Design tokens: `app/globals.css`
- Add pages: `app/[page-name]/page.tsx`
[If Studio was added:]
- Self-service editor: visit `/studio` (passphrase: your `STUDIO_PASSWORD`).
In dev, `STUDIO_LOCAL_WRITE=1` edits files locally. For production, set
`STUDIO_PASSWORD`, `STUDIO_SESSION_SECRET`, `GITHUB_TOKEN`, `GITHUB_REPO`
in the host's project settings (Vercel → Settings → Environment Variables),
and make sure `STUDIO_COMMIT_EMAIL` maps to a GitHub account the host can
deploy from (else deploys are blocked).
3. **Redeploy:**
- Via CLI (instant, from local): `vercel --prod`
- Via GitHub (if connected): `git add -A && git commit -m "Update" && git push` — Vercel auto-deploys from `main`
[If Studio was added: the owner's Publish in /studio commits to `main` and triggers this same auto-deploy.]
Design Direction Presets
Minimal Clean
--bg-page: 0 0% 100% (white)
--bg-card: 0 0% 98% (off-white)
--text-primary: 0 0% 9% (near-black)
--text-muted: 0 0% 45% (gray)
--border-subtle: 0 0% 90%
Radius: small (8px cards, 6px buttons)
Font: Inter
Bold Dark
--bg-page: 0 0% 5% (near-black)
--bg-card: 0 0% 10% (dark gray)
--text-primary: 0 0% 95% (near-white)
--text-muted: 0 0% 65% (light gray)
--border-subtle: 0 0% 20%
Radius: medium (12px cards, 8px buttons)
Font: Inter
Glass effect on cards: backdrop-blur-xl bg-white/5
Warm Professional
--bg-page: 30 20% 97% (warm off-white)
--bg-card: 0 0% 100% (white)
--text-primary: 20 10% 15% (warm dark)
--text-muted: 20 5% 45% (warm gray)
--border-subtle: 30 10% 88%
Radius: large (16px cards, full buttons)
Font: DM Sans
Error Handling
Situation
Action
npx create-next-app fails
Check Node.js version (needs 18.17+), suggest nvm use 18
GITHUB_TOKEN not set. Add a fine-grained PAT (Contents: read/write on this repo), or set STUDIO_LOCAL_WRITE=1 for local-only editing
Studio: login always fails
STUDIO_PASSWORD unset/mismatched, or STUDIO_SESSION_SECRET shorter than 16 chars. Set both; regenerate the secret with openssl rand -base64 32
Studio: "page changed since you opened it" (409)
Optimistic-concurrency guard — the file changed since load. Reload the editor and re-apply the edit
Studio: Publish succeeds but site never updates
Committer-email gotcha — STUDIO_COMMIT_EMAIL maps to an account the host won't deploy from, so the host blocked the deploy. Use the repo owner's GitHub noreply email
Studio: public Header/Footer show on /studio
Add the usePathname guard (if (pathname?.startsWith("/studio")) return null;) to header.tsx/footer.tsx
Multilingual: translated page shows canonical-language text
By design — blank translation fields fall back per key. Fill the field in that language's Studio editor; never machine-fill it