--- name: migrate-to-nextjs description: Autonomous site migration from any legacy stack to modern Next.js. Visual diffing, best practices enforcement, live progress on localhost. user-invocable: true --- # Site Migration Skill **STOP. READ THIS ENTIRE DOCUMENT BEFORE DOING ANYTHING.** This skill migrates legacy websites to modern Next.js. You MUST follow every step exactly. Skipping steps will result in failed migrations. --- ## PHASE 1: SETUP Install all dependencies, ask the user questions, create the Next.js project, and configure MCP. Do not proceed to Phase 2 until everything is verified. ### 1.1 Install Skills Run each command and verify it succeeds: ```bash npx skills add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices --yes npx skills add https://github.com/vercel-labs/next-skills --skill next-best-practices --yes npx skills add https://github.com/vercel-labs/next-skills --skill next-cache-components --yes npx skills add https://github.com/vercel-labs/agent-skills --skill web-design-guidelines --yes ``` ### 1.2 Install Migent ```bash npm install -g migent ``` **VERIFY**: `migent --version` returns a version number. ### 1.3 Ask User Questions 1. **"Which directory contains your legacy site?"** - Scan workspace for `package.json`, `composer.json`, `Gemfile`, `index.html`, `index.php` - Offer detected options as choices 2. **"What port is your legacy site running on?"** (or "How do I start it?") - Common ports: 3000, 4000, 8000, 8080 3. **"What should I name the Next.js project?"** - Suggest: `-next` ### 1.4 Validate Legacy Site ```bash ls -la curl -s -o /dev/null -w "%{http_code}" http://localhost:/ ``` **MUST PASS**: Directory exists AND curl returns `200`. **CAPTURE** any observed request patterns. Example: Redirect to /en means the site has localisation — include it in the migration plan. **IF VALIDATION FAILS**: Return to user with specific error. Do not guess or proceed. ### 1.5 Load All Skills Load all skill contexts now. They will be used throughout the migration. ``` /next-best-practices /vercel-react-best-practices /web-design-guidelines ``` **IMPORTANT**: Always use the latest Next.js and tailwindcss (check versions). ### 1.6 Create Next.js Project ```bash bunx create-next-app@latest \ --typescript \ --tailwind \ --app \ --src-dir \ --import-alias "@/*" \ --use-bun \ --yes ``` **NOTE**: - Use `bun`, not `npm` - Use `bunx`, not `npx` - ESLint is NOT included — we use Biome ### 1.7 Install Biome ```bash cd bun add -D @biomejs/biome ``` Create `biome.json`: ```json { "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "organizeImports": { "enabled": true }, "linter": { "enabled": true, "rules": { "recommended": true } }, "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 } } ``` ### 1.8 Configure MCP Configure MCP servers in the **workspace root** (NOT inside the Next.js project): ``` workspace/ ← config goes HERE ├── legacy-site/ ├── my-next-app/ └── .mcp.json ``` Create `.mcp.json`: ```json { "mcpServers": { "migent": { "command": "npx", "args": ["-y", "migent", "mcp"] } } } ``` ### 1.9 Verify MCP Start the Next.js dev server, then test MCP: ```bash bun run dev ``` ``` ir_capture(port: 3000, route: "/") ``` **VERIFY**: Returns JSON with `elementCount > 0`. ### 1.10 Copy Assets ```bash mkdir -p /public cp -r /images/* /public/images/ 2>/dev/null || true cp -r /fonts/* /public/fonts/ 2>/dev/null || true cp -r /assets/* /public/assets/ 2>/dev/null || true ``` ### Setup Checkpoint Before proceeding, confirm ALL of the following: - [ ] All 4 skills installed - [ ] Legacy site running and accessible - [ ] Next.js project created with Biome configured - [ ] MCP returning captures for both sites - [ ] Assets copied **IF ANY FAILS**: Stop and report the error to the user. --- ## PHASE 2: DISCOVERY Use MCP tools to capture the legacy site and analyze patterns. **DO NOT USE CURL. DO NOT FETCH HTML MANUALLY.** ### 2.1 Discover Routes Analyze legacy codebase to find all routes: - Check `sitemap.xml` if exists - Check router files (Express routes, Next.js pages, PHP files) - Check navigation links in captured IR ### 2.2 Capture All Routes (Parallel) Call `ir_capture` for all discovered routes **in parallel** (batch all calls in a single message). Each `ir_capture` creates a fresh Playwright page — no shared state conflicts. ``` # Call all in one message — they run concurrently: ir_capture(port: , route: "/") ir_capture(port: , route: "/about") ir_capture(port: , route: "/contact") # ... all discovered routes ``` Collect all results. Write captures to `migration.json`: ```json { "legacy": { "directory": "./legacy-site", "port": 8000, "framework": "php", "routes": ["/", "/about", "/contact"] }, "captures": { "/": { "elementCount": 150, "animationCount": 12 }, "/about": { "elementCount": 89, "animationCount": 3 } }, "next": { "directory": "./my-next-app", "port": 3000 }, "routeStatus": { "/": "pending", "/about": "pending", "/contact": "pending" }, "progress": {}, "skippedIssues": [] } ``` ### 2.3 Analyze JavaScript Patterns **IMPORTANT**: Legacy JavaScript is ANYTHING that is NOT React or Next.js. Search legacy codebase for patterns that need conversion: ```bash # Find jQuery grep -r "jquery\|jQuery\|\\\$(" --include="*.js" --include="*.html" --include="*.php" # Find inline handlers grep -r "onclick=\|onsubmit=\|onchange=" --include="*.html" --include="*.php" ``` Document findings in `migration.json` under `legacy.javascript`. ### 2.4 Detect Locales & Validate Links Check `ir_capture` results for locale patterns: 1. **Redirect-based detection**: If `ir_capture` returns `redirects` (e.g., `/` → `/en/`), the site uses locale prefixes. 2. **Route-based detection**: If discovered routes have locale prefixes (e.g., `/en/about`, `/fr/about`), locales are in use. **If locales are detected:** - Set up Next.js i18n middleware for locale routing - Create `src/middleware.ts` with locale detection and redirect logic - Use `next-intl` or Next.js built-in i18n for locale-aware Link components - Validate all internal links include the correct locale prefix - Map each locale route to its Next.js equivalent **Internal link validation**: Check `ir_capture` `internalLinks` against detected locales. Links missing locale prefixes will break in the migrated site. ### 2.5 Install Conditional Dependencies Based on discovery results: If animations were detected in any `ir_capture`: ```bash cd bun add framer-motion ``` --- ## PHASE 3: MIGRATE (PER ROUTE) For EACH route discovered in Phase 2, repeat steps 3.1 through 3.4. Start with `/` to build the shared shell first. ### CRITICAL RULES — VIOLATIONS ARE FAILURES **FORBIDDEN:** - `dangerouslySetInnerHTML` — NEVER use to copy legacy HTML - `onclick="..."` or any inline event handlers - jQuery or any jQuery patterns - `