Skip to content

Commit 2b43662

Browse files
authored
Merge branch 'dev' into fix/double-encoding
2 parents 71e1740 + 6eb2390 commit 2b43662

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1316
-502
lines changed

.changeset/bright-cougars-think.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-router": patch
3+
---
4+
5+
Use a stable useOptimistic setter stub in React 18

.changeset/early-doors-obey.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@react-router/dev": patch
3+
"react-router": patch
4+
---
5+
6+
add support for throwing redirect Response's at RSC render time

.changeset/plenty-kiwis-matter.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@react-router/dev": patch
3+
"react-router": patch
4+
---
5+
6+
`routeRSCServerRequest` replace `fetchServer` with `serverResponse`
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": patch
3+
---
4+
5+
Import ESM package `pkg-types` with a dynamic import to avoid issues on Node 20.18 and below

.changeset/silent-shirts-retire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": patch
3+
---
4+
5+
Update `valibot` dependency to `^1.2.0`

.changeset/stupid-forks-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": minor
3+
---
4+
5+
feat: add `vite preview` support

.github/workflows/integration-full.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
uses: ./.github/workflows/shared-integration.yml
3232
with:
3333
os: "ubuntu-latest"
34-
node_version: "[20, 22]"
34+
node_version: "[20.18, 22]"
3535
browser: '["chromium", "firefox"]'
3636

3737
integration-windows:
@@ -49,5 +49,5 @@ jobs:
4949
uses: ./.github/workflows/shared-integration.yml
5050
with:
5151
os: "macos-latest"
52-
node_version: "[20, 22]"
52+
node_version: "[20.18, 22]"
5353
browser: '["webkit"]'

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
fail-fast: false
2727
matrix:
2828
node:
29-
- 20
29+
- 20.18
3030
- 22
3131

3232
runs-on: ubuntu-latest

AGENTS.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# React Router Development Guide
2+
3+
## Commands
4+
5+
- **Build**: `pnpm build` (all packages) or `pnpm run --filter <package> build` (single package)
6+
- **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)
7+
- **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)
8+
- **Typecheck**: `pnpm run typecheck`
9+
- **Lint**: `pnpm run lint`
10+
- **Docs generation**: `pnpm run docs` (regenerates API docs from JSDoc)
11+
- **Type generation**: `pnpm run typegen` (Framework Mode only)
12+
- **Clean**: `pnpm run clean` (git clean -fdX)
13+
14+
## Modes
15+
16+
**Five distinct modes**: Declarative, Data, Framework, RSC Data (unstable), RSC Framework (unstable). **Always identify which mode(s) a feature applies to.**
17+
18+
1. **Declarative**: `<BrowserRouter>`, `<Routes>`, `<Route>`
19+
2. **Data**: `createBrowserRouter()` with `loader`/`action`, `<RouterProvider>`
20+
3. **Framework**: Vite plugin + `routes.ts` + Route Module API (route exports like `loader`, `action`, `default`) + type generation + SSR/SPA
21+
4. **RSC Data** (unstable): RSC runtime APIs, manual bundler setup, runtime route config
22+
5. **RSC Framework** (unstable): Framework Mode with `unstable_reactRouterRSC` Vite plugin
23+
24+
**RSC mode differences:**
25+
26+
- **RSC Framework**: `unstable_reactRouterRSC` plugin, `@vitejs/plugin-rsc`, different entry points/format
27+
- **RSC Data**: Manual bundler, runtime route config typically in `src/routes.ts`, `unstable_RSCRouteConfig`, different runtime APIs, `setupRscTest` in `integration/rsc/`, tests Vite + Parcel
28+
29+
## Architecture
30+
31+
- **Monorepo**: pnpm workspace, packages in `packages/`
32+
- **Key packages**:
33+
- `react-router`: Core (all modes) - `lib/components.tsx`, `lib/hooks.tsx`, `lib/router/`, `lib/dom/`, `lib/rsc/`
34+
- `@react-router/dev`: Framework tooling - `vite/plugin.ts` (Framework), `vite/rsc/plugin.ts` (RSC Framework), `typegen/`
35+
- `react-router-dom`: Re-exports `react-router` (v6→v7 compat)
36+
- `@react-router/node`, `@react-router/cloudflare`, `@react-router/express`: Server adapters
37+
- `@react-router/serve`: Minimal server for Framework Mode
38+
- `@react-router/fs-routes`: File-system routing (`flatRoutes()`)
39+
40+
## Testing
41+
42+
### Unit Tests (`packages/react-router/__tests__/`)
43+
44+
Use Jest for pure routing logic, pure server runtime behavior, router state, React component behavior. No build required.
45+
46+
```bash
47+
pnpm test # All packages
48+
pnpm test packages/react-router/ # Single package
49+
pnpm test packages/react-router/__tests__/router/fetchers-test.ts # Single file
50+
pnpm test -- -t "action fetch" # Tests matching name
51+
```
52+
53+
### Integration Tests (`integration/`)
54+
55+
Use Playwright for Vite plugin, build pipeline, SSR/hydration, RSC, type generation.
56+
57+
```bash
58+
pnpm test:integration --project chromium # Build + test all
59+
pnpm test:integration:run --project chromium # Test only, all
60+
pnpm test:integration:run --project chromium integration/middleware-test.ts # Single file
61+
pnpm test:integration:run --project chromium -g "middleware" # Tests matching name
62+
```
63+
64+
**Project**: Always use `chromium` for integration tests, unless explicitly stated otherwise.
65+
66+
**Rebuild when**: First run, after changing `packages/` (not needed for test-only changes)
67+
68+
**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).
69+
70+
**RSC testing**:
71+
72+
- **RSC Framework**: Use `createFixture` with `rsc-vite-framework/` template
73+
- **RSC Data**: Use `setupRscTest` in `integration/rsc/`, tests Vite + Parcel
74+
75+
Test shared behavior across multiple templates (e.g., `["vite-5-template", "rsc-vite-framework"]`). Test RSC-specific features against RSC template.
76+
77+
## routes.ts
78+
79+
Framework Mode uses `routes.ts` in `app/`. Most tests use `flatRoutes()` for file-system routing:
80+
81+
```ts
82+
// app/routes.ts
83+
import { type RouteConfig } from "@react-router/dev/routes";
84+
import { flatRoutes } from "@react-router/fs-routes";
85+
86+
export default flatRoutes() satisfies RouteConfig;
87+
```
88+
89+
**File-system conventions** (`app/routes/`):
90+
91+
- `_index.tsx``/` (index route)
92+
- `about.tsx``/about`
93+
- `blog.$slug.tsx``/blog/:slug` (URL param)
94+
- `settings.profile.tsx``/settings/profile` (`.` creates nesting)
95+
- `_layout.tsx` → pathless layout route
96+
97+
**Manual config alternative**:
98+
99+
```ts
100+
import { index, route, layout } from "@react-router/dev/routes";
101+
export default [
102+
index("./home.tsx"),
103+
route("about", "./about.tsx"),
104+
layout("./auth-layout.tsx", [route("login", "./login.tsx")]),
105+
];
106+
```
107+
108+
## Documentation
109+
110+
**Don't edit generated files**: `docs/api/` (from JSDoc), `.react-router/types/` (from typegen)
111+
112+
**Mode indicators**: Every doc needs `[MODES: framework, data, declarative]`
113+
114+
**API docs**: Edit JSDoc in `packages/react-router/lib/`, run `pnpm docs`
115+
116+
**Unstable features**: Prefix `unstable_`, add `unstable: true` to frontmatter, include warning block
117+
118+
## Future Flags
119+
120+
- **Future flags** (`vX_*`): Stable breaking changes for next major
121+
- **Unstable flags** (`unstable_*`): Experimental, may change
122+
123+
Test both states (on/off) for future flags. Don't break existing behavior without a flag.
124+
125+
## Changesets
126+
127+
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.
128+
129+
Format:
130+
131+
```markdown
132+
---
133+
"react-router": patch
134+
"@react-router/dev": minor
135+
---
136+
137+
Brief description of the change
138+
139+
- Additional details if needed
140+
```
141+
142+
## Branching
143+
144+
- **`main`**: Latest stable release
145+
- **`dev`**: Active development (branch from here for code changes)
146+
- **`v6`**: v6.x maintenance
147+
- Branch from `main` for docs-only changes
148+
149+
## Key Files
150+
151+
| Purpose | Location |
152+
| ----------------- | ----------------------------------------------------------- |
153+
| Router | `packages/react-router/lib/router/router.ts` |
154+
| React API | `packages/react-router/lib/components.tsx`, `lib/hooks.tsx` |
155+
| Vite plugin | `packages/react-router-dev/vite/plugin.ts` |
156+
| RSC Vite plugin | `packages/react-router-dev/vite/rsc/plugin.ts` |
157+
| Type generation | `packages/react-router-dev/typegen/` |
158+
| Unit tests | `packages/react-router/__tests__/` |
159+
| Integration tests | `integration/` |
160+
| Decision docs | `decisions/` |

contributors.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
- haivuw
148148
- hampelm
149149
- harshmangalam
150+
- harucn
150151
- HelpMe-Pls
151152
- HenriqueLimas
152153
- hernanif1

0 commit comments

Comments
 (0)