Comprehensive guide for migrating Create React App (CRA) projects to Next.js. Use when migrating a CRA app, converting React Router to file-based routing, or adopting Next.js patterns like Server Components, App Router, or image optimization.
npx skills add https://github.com/vercel-labs/migration-skills --skill cra-to-next-migrationCLI를 사용하여 이 스킬을 설치하고 작업 공간에서 SKILL.md 워크플로 사용을 시작하세요.
Comprehensive migration guide for converting Create React App projects to Next.js, covering routing, data fetching, components, styling, and deployment. Contains 148 rules across 17 categories, prioritized by migration impact. After a successful migration the application should work the same as it did before the migration.
Reference these guidelines when:
Use Next.js 16.x or later. Do NOT use Next.js 14.x or 15.x.
Before starting migration, check the current latest version:
npm info next version
Use the latest version in your package.json with a caret for minor/patch updates. The minimum supported version for this migration guide is ^16.0.0.
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | Project Setup | CRITICAL | setup- |
6 |
| 2 | Dependencies | CRITICAL | deps- |
1 |
| 3 | Routing | CRITICAL | routing- |
17 |
| 4 | Data Fetching | CRITICAL | data- |
11 |
| 5 | Components | HIGH | components- |
9 |
| 6 | Environment Variables | HIGH | env- |
6 |
| 7 | Styling | HIGH | styling- |
12 |
| 8 | Public Assets | MEDIUM | assets- |
5 |
| 9 | Images | MEDIUM | images- |
8 |
| 10 | Fonts | MEDIUM | fonts- |
6 |
| 11 | SEO & Metadata | MEDIUM | seo- |
9 |
| 12 | API Routes | MEDIUM | api- |
9 |
| 13 | State Management | MEDIUM | state- |
8 |
| 14 | Integrations | MEDIUM | integrations- |
1 |
| 15 | Testing | LOW | testing- |
9 |
| 16 | Build & Deploy | LOW | build- |
7 |
| 17 | Common Gotchas | HIGH | gotchas- |
24 |
setup-initial-structure - Convert CRA folder structure to Next.js App Routersetup-package-json - Update dependencies and scriptssetup-next-config - Create and configure next.config.jssetup-typescript - Migrate TypeScript configurationsetup-eslint - Update ESLint for Next.jssetup-gitignore - Update .gitignore for Next.jsdeps-react19-compatibility - Upgrade dependencies for React 19 compatibilityrouting-basic-pages - Convert components to file-based routesrouting-dynamic-routes - Use [param] syntax for dynamic segmentsrouting-catch-all-routes - Use [...slug] for catch-all routesrouting-optional-catch-all - Use [[...slug]] for optional catch-allrouting-route-groups - Use (group) folders for organizationrouting-parallel-routes - Use @slot for parallel routesrouting-intercepting-routes - Use (..) for intercepting routesrouting-link-component - Replace react-router Link with next/linkrouting-programmatic-navigation - Replace useNavigate with useRouterrouting-use-params - Replace useParams with Next.js paramsrouting-use-search-params - Replace useSearchParams properlyrouting-nested-layouts - Convert nested routes to layoutsrouting-loading-states - Add loading.tsx for suspenserouting-error-boundaries - Add error.tsx for error handlingrouting-not-found - Add not-found.tsx for 404 pagesrouting-hash-based - Handle hash-based routing for client-only appsrouting-protected-routes - Implement protected route patternsdata-useeffect-to-rsc - Convert useEffect fetches to Server Componentsdata-useeffect-to-ssr - Convert useEffect to getServerSidePropsdata-useeffect-to-ssg - Convert useEffect to getStaticPropsdata-client-fetch - Keep client fetches with proper patternsdata-server-actions - Use Server Actions for mutationsdata-revalidation - Configure data revalidation strategiesdata-streaming - Use Suspense for streaming datadata-parallel-fetching - Fetch data in parallel on serverdata-sequential-fetching - Handle sequential data dependenciesdata-caching - Configure fetch caching behaviordata-client-library-init - Initialize client-only libraries in useEffectcomponents-use-client - Add 'use client' directive for client componentscomponents-server-default - Understand server components are defaultcomponents-boundary-placement - Place client boundaries strategicallycomponents-composition - Use composition to minimize client JScomponents-interleaving - Interleave server and client componentscomponents-props-serialization - Ensure props are serializablecomponents-children-pattern - Pass server components as childrencomponents-context-providers - Handle Context providers properlycomponents-third-party - Wrap third-party client componentsenv-prefix-change - Change REACTAPP to NEXTPUBLICenv-server-only - Use non-prefixed vars for server-onlyenv-runtime-config - Use runtime configuration when neededenv-local-files - Understand .env file loading orderenv-build-time - Understand build-time vs runtime env varsenv-validation - Validate required environment variablesstyling-global-css - Move global CSS to app/layout.tsxstyling-css-modules - CSS Modules work with minor changesstyling-sass - Configure Sass supportstyling-tailwind - Configure Tailwind CSSstyling-css-in-js - Handle CSS-in-JS librariesstyling-styled-components - Configure styled-components for SSRstyling-emotion - Configure Emotion for SSRstyling-component-styles - Import component styles properlystyling-postcss - Configure PostCSSstyling-scss-global-syntax - Use :global only in CSS Modulesstyling-css-import-order - Control CSS import order in layoutsstyling-dark-mode-hydration - Handle dark mode without hydration mismatchassets-public-folder - Public folder works the same wayassets-static-imports - Use static imports for assetsassets-absolute-urls - Reference assets without public prefixassets-favicon - Place favicon in app directoryassets-manifest - Configure web app manifestimages-next-image - Replace img with next/imageimages-required-dimensions - Provide width and heightimages-fill-prop - Use fill for responsive imagesimages-priority - Use priority for LCP imagesimages-placeholder - Configure blur placeholdersimages-remote-patterns - Configure remote image domainsimages-loader - Configure custom image loadersimages-optimization - Understand automatic optimizationfonts-next-font - Use next/font for optimizationfonts-google-fonts - Load Google Fonts properlyfonts-local-fonts - Load local font filesfonts-variable-fonts - Configure variable fontsfonts-font-display - Configure font-display strategyfonts-preload - Understand automatic font preloadingseo-metadata-api - Use Metadata API instead of react-helmetseo-dynamic-metadata - Generate dynamic metadataseo-opengraph - Configure Open Graph metadataseo-twitter-cards - Configure Twitter Card metadataseo-json-ld - Add structured data (JSON-LD)seo-canonical - Set canonical URLsseo-robots - Configure robots meta tagsseo-sitemap - Generate sitemap.xmlseo-head-component - Migrate from next/head to Metadataapi-route-handlers - Create Route Handlers in app/apiapi-http-methods - Export named functions for HTTP methodsapi-request-body - Parse request body properlyapi-query-params - Access query parametersapi-headers-cookies - Access headers and cookiesapi-response-types - Return proper response typesapi-middleware - Implement middleware patternsapi-cors - Configure CORS properlyapi-rate-limiting - Implement rate limitingstate-context-client - Context requires 'use client'state-zustand - Zustand works with hydration carestate-redux - Configure Redux with Next.jsstate-jotai - Configure Jotai properlystate-recoil - Configure Recoil properlystate-url-state - Use URL for shareable statestate-server-state - Minimize client state with RSCstate-persistence - Handle state persistenceintegrations-sentry - Migrate Sentry error monitoringtesting-jest-config - Update Jest configurationtesting-react-testing-library - RTL works the sametesting-server-components - Test Server Componentstesting-client-components - Test Client Componentstesting-async-components - Test async componentstesting-mocking - Mock Next.js modulestesting-e2e-cypress - Configure Cypress for Next.jstesting-e2e-playwright - Configure Playwright for Next.jstesting-api-routes - Test API Route Handlersbuild-scripts - Update build scriptsbuild-output - Understand build outputbuild-standalone - Configure standalone outputbuild-static-export - Configure static exportbuild-bundle-analysis - Analyze bundle sizebuild-vercel - Deploy to Vercelbuild-docker - Configure Docker deploymentgotchas-window-undefined - Handle window/document in SSRgotchas-hydration-mismatch - Fix hydration mismatchesgotchas-use-effect-timing - Understand useEffect in Next.jsgotchas-router-ready - Check router.isReady for query paramsgotchas-dynamic-imports - Use next/dynamic properlygotchas-api-routes-edge - Edge vs Node.js runtimegotchas-middleware - Middleware runs on edgegotchas-static-generation - Static vs dynamic renderinggotchas-redirect - Handle redirects properlygotchas-headers - Set response headersgotchas-cookies - Handle cookies in RSCgotchas-turbopack - Handle Turbopack compatibility issuesgotchas-empty-modules - Fix empty module exports for isolatedModulesgotchas-nullish-coalescing - Fix nullish coalescing runtime errorsgotchas-react19-class-components - Fix React 19 class component this bindinggotchas-react19-ref-prop - Handle React 19 ref prop changesgotchas-websocket-optional-deps - Handle WebSocket native dependency bundlinggotchas-auth-race-conditions - Guard against auth/API race conditionsgotchas-auth-state-gating - Wait for auth state before checking rolesgotchas-configuration-idempotency - Ensure configuration idempotency with useRefgotchas-hydration-nested-interactive - Avoid nested interactive elementsgotchas-router-push-timing - Never call router.push during rendergotchas-infinite-rerender - Prevent infinite re-render loopsgotchas-provider-hierarchy - Configure provider hierarchy correctlyBefore starting migration, scan the codebase for patterns that need special handling:
# Check for WebSocket libraries (needs webpack fallback config)
grep -E "(socket\.io|\"ws\")" package.json
# Check for SCSS :export syntax (may need --webpack flag)
grep -r ":export" --include="*.scss" src/
# Check for SVG ReactComponent imports (needs SVGR config)
grep -r "ReactComponent" --include="*.ts" --include="*.tsx" src/
# List all REACT_APP_ environment variables
grep -roh "REACT_APP_[A-Z_]*" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" src/ | sort -u
# Check for Redux extraReducers using object notation (must convert to builder pattern for RTK v2)
grep -r "extraReducers:" --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" src/
# Check for /app/ paths that need updating if using (app) route group
grep -rE "(href|to|push|replace|redirect).*['\"]\/app\/" --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" src/
Scan Results to Rule Mapping:
| Scan Result | Rules to Read |
|---|---|
| socket.io or ws in package.json | gotchas-websocket-optional-deps, setup-next-config |
:export in SCSS files |
gotchas-turbopack |
ReactComponent SVG imports |
assets-static-imports |
REACT_APP_ variables found |
env-prefix-change |
extraReducers: found |
state-redux (RTK v2 builder callback required) |
/app/ paths in navigation |
routing-route-groups (update paths for route groups) |
Read individual rule files for detailed explanations and code examples:
rules/setup-initial-structure.md
rules/routing-basic-pages.md
rules/data-useeffect-to-rsc.md
Each rule file contains:
For best results, migrate in this order:
After migration, verify the application works correctly:
Core Functionality:
npm run dev starts Next.js dev server without errorsnpm run build completes successfullynpm start runs the production buildClient-Side Features:
Routing (if applicable):
#room=abc,key=xyz)Real-Time Features (if applicable):
Integrations (if applicable):
PWA (if applicable):
Performance: