---
name: create-site
description: >-
Creates a new Power Pages code site (SPA) using React, Angular, Vue, or Astro. Guides through
the full process from initial concept to deployed site: requirements discovery, scaffolding,
component planning, design, implementation, validation, and deployment. Use when the user
wants to create, build, or scaffold a new Power Pages website or portal.
user-invocable: true
argument-hint: Optional site description
allowed-tools: Read, Write, Edit, Grep, Glob, Bash, WebSearch, AskUserQuestion, Task, TaskCreate, TaskUpdate, TaskList, mcp__plugin_power-pages_playwright__browser_navigate, mcp__plugin_power-pages_playwright__browser_snapshot, mcp__plugin_power-pages_playwright__browser_click
model: opus
---
> **Plugin check**: Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/check-version.js"` — if it outputs a message, show it to the user before proceeding.
# Create Power Pages Code Site
Guide the user through creating a complete, production-quality Power Pages code site from initial concept to deployed site. Follow a systematic approach: discover requirements, scaffold and launch immediately, plan components and design, implement with design applied, validate, review, and deploy.
## Core Principles
- **Use best judgement for design details**: Once the user picks an aesthetic direction and mood, make confident decisions about specific fonts, colors, page layouts, and component behavior. Do not ask the user to specify every detail — use the design reference and your own taste to make creative, distinctive choices.
- **Use TaskCreate/TaskUpdate**: Track all progress throughout all phases — create the todo list upfront with all phases before starting any work.
- **Scaffold early, design with intention**: Get the dev server running immediately after discovery so the user has something to look at. Then plan the design and features while the scaffold is live — apply the chosen aesthetic during implementation.
- **Live preview feedback loop**: The dev server MUST be running before any customization begins. Browse the site via Playwright (`browser_navigate` + `browser_snapshot`) to verify every significant change. Do NOT take screenshots — only use accessibility snapshots to check page structure and content.
- **Keep the scaffold loader in sync with reality**: The scaffold loader polls `public/scaffold-status.json`. Update this file before every `AskUserQuestion` (to raise the "waiting for your input" banner so the user doesn't miss a terminal prompt) and before each implementation step in Phase 5 (so the progress-bar label matches what you're actually doing while the decorative spinner continues its default cycle). See [Live Preview Status Protocol](#live-preview-status-protocol).
- **Use real images**: Source high-quality photos from Unsplash wherever pages need visual content — hero sections, feature cards, about pages, backgrounds, etc. Use `https://images.unsplash.com/photo-{id}?w={width}&h={height}&fit=crop` URLs with specific photo IDs found via `WebSearch`. Never leave image placeholders or broken `` tags pointing to nonexistent files.
- **Git checkpoints**: Commit after every individual page and component — each gets its own commit so breaking changes can be reverted.
**Constraint**: Only static SPA frameworks are supported (React, Vue, Angular, Astro). NOT supported: Next.js, Nuxt.js, Remix, SvelteKit, Liquid.
**Initial request:** $ARGUMENTS
---
## Live Preview Status Protocol
While the scaffold loading screen is visible (from Phase 2.6 until the Home page itself is replaced in Phase 5), the loader polls `GET /scaffold-status.json` every 1.5 seconds. The `message` you write into `/public/scaffold-status.json` appears as the label under the progress bar, and `awaitingInput` controls the "waiting for your input" banner. The decorative spinner above the progress bar continues its built-in phrase cycle; keep the progress-bar label current so the loader still reflects what is actually happening.
**Why this matters**: When the browser with the loader takes over the user's screen, a prompt in the terminal can sit unanswered for a long time because the user doesn't realize anything is waiting. The banner makes it obvious.
**File shape** (all fields optional — omit any field you don't want to change):
```json
{
"message": "Creating Contact page",
"awaitingInput": false,
"inputPrompt": "Please check your terminal to respond."
}
```
- `message` — one short present-participle phrase shown as the status line under the progress bar in the loader (replacing the default "Getting started…" / "Setting up infrastructure…" cycle). Include the grouping context inline when it helps (e.g., `"Creating Footer component (shared components)"`).
- `awaitingInput` — when `true`, a prominent pulsing banner appears at the top of the loader and stays visible until this field is cleared. Set this **before** every `AskUserQuestion` call and clear it (`false`) **immediately after** the user answers.
- `inputPrompt` — short context for the banner (e.g., `"Choose a framework"`). Optional.
**When to update the file**:
1. **After scaffold launches (end of Phase 2)**: write an initial status like `{ "message": "Planning your site", "awaitingInput": false }`.
2. **Before any `AskUserQuestion` that runs while the scaffold is visible** (Phases 3, 4, and any in-scaffold prompt in Phase 5): set `awaitingInput: true` with a short `inputPrompt`. After the user answers, write again with `awaitingInput: false`.
3. **Before each implementation step in Phase 5** — applying design tokens, creating each shared component, creating each page, updating the router, updating navigation — update `message` to the specific action. Examples: `"Applying design tokens"`, `"Creating Navbar component"`, `"Creating Contact page"`.
4. **At the end of Phase 5, after the Home page has been replaced**: delete `public/scaffold-status.json` so it isn't deployed with the site.
Write the file with the `Write` tool (atomic overwrite). You do not need to read it first.
---
## Phase 1: Discovery
**Goal**: Understand what site needs to be built and what problem it solves
**Actions**:
1. Create todo list with all 8 phases (see [Progress Tracking](#progress-tracking) table)
2. If site purpose is clear from arguments:
- Summarize understanding
- Identify site type (portal, dashboard, landing page, blog, etc.)
3. If site purpose is unclear, use `AskUserQuestion`:
| Question | Header | Options |
|----------|--------|---------|
| What should the site be called? (e.g., "Contoso Portal", "HR Dashboard") | Site Name | *(free text — use a single generic option so the user types a custom name via "Other")* |
| Which frontend framework? | Framework | React (Recommended), Vue, Angular, Astro |
| What is the site's purpose? | Purpose | Company Portal, Blog/Content, Dashboard, Landing Page |
| Who is the target audience? | Audience | Internal (employees, partners), External (public-facing customers) |
| Where should the project be created? | Location | Current directory, New folder in current directory (Recommended), Any other directory |
4. Resolve the project location:
- **If "Current directory"**: Project root = ``.
- **If "New folder in current directory"**: Create a folder named `__SITE_NAME__` inside the cwd. Project root = `/__SITE_NAME__/`.
- **If "Any other directory"**: Ask for the full path. Verify/create it. Project root = provided path.
After resolving, confirm: "The site will be created at ``."
Store this as `PROJECT_ROOT`.
5. From the user's answers, derive:
- `__SITE_NAME__` (Title Case, e.g., `Contoso Portal`)
- `__SITE_SLUG__` (kebab-case derived from site name, e.g., `contoso-portal`)
- `__SITE_DESCRIPTION__` (one-line description based on name + purpose)
6. Summarize understanding and confirm with user before proceeding
**Audience influences site generation:**
- **Internal**: Prioritize data tables, dashboards, authentication, navigation depth, functional over flashy design
- **External**: Prioritize landing page appeal, SEO-friendly structure, contact forms, clean marketing-oriented layout
**Output**: Clear statement of site purpose, framework, audience, derived naming values, and project location
---
## Phase 2: Scaffold & Launch Dev Server
**Goal**: Get a running site immediately so the user has something to preview while features and design are planned
> **The scaffold is a temporary branded loading screen** — it shows a Power Pages animated "Building your site" experience with orbiting elements, status messages, and feature cards. Its only purpose is to get the dev server running quickly so the user has something to look at while you plan and build. **During Phase 5 (Implementation), the entire scaffold — including theme.css, Layout, Home page, and all placeholder components — is completely replaced** with the user's actual site: their chosen typography, color palette, pages, components, and navigation. Do NOT try to build on top of the loading screen; replace it entirely.
> See `${CLAUDE_PLUGIN_ROOT}/references/framework-conventions.md` for the full framework → build tool → router → output path mapping.
**Actions**:
### 2.1 Copy Template
> `${CLAUDE_PLUGIN_ROOT}` is already resolved to the plugin's absolute path at runtime. Use it directly in Glob/Read paths — do NOT search for the plugin directory.
Read and copy all files from the matching asset template to the project directory:
| Framework | Asset Directory |
|-----------|----------------|
| React | `${CLAUDE_PLUGIN_ROOT}/skills/create-site/assets/react/` |
| Vue | `${CLAUDE_PLUGIN_ROOT}/skills/create-site/assets/vue/` |
| Angular | `${CLAUDE_PLUGIN_ROOT}/skills/create-site/assets/angular/` |
| Astro | `${CLAUDE_PLUGIN_ROOT}/skills/create-site/assets/astro/` |
Use `Glob` to discover all files in the asset directory, `Read` each file, then `Write` to the project directory preserving the relative path structure.
**Also copy the shared loader icon** that the scaffold references from its CSS (`url('/power-pages-icon.png')`):
`Read` the binary file `${CLAUDE_PLUGIN_ROOT}/skills/create-site/assets/shared/power-pages-icon.png` and `Write` it to `/public/power-pages-icon.png`. (All four supported frameworks serve `public/` at the web root, so the same `/power-pages-icon.png` URL works for every framework.)
**Seed the live status file** so the loader shows a real message the moment it mounts. `Write` `/public/scaffold-status.json`:
```json
{ "message": "Planning your site", "awaitingInput": false }
```
See [Live Preview Status Protocol](#live-preview-status-protocol) for the full contract — from here on, update this file before every `AskUserQuestion` and before each Phase 5 implementation step.
### 2.2 Replace Placeholders
After copying, replace all `__PLACEHOLDER__` tokens in every file. Use `Edit` with `replace_all: true` on each file.
- **Name/slug/description placeholders**: Use the actual values from Phase 1 (`__SITE_NAME__`, `__SITE_SLUG__`, `__SITE_DESCRIPTION__`).
> **Note:** The scaffold loading screen uses hardcoded Power Pages branding colors — there are no color placeholders (`__PRIMARY_COLOR__`, etc.) to replace. The user's chosen color palette is applied fresh during Phase 5 when the scaffold is completely replaced.
### 2.3 Rename gitignore
Rename `gitignore` → `.gitignore` in the project root (stored without dot prefix to avoid git interference in the plugin repo).
### 2.4 Install Dependencies
Run `npm install` **before** initializing git so that `package-lock.json` is included in the initial commit:
```bash
cd ""
npm install
```
### 2.5 Initialize Git Repository
Initialize a git repo and make the first commit. This captures all template files AND `package-lock.json` in one clean baseline:
```bash
cd ""
git init
git add -A
git commit -m "Initial scaffold: __SITE_NAME__ (__FRAMEWORK__)"
```
From this point, **commit after every significant milestone** so any breaking change can be reverted.
### 2.6 Start Dev Server
**This MUST happen now — before any planning or customization begins.** The dev server gives the user a live preview while features and design are being planned:
```bash
cd ""
npm run dev
```
Run `npm run dev` in the background using `Bash` with `run_in_background: true`. Note the local URL (typically `http://localhost:5173` for Vite or `http://localhost:4200` for Angular or `http://localhost:4321` for Astro).
### 2.7 Verify in Playwright & Share URL
Immediately after the dev server starts, verify the scaffold is working:
1. Use `mcp__plugin_power-pages_playwright__browser_navigate` to open the dev server URL
2. Use `mcp__plugin_power-pages_playwright__browser_snapshot` to verify the page loaded correctly (do NOT take screenshots — only use accessibility snapshots)
3. **Share the dev server URL with the user** so they can preview the site in their own browser (e.g., "Your site is running at `http://localhost:5173` — open it in your browser to follow along as I build.")
> **GATE: Do NOT proceed to Phase 3 until ALL of the following are true:**
>
> 1. Template files copied and placeholders replaced
> 2. Git repo initialized with initial scaffold commit
> 3. `npm install` completed successfully
> 4. Dev server is running in the background (`npm run dev`)
> 5. Playwright has opened the site and verified it loads via `browser_snapshot`
> 6. The dev server URL has been shared with the user
>
> If any of these are not done, complete them now before moving on.
**Output**: Running dev server with verified scaffold, URL shared with user
---
## Phase 3: Component Planning
**Goal**: Determine what pages, components, and design elements the site needs — while the user previews the running scaffold
**Actions**:
1. **Raise the "awaiting input" banner** so the user notices the terminal prompt even while the browser loader is full-screen. `Write` `/public/scaffold-status.json`:
```json
{ "message": "Planning your site", "awaitingInput": true, "inputPrompt": "Features, aesthetic, and mood — please answer in the terminal." }
```
Immediately after the user answers, `Write` the same file again with `"awaitingInput": false` so the banner disappears.
2. Use `AskUserQuestion` to collect feature and design requirements:
| Question | Header | Options |
|----------|--------|---------|
| Which features? (multi-select) | Features | *(generate 3-4 context-aware options based on the site name, purpose, and audience from Phase 1)* |
| What aesthetic direction do you want? | Aesthetic | Minimal & Clean (Recommended), Bold & Vibrant, Dark & Moody, Warm & Organic |
| What's the overall mood? | Mood | Professional & Trustworthy (Recommended), Creative & Playful, Technical & Precise, Elegant & Premium |
> **Feature options are NOT hardcoded.** Infer relevant features from Phase 1 answers. For example:
> - "HR Dashboard" + Internal → Employee Directory, Leave Requests, Announcements, Org Chart
> - "Contoso Portal" + External → Contact Form, Service Catalog, Knowledge Base, FAQ
> - "Partner Hub" + Internal → Document Library, Partner Directory, Deal Tracker, Notifications
>
> Always generate options that make sense for the specific site — never reuse a fixed list.
3. Read the design aesthetics reference: `${CLAUDE_PLUGIN_ROOT}/skills/create-site/references/design-aesthetics.md`
4. **Map aesthetic + mood to design choices** using the Aesthetic x Mood Mapping table from the design reference. Record the chosen font direction, color direction, and motion direction.
5. Analyze requirements and determine needed components. Present component plan to user as a table:
```
| Component Type | Count | Details |
|---------------------|-------|---------|
| Pages | 4 | Home, About, Services, Contact |
| Shared Components | 3 | Navbar, Footer, ContactForm |
| Design Elements | 4 | Google Fonts (Playfair Display + Source Sans Pro), Color palette (6 CSS vars), Page transitions, Gradient backgrounds |
| Routes | 4 | /, /about, /services, /contact |
```
6. Use best judgement to determine the final color palette based on the chosen aesthetic + mood. These will be written fresh into a new `theme.css` during Implementation (Phase 5) when the scaffold loading screen is completely replaced:
| CSS Variable | Description | Value |
|-------------|-------------|-------|
| `--color-primary` | Primary hex color | *(choose based on aesthetic + mood)* |
| `--color-secondary` | Complementary hex color | *(choose based on aesthetic + mood)* |
| `--color-bg` | Background color | *(choose based on aesthetic + mood)* |
| `--color-surface` | Surface/card color | *(choose based on aesthetic + mood)* |
| `--color-text` | Main text color | *(choose based on aesthetic + mood)* |
| `--color-text-muted` | Muted text color | *(choose based on aesthetic + mood)* |
**Output**: Confirmed list of pages, components, design elements, and routes to create
---
## Phase 4: Plan Approval
**Goal**: Render the implementation plan as an HTML document, open it in the user's default browser, and get approval before starting implementation.
> **Why HTML instead of a chat message**: A structured HTML plan (like the ones produced by `/integrate-backend`, `/add-server-logic`, and `/add-cloud-flow`) lets the user skim sections, compare swatches, and preview typography — all impossible in a terminal. The scaffold loader in their browser may also be full-screen, so surfacing the plan in a new tab puts it where they can actually read it.
### 4.1 Read the Design Reference
Read the design aesthetics reference: `${CLAUDE_PLUGIN_ROOT}/skills/create-site/references/design-aesthetics.md`. Every field you populate below should be justified by the chosen aesthetic + mood from Phase 3.
### 4.2 Build the Plan Data
Assemble a single JSON object with the following keys. The plan template rejects any data that's missing a required key, so include all of them.
| Key | Type | Content |
|-----|------|---------|
| `SITE_NAME` | string | Title-case site name from Phase 1 |
| `PLAN_TITLE` | string | Always `"Implementation Plan"` |
| `FRAMEWORK` | string | `React` / `Vue` / `Angular` / `Astro` |
| `AESTHETIC` | string | Chosen aesthetic (e.g., `Minimal & Clean`) |
| `MOOD` | string | Chosen mood (e.g., `Professional & Trustworthy`) |
| `SUMMARY` | string | One paragraph describing what the site is and who it serves |
| `TYPOGRAPHY_DATA` | object | `{ primary: { name, sample, reason }, secondary: { name, sample, reason } }` — `name` must be a real Google Font family |
| `PALETTE_DATA` | array | `[{ var, hex, description }]` — one entry per CSS variable (primary, secondary, bg, surface, text, text-muted) |
| `MOTION_DATA` | array | `[{ label, description }]` — page transitions, hover states, etc. |
| `BACKGROUNDS_DATA` | array | `[{ label, description }]` — hero backgrounds, section treatments, patterns |
| `PAGES_DATA` | array | `[{ name, route, description, content: [...], components: [...] }]` — `content` is an outline of what's on the page, `components` is shared component names used |
| `COMPONENTS_DATA` | array | `[{ name, purpose, usedBy: [...] }]` — shared components with the page names that consume them |
| `ROUTES_DATA` | array | `[{ path, page }]` — every route the router will register |
| `REVIEW_DATA` | array of strings | Verification checklist items (e.g., "All pages load without console errors") |
| `DEPLOYMENT_DATA` | array | `[{ title, description, recommended?: boolean }]` — mark exactly one as `recommended: true` |
**Write the data for the user**, not for internal tooling — phrase `description` and `reason` fields in plain language.
### 4.3 Render the HTML Plan
Pick an output path under `/docs/`. Default is `create-site-plan.html`; if that file already exists, pick a descriptive variant like `create-site-plan-v2.html` (the render script refuses to overwrite existing files).
```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/render-createsite-plan.js" --output "/docs/create-site-plan.html" --data-inline ''
```
Use `--data-inline` so no temp JSON file is written. If the JSON is too large for a single shell argument, write it to a temp file and use `--data ` instead, then delete the temp file after the render succeeds.
The script prints `{"status":"ok","output":""}` on success. Capture and use that actual output path for the next step.
### 4.4 Open the Plan in the Default Browser
Open `` in the default browser using the platform-appropriate file opener for the current environment. For example, use `open` on macOS, `xdg-open` on Linux, or the equivalent default-browser opener available on Windows.
### 4.5 Present a Brief Summary in the Terminal
Keep the terminal message short — **the full plan lives in the HTML file now**. Include:
- One sentence confirming the plan was rendered and where (the output path).
- A 3-5 line bullet summary: framework, page count, component count, palette primary + mood.
- A pointer: "See the open browser tab for pages, color swatches, typography samples, and deployment options."
Do NOT dump the full plan contents into the terminal — that defeats the purpose of the HTML view.
### 4.6 Raise the "Awaiting Input" Banner
The user may still be looking at the full-screen scaffold loader when you ask for approval. `Write` `/public/scaffold-status.json`:
```json
{ "message": "Ready to build", "awaitingInput": true, "inputPrompt": "Plan approval needed — review the plan in your browser and answer in the terminal." }
```
Immediately after the user answers, `Write` the same file again with `"awaitingInput": false`.
### 4.7 Ask for Approval
Use `AskUserQuestion`:
| Question | Header | Options |
|----------|--------|---------|
| Does this plan look good? | Plan | Approve and start building (Recommended), I'd like to make changes |
- **If "Approve"**: Proceed to Phase 5.
- **If "I'd like to make changes"**: Ask what they want changed, update the JSON, and re-render to a new filename (the render script won't overwrite). Re-open that new file in the browser and repeat 4.5–4.7.
**Output**: Approved implementation plan, with an HTML copy committed alongside the project for the user to reference during and after implementation.
---
## Phase 5: Implementation
**Goal**: Build all pages, components, and design elements with the chosen aesthetic applied from the start
> **Prerequisite:** The dev server MUST already be running and verified via Playwright (completed in Phase 2). If it is not, go back and complete Phase 2.
>
> **Design reference:** Read `${CLAUDE_PLUGIN_ROOT}/skills/create-site/references/design-aesthetics.md` and apply its principles throughout this phase. All pages and components should be built with the chosen typography, color palette, motion, and backgrounds from the start — do NOT build with neutral styling first and redesign later.
**Actions**:
### 5.1 Create Todos for All Work
**Before writing any code**, use `TaskCreate` to create a todo for every piece of work. This gives the user full visibility into what will be built:
- **One todo per page** — e.g., "Create Contact page (`/contact`)", "Create Dashboard page (`/dashboard`)"
- **One todo per shared component** — e.g., "Create ContactForm component", "Create DataTable component"
- **One todo for routing** — "Update router with all new routes"
- **One todo for navigation** — "Update Layout/Header with navigation links"
- **One todo for design foundations** — "Apply design tokens (fonts, colors, motion, backgrounds)"
Each todo should have a clear `subject`, `activeForm`, and `description` that includes the file path and what the page/component does. Then work through the todos in order, marking each `in_progress` → `completed`.
### 5.2 Replace the Scaffold & Build
The scaffold is a temporary loading screen — it must be **completely replaced** during this phase. Do NOT build on top of it or try to modify the loading animation into a real page. Start fresh with the user's chosen design.
> **Narrate progress in the loader**: Before each of the steps below, update `/public/scaffold-status.json` so the user — who may still be watching the Home page loader — sees what's actually happening instead of the hardcoded placeholder cycle. Use a short present-participle `message` (e.g., `"Creating Navbar component"`, `"Creating Contact page"`). Include any useful grouping context inline in the message itself. The loader picks up changes within ~1.5 seconds. Updates become no-ops once step 4 replaces the Home page.
1. **Design foundations** — **Completely rewrite** `theme.css` (or `styles.css` for Angular) from scratch with the chosen color palette as CSS custom properties, Google Fonts, motion/animation utilities, and background treatments. The scaffold's loading screen CSS is discarded entirely. Commit after this step. *Before starting, set the loader status to `{ "message": "Applying design tokens" }`.*
2. **Layout** — **Rewrite** the Layout component (and Header/Footer for Astro) with proper navigation, header, and footer that reflect the chosen design. The scaffold's passthrough Layout is replaced with a real layout structure. *Set status to `{ "message": "Rewriting Layout" }`.*
3. **Shared components** — Build reusable components (Navbar, Footer, ContactForm, etc.) that pages will use. *For each component, set status to `{ "message": "Creating component" }`.*
4. **Pages** — Create route components for each requested page, **replacing** the scaffold Home page and About placeholder entirely. Each page component must update `document.title` on mount to reflect the current page (e.g., `"Contact — Contoso Portal"`). Use the framework's idiomatic lifecycle hook: `useEffect` (React), `onMounted` (Vue), `ngOnInit` (Angular), or a `` tag in the frontmatter (Astro). Format: `" — "`, with the home page using just `""`. *For each page, set status to `{ "message": "Creating page" }` before writing the file. The loader disappears when the Home page itself is replaced — no further status updates are needed after that.*
5. **Router** — Register all new routes (the scaffold only has `/` and `/about` — add all requested routes)
6. **Navigation** — Add links to the new Layout/Header component
7. **Entry HTML** — Update `index.html` (or `Layout.astro` for Astro) to load the chosen Google Fonts instead of the scaffold's DM Sans + Outfit
**Important**: Build real, functional UI with distinctive design applied — not placeholder "coming soon" pages, and not generic unstyled markup. Every page and component should reflect the chosen aesthetic from the moment it's created. The scaffold loading screen should be completely gone after this phase — no trace of the Power Pages branded animation should remain.
### 5.3 Source Real Images
Use high-quality photos from Unsplash wherever the site needs visual content. Do NOT use placeholder services (e.g., `placeholder.com`, `placehold.co`), broken `` tags, or leave empty image slots.
**How to find images:**
1. Use `WebSearch` to search Unsplash for relevant photos (e.g., `site:unsplash.com modern office workspace`)
2. Pick specific photos and use their direct URL with sizing parameters: `https://images.unsplash.com/photo-{id}?w={width}&h={height}&fit=crop`
3. Choose images that match the site's aesthetic and mood
**Where to use images:**
- **Hero sections** — Striking, high-resolution photos that set the tone for the site
- **Feature/service cards** — Relevant photos that illustrate each feature or service
- **About/team sections** — Professional or contextual photos matching the site's purpose
- **Backgrounds** — Atmospheric photos used as full-bleed or overlay backgrounds
- **Content sections** — Supporting photos that break up text and add visual interest
**Guidelines:**
- Pick images that feel cohesive together — consistent style, lighting, and color tone
- Use appropriate sizing (`w=800` for cards, `w=1600` for heroes/backgrounds) to avoid slow loads
- Add descriptive `alt` text to every `` for accessibility
- For icons and logos, use inline SVGs instead of photos
### 5.4 Git Commit Checkpoints
Commit after **every individual page and component** so breaking changes can be reverted. Each page and each component gets its own commit — do NOT batch multiple pages or components into a single commit.
```bash
git add -A
git commit -m ""
```
**When to commit:**
- After applying design foundations (fonts, colors, motion)
- After creating each page (e.g., "Add Home page", "Add Contact page")
- After creating each shared component (e.g., "Add Navbar component", "Add Footer component")
- After updating routing and navigation
- Before attempting anything risky or experimental
**If something breaks**, revert to the last good commit:
```bash
git revert HEAD
```
### 5.5 Live Verification
After each significant change (new page or component), browse the site via Playwright to ensure everything is up to the mark:
1. Use `mcp__plugin_power-pages_playwright__browser_navigate` to reload or navigate to the updated page
2. Use `mcp__plugin_power-pages_playwright__browser_snapshot` to verify the page structure and content are correct — do NOT take screenshots
3. If something looks wrong in the snapshot, fix it before proceeding
The user is previewing in their own browser via the dev server URL shared in Phase 2.7.
### 5.6 Clean Up the Live Status File
Once the scaffold loader is gone, `public/scaffold-status.json` is just dead weight that would ship with the deployed site. Delete the file from `/public/` and commit the removal alongside the final implementation.
> **GATE: Do NOT proceed to Phase 6 until ALL customization is complete with design applied.** The site must have distinctive typography (Google Fonts — no generic Inter/Roboto/Arial), a cohesive color palette (CSS variables), motion/animations, and all requested pages/features before moving to accessibility verification.
**Output**: All pages, components, and design elements implemented and verified
---
## Phase 6: Accessibility Verification
**Goal**: Verify the site meets WCAG 2.2 AA standards using axe-core automated testing and fix any violations
> **Prerequisite:** All pages and components must be fully implemented (Phase 5 complete). The dev server MUST be running.
**Actions**:
### 6.1 Install Playwright Dependency
Install `playwright` as a dev dependency in the project so the audit script can launch a headless browser. This uses the system-installed browser (Edge/Chrome) — no browser download is needed:
```bash
cd ""
npm install --save-dev playwright
```
### 6.2 Run axe-core Audit on Every Page
Run the audit script via `Bash`, passing the dev server URL and all site routes:
```bash
node "${CLAUDE_PLUGIN_ROOT}/skills/create-site/scripts/axe-audit.js" --url --routes /,/about,/services,/contact --project-root ""
```
The script launches a headless browser, navigates to each route, injects axe-core from CDN, runs the analysis, and outputs a JSON array of per-route results to stdout. Each result contains `violations` (with `id`, `impact`, `description`, `helpUrl`, and affected `nodes`), `passes` count, and `incomplete` count. The script exits with code 1 if any `critical` or `serious` violations are found.
Parse the JSON output and record all violations.
### 6.3 Fix Accessibility Violations
For each violation found, identify the source file and apply the fix:
| Violation | Fix |
|-----------|-----|
| Missing `alt` text on images | Add descriptive `alt` attributes to `` tags |
| Insufficient color contrast | Adjust CSS color variables to meet 4.5:1 (normal text) or 3:1 (large text) ratios |
| Missing form labels | Add `