KahWee - Web Development, AI Tools & Tech Trends

Expert takes on AI tools like Claude and Sora, modern web development with React and Vite, and tech trends. By KahWee.

Migrating from Remix to React Router v7 - Part 2

This is Part 2 covering the step-by-step migration process. Part 1 covered why I migrated and the main challenges.

The Step-by-Step Migration Process

Phase 1: Dependencies and Configuration (30 minutes)

Package.json overhaul: Replace all @remix-run/* packages with React Router equivalents. Script updates: Change build/dev commands to use react-router CLI. Vite configuration: Simplify from complex Remix config to minimal React Router setup. New config file: Add react-router.config.ts for framework-specific settings.

Phase 2: Import Refactoring (90 minutes)

This was the most time-consuming phase. Every file importing from @remix-run/* needed updates:

  • Route files (23 files): Updated loader/action imports and useLoaderData calls
  • Component files (8 files): Changed Link and Form imports
  • Entry files (2 files): Updated server/client entry points
  • Utility files (7 files): Modified auth and theme utilities

The process was methodical: start with entry points, then routes, then components, fixing TypeScript errors as they appeared.

Phase 3: Configuration Fine-tuning (30 minutes)

TypeScript config: Updated to use React Router types. Route file naming: Converted splat routes from api.auth.$.ts to api.auth.$rest.tsx for clarity. Development scripts: Added the new react-router typegen command.

Understanding React Router Typegen: The Game Changer

One feature that took me time to fully appreciate was react-router typegen. This wasn't available in Remix - it's a React Router v7 innovation that represents a significant leap in TypeScript integration.

The typegen command generates route-specific TypeScript types automatically. It creates a +types/<route-file>.d.ts for each route, providing automatic type inference for loader data without manual interfaces, route-specific parameter typing, action and loader return type validation, and component prop type safety based on your actual route implementation.

React Router's type generation executes your route config to determine routes, then generates corresponding TypeScript definitions. This build-time analysis provides runtime safety without polluting the API design.

Instead of manually defining LoaderData interfaces for every route, typegen infers them from your actual loader implementations:

// New React Router v7 pattern - types inferred automatically
export async function loader({ request }: LoaderFunctionArgs) {
  // Return whatever you want, typegen handles the interface
  return { recipes: await getRecipes(), user: await getUser(request) };
}

// Component gets proper typing automatically
export default function RecipeList() {
  const { recipes, user } = useLoaderData<typeof loader>();
  // recipes and user are fully typed without manual interfaces
}

The type inference approach fixes the interface drift problem that plagued my Remix codebase. With manual interfaces, you change a loader to return additional data but forget to update the interface. TypeScript doesn't complain because the interface still "works" - it just silently ignores the new properties.

useLoaderData<typeof loader> eliminates this entirely. The type reflects your actual loader implementation, not what you think it should return. When you refactor a loader's return structure, every component using that data updates automatically.

What Happened to Remix?

Ryan Florence and Michael Jackson handed React Router v7 to an open governance committee while they focus on Remix v3. But Remix v3 isn't an iteration - it's a complete rewrite with no React dependencies. They're building on a fork of Preact for "AI-first development" and "AI driven user interfaces." This leaves React Router v7 as the clear successor for production React applications that want the Remix experience.

Worth the Switch?

React Router v7 is actively developed while Remix v2 is in maintenance mode. The simplified dependency tree, better TypeScript integration, and improved build system provide immediate benefits. For teams on Remix v2 with future flags enabled, the migration is straightforward.

Whether coming from Remix or considering alternatives to Next.js, React Router v7 framework mode handles full-stack React applications well. AI assistance was critical for batch import updates across 40+ files. What could have been a full day of manual work became two focused sessions.

The migration is complete and running smoothly on React Router v7. The process has proven that React Router v7 framework mode is a worthy successor to Remix, offering the same power with simplified tooling and enhanced type safety.