remix-run/react-router ⭐ 56,246
github.com/remix-run/react-router Last updated: 2026-02-20 00:24:34
AGENTS.md
# React Router Development Guide
## Commands
- **Build**: `pnpm build` (all packages) or `pnpm run --filter <package> build` (single package)
- **Test (Jest)**: `pnpm test` (all packages), `pnpm test packages/<package>/` (single package), `pnpm test packages/react-router/__tests__/router/fetchers-test.ts` (single file), or `pnpm test -- -t "action fetch"` (tests matching name)
- **Integration tests (Playwright)**: `pnpm test:integration --project chromium` (build + test all), `pnpm test:integration:run --project chromium` (test only, all), `pnpm test:integration:run --project chromium integration/middleware-test.ts` (single file), or `pnpm test:integration:run --project chromium -g "middleware"` (tests matching name)
- **Typecheck**: `pnpm run typecheck`
- **Lint**: `pnpm run lint`
- **Docs generation**: `pnpm run docs` (regenerates API docs from JSDoc)
- **Type generation**: `pnpm run typegen` (Framework Mode only)
- **Clean**: `pnpm run clean` (git clean -fdX)
## Modes
**Five distinct modes**: Declarative, Data, Framework, RSC Data (unstable), RSC Framework (unstable). **Always identify which mode(s) a feature applies to.**
1. **Declarative**: `<BrowserRouter>`, `<Routes>`, `<Route>`
2. **Data**: `createBrowserRouter()` with `loader`/`action`, `<RouterProvider>`
3. **Framework**: Vite plugin + `routes.ts` + Route Module API (route exports like `loader`, `action`, `default`) + type generation + SSR/SPA
4. **RSC Data** (unstable): RSC runtime APIs, manual bundler setup, runtime route config
5. **RSC Framework** (unstable): Framework Mode with `unstable_reactRouterRSC` Vite plugin
**RSC mode differences:**
- **RSC Framework**: `unstable_reactRouterRSC` plugin, `@vitejs/plugin-rsc`, different entry points/format
- **RSC Data**: Manual bundler, runtime route config typically in `src/routes.ts`, `unstable_RSCRouteConfig`, different runtime APIs, `setupRscTest` in `integration/rsc/`
## Architecture
- **Monorepo**: pnpm workspace, packages in `packages/`
- **Key packages**:
- `react-router`: Core (all modes) - `lib/components.tsx`, `lib/hooks.tsx`, `lib/router/`, `lib/dom/`, `lib/rsc/`
- `@react-router/dev`: Framework tooling - `vite/plugin.ts` (Framework), `vite/rsc/plugin.ts` (RSC Framework), `typegen/`
- `react-router-dom`: Re-exports `react-router` (v6→v7 compat)
- `@react-router/node`, `@react-router/cloudflare`, `@react-router/express`: Server adapters
- `@react-router/serve`: Minimal server for Framework Mode
- `@react-router/fs-routes`: File-system routing (`flatRoutes()`)
## Testing
### Unit Tests (`packages/react-router/__tests__/`)
Use Jest for pure routing logic, pure server runtime behavior, router state, React component behavior. No build required.
```bash
pnpm test # All packages
pnpm test packages/react-router/ # Single package
pnpm test packages/react-router/__tests__/router/fetchers-test.ts # Single file
pnpm test -- -t "action fetch" # Tests matching name
```
### Integration Tests (`integration/`)
Use Playwright for Vite plugin, build pipeline, SSR/hydration, RSC, type generation.
```bash
pnpm test:integration --project chromium # Build + test all
pnpm test:integration:run --project chromium # Test only, all
pnpm test:integration:run --project chromium integration/middleware-test.ts # Single file
pnpm test:integration:run --project chromium -g "middleware" # Tests matching name
```
**Project**: Always use `chromium` for integration tests, unless explicitly stated otherwise.
**Rebuild when**: First run, after changing `packages/` (not needed for test-only changes)
**Organization**: Use `createFixture()` → `createAppFixture()` → `PlaywrightFixture`. Templates available: `vite-6-template/`, `rsc-vite-framework/`, etc. Test all applicable modes (iterate over template array when behavior should work across modes). Test both states when introducing future flags (one test with flag on, one with flag off).
**RSC testing**:
- **RSC Framework**: Use `createFixture` with `rsc-vite-framework/` template
- **RSC Data**: Use `setupRscTest` in `integration/rsc/`
Test shared behavior across multiple templates (e.g., `["vite-5-template", "rsc-vite-framework"]`). Test RSC-specific features against RSC template.
## routes.ts
Framework Mode uses `routes.ts` in `app/`. Most tests use `flatRoutes()` for file-system routing:
```ts
// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export default flatRoutes() satisfies RouteConfig;
```
**File-system conventions** (`app/routes/`):
- `_index.tsx` → `/` (index route)
- `about.tsx` → `/about`
- `blog.$slug.tsx` → `/blog/:slug` (URL param)
- `settings.profile.tsx` → `/settings/profile` (`.` creates nesting)
- `_layout.tsx` → pathless layout route
**Manual config alternative**:
```ts
import { index, route, layout } from "@react-router/dev/routes";
export default [
index("./home.tsx"),
route("about", "./about.tsx"),
layout("./auth-layout.tsx", [route("login", "./login.tsx")]),
];
```
## Documentation
**Don't edit generated files**: `docs/api/` (from JSDoc), `.react-router/types/` (from typegen)
**Mode indicators**: Every doc needs `[MODES: framework, data, declarative]`
**API docs**: Edit JSDoc in `packages/react-router/lib/`, run `pnpm docs`
**Unstable features**: Prefix `unstable_`, add `unstable: true` to frontmatter, include warning block
## Future Flags
- **Future flags** (`vX_*`): Stable breaking changes for next major
- **Unstable flags** (`unstable_*`): Experimental, may change
Test both states (on/off) for future flags. Don't break existing behavior without a flag.
## Changesets
When making changes that affect users, create a changeset at `.changeset/<unique-meaningful-name>.md`. If iterating on a change that hasn't shipped yet, update the existing changeset file instead of creating a new one.
Format:
```markdown
---
"react-router": patch
"@react-router/dev": minor
---
Brief description of the change
- Additional details if needed
```
## Branching
- **`main`**: Latest stable release
- **`dev`**: Active development (branch from here for code changes)
- **`v6`**: v6.x maintenance
- Branch from `main` for docs-only changes
## Key Files
| Purpose | Location |
| ----------------- | ----------------------------------------------------------- |
| Router | `packages/react-router/lib/router/router.ts` |
| React API | `packages/react-router/lib/components.tsx`, `lib/hooks.tsx` |
| Vite plugin | `packages/react-router-dev/vite/plugin.ts` |
| RSC Vite plugin | `packages/react-router-dev/vite/rsc/plugin.ts` |
| Type generation | `packages/react-router-dev/typegen/` |
| Unit tests | `packages/react-router/__tests__/` |
| Integration tests | `integration/` |
| Decision docs | `decisions/` |