React Router v7 absorbed Remix’s framework features in late 2024, Remix v2 is now the legacy path everyone is told to migrate off of, and in April 2026 the Remix team shipped a beta preview of Remix 3 — a full-stack framework that drops React entirely and runs on Preact and the Fetch API instead. All three currently answer to some form of the name “Remix” in a codebase, a package.json, or a Stack Overflow answer from any point in the last four years, and an unguided Claude Code has no reliable way to tell which one it’s looking at. That’s not a hypothetical: the loader/action mental model is identical across Remix v2 and React Router v7, so the code looks interchangeable right up until an import path, a config file, or a component API silently doesn’t exist in the version the project actually runs. CLAUDE.md is the only place that gap gets closed, because it’s the one thing that’s true about the project rather than true about “Remix” in general.
The gallery’s existing Remix + Supabase entry was written for the Remix v2 era and is still useful for its Supabase auth patterns, but it predates the React Router v7 merge and says nothing about which framework mode a project should be locked to. Browse more real-world CLAUDE.md and AGENTS.md examples in our gallery.
Three Things Now Called “Remix”
| Remix v2 | React Router v7 (framework mode) | Remix 3 | |
|---|---|---|---|
| Status in 2026 | Legacy, migration target is React Router v7 | Current, stable, the recommended full-stack path | Beta preview (shipped April 30, 2026), not production-ready |
| UI framework | React | React | Not React — a forked Preact, procedural components |
| Core package | @remix-run/react, @remix-run/node | react-router, @react-router/node | remix, remix/ui (small composable packages) |
| Data model | loader / action exports, useLoaderData | Same loader/action model, meta now reads loaderData not data | Routes as Fetch API handlers — “controllers return responses” |
| Scaffold command | npx create-remix@latest | npx create-react-router@latest | npx remix@next new my-remix-app |
| Config file | remix.config.js (or Vite plugin from @remix-run/dev) | react-router.config.ts + reactRouter() Vite plugin | N/A — no Vite compiler step described in the beta docs |
The overlap that actually causes bugs isn’t the naming — it’s that Remix v2 and React Router v7 framework mode share the same loader/action/nested-route mental model closely enough that migrated and unmigrated code both compile-check as “plausible Remix code” to a model working from training data. Remix 3 is the opposite problem: it’s different enough that a model pattern-matching on the word “Remix” can hallucinate remix/ui imports or on() event handlers into a project that’s actually running React Router v7’s JSX components, because both are technically true statements about something called Remix.
What Breaks Without an Explicit CLAUDE.md Statement
Import paths that resolve to a package that isn’t installed. A migrated project has react-router and @react-router/node in package.json; Remix v2 training data — which is most of what exists on the public web for “Remix” as of 2026 — imports from @remix-run/node and @remix-run/react.
// WRONG in a migrated React Router v7 project — package no longer installed
import { redirect } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
// RIGHT — React Router v7 framework mode
import { redirect } from "react-router";
import { ServerRouter } from "react-router";
meta reading the wrong field. This one compiles and runs, then silently returns undefined — the kind of bug that doesn’t throw, it just quietly breaks SEO tags.
// WRONG — `data` was the Remix v2 meta arg, deprecated in React Router v7
export function meta({ data }: Route.MetaArgs) {
return [{ title: data.title }];
}
// RIGHT — React Router v7 renamed the field
export function meta({ loaderData }: Route.MetaArgs) {
return [{ title: loaderData.title }];
}
Scripts that reference a binary the project no longer has. remix vite:dev and remix-serve are Remix v2 script names; a migrated package.json runs react-router dev and react-router-serve instead. An agent regenerating package.json scripts from a stale mental model breaks npm run dev outright.
Remix 3 syntax leaking into a React Router v7 file. Because both currently go by “Remix” in casual usage, a model that’s aware Remix 3 exists can suggest its mix style-composition property or remix/ui imports inside a project that’s actually rendering JSX components — the two have no shared component API at all, so this fails immediately rather than subtly.
The Official React Router Agent Skill (and Where It Stops)
The React Router team publishes an official agent skills repository (138 stars, actively maintained through mid-2026) with three separate skills — react-router-framework-mode, react-router-data-mode, and react-router-declarative-mode — installable via npx skills add remix-run/agent-skills --skill react-router-framework-mode. The framework-mode skill is genuinely good: it documents the Form vs. useFetcher distinction (search forms use <Form method="get">, inline mutations use useFetcher to avoid a full navigation), states that global nav/footer belongs in root.tsx rather than a separate layout file, flags that middleware requires React Router 7.9.0+ behind the v8_middleware flag, and correctly documents the meta → loaderData rename covered above.
What it doesn’t — and by its own design, can’t — do:
Official react-router-framework-mode skill | Your project’s CLAUDE.md | |
|---|---|---|
| Scope | React Router API patterns, general to any project | This project’s actual mode, migration status, and version pin |
| Which of the 3 modes this project uses | Not addressed — you install the skill for the mode you’re already using | Required; the skill split into three separate skills is itself evidence a model can’t infer this |
| Remix v2 → React Router v7 migration state | Not addressed | Required — fully migrated, partially migrated, or untouched changes what imports are even valid |
| Remix 3 exclusion | Not addressed | Required if the project has any adjacent Remix 3 experiments or examples in the repo |
| Activation | Loads contextually when the agent decides it’s relevant (per the Agent Skills spec) | Always in context — no activation judgment call needed |
Installing the skill and writing CLAUDE.md rules aren’t competing options — the skill teaches Claude Code the current React Router API surface accurately; CLAUDE.md tells it which mode this specific project is locked to and what state its migration is actually in, which the skill has no way to know without being told.
A CLAUDE.md Template for React Router v7 Projects
# CLAUDE.md — Routing / Data Layer
## Framework and Mode
- Running: React Router v7, **framework mode** (not library/declarative mode,
not data mode, not Remix v2, not Remix 3).
- Confirm before assuming: `npm list react-router @react-router/dev` —
if `@remix-run/react` or `@remix-run/node` appear instead, this project
has NOT migrated and Remix v2 conventions still apply below the fold.
- Do not scaffold with `npx remix@next` or suggest `remix/ui` imports —
Remix 3 is a separate, non-React beta framework, unrelated to this stack.
## Migration Status
- {Fully migrated from Remix v2 on {date} / Never was Remix, started on
React Router v7 directly / Partially migrated — {list any remaining
@remix-run/* imports and why they haven't moved yet}}.
- Package mapping if migration is incomplete:
`@remix-run/react` → `react-router`, `@remix-run/node` → `@react-router/node`,
`@remix-run/dev` → `@react-router/dev`, `@remix-run/serve` → `@react-router/serve`.
## Conventions In Use
- Routes defined in: {`app/routes.ts` with explicit `route()`/`index()`/`layout()`
helpers / file-based via `@react-router/fs-routes` / a mix — state which}.
- `meta` reads `loaderData`, never the deprecated `data` field.
- Search forms: `<Form method="get">`. Inline mutations that shouldn't
navigate: `useFetcher`. Do not hand-roll `onSubmit` + `setSearchParams`.
- Global nav/footer/providers live in `app/root.tsx` — do not create a
separate top-level layout file for them.
- Middleware: {in use, requires React Router 7.9.0+ and the `v8_middleware`
flag in `react-router.config.ts` / not in use}.
## Version Pin
- `react-router@{exact version}` — check `npm list react-router` before
assuming any API; framework mode, data mode, and Remix 3 are not
interchangeable despite sharing "React Router" or "Remix" in the name.
settings.json: Keeping the Scaffolds Straight
{
"permissions": {
"allow": [
"Bash(npm run dev)",
"Bash(npm run build)",
"Bash(npm run typecheck)",
"Bash(npm list react-router*)"
],
"deny": [
"Bash(npx remix@next*)",
"Bash(npx create-remix*)",
"Bash(npm install @remix-run/*)"
]
}
}
The npm install @remix-run/* deny line is the one that actually catches drift: if Claude Code ever suggests reinstalling a Remix v2 package to “fix” a missing import, that’s the signal the CLAUDE.md migration-status section wasn’t specific enough, not a legitimate fix.
Common Mistakes to Watch For
Treating a remix.config.js file’s presence or absence as proof of which version is running. React Router v7 framework mode uses react-router.config.ts, but a repo mid-migration can have stray legacy files left behind — check package.json dependencies, not config file names.
Assuming loader/action code that “looks like Remix” is safe to copy verbatim from search results. The mental model transfers between Remix v2 and React Router v7 almost perfectly, which is exactly why import-path and meta field bugs are easy to introduce without anyone noticing until runtime.
Letting “Remix” in a prompt or comment pull in Remix 3 patterns. Remix 3’s remix/ui components, on() event binding, and mix style composition have zero surface overlap with React Router v7’s JSX — there’s no partial compatibility to fall back on if this happens.
Skipping the official skill because CLAUDE.md already exists. The skill’s reference files cover routing, forms, type safety, and rendering strategies in more API depth than a CLAUDE.md file should try to hold — they’re complementary, not redundant.
Not stating whether middleware is in use. It’s a 7.9.0+, flag-gated feature; an agent suggesting middleware code in a project on an older pin or without the flag enabled will generate code that doesn’t run.
None of this is an argument against React Router v7 — the framework-mode merge genuinely simplified what used to be two separate things to learn, and the official agent skill is a good sign the ecosystem is taking AI-generated code seriously. It’s an argument for writing down, in the one place a coding agent always reads, which of the three things called “Remix” a given project actually is — because the code alone doesn’t say, and for exactly the two months between the Remix 3 beta preview and whenever it stabilizes, “Remix” is doing triple duty as a name.
Browse more real routing, framework, and infrastructure-specific CLAUDE.md/AGENTS.md examples in our gallery.
FAQ
Is Remix the same thing as React Router v7? Not exactly. React Router v7 merged Remix’s full-stack framework features back into React Router itself, adding a “framework mode” that covers what Remix v2 used to do. The React Router team has told Remix v2 users to upgrade to React Router v7 rather than treating them as two products going forward.
What is Remix 3?
A separate beta framework, previewed April 30, 2026, that drops React entirely in favor of a forked Preact and runs directly on the Fetch API’s Request/Response objects instead of Node’s request/response system. It shares a name and a founding team with Remix v2 but has no component-API compatibility with either Remix v2 or React Router v7.
Do I need to change my code to migrate from Remix v2 to React Router v7?
The loader, action, and nested-routing mental model is identical, so most Remix v2 apps migrate in a few hours of mechanical changes — updating @remix-run/* imports to react-router/@react-router/*, renaming remix.config.js/the Vite plugin to react-router.config.ts/reactRouter(), and switching the meta function’s data argument to loaderData.
Does the official React Router agent skill cover which mode my project uses? No. The skill activates once you’ve installed it for a specific mode (framework, data, or declarative) and teaches API patterns within that mode — it has no way to know which mode a given project is actually locked to, or whether the project has fully migrated off Remix v2. That’s what CLAUDE.md needs to state.
Can I run Remix 3 in production yet? Not as of the beta preview released in April 2026 — it’s explicitly a pre-release with an evolving API. React Router v7 remains the production-ready recommendation for both new projects and Remix v2 migrations.