# remix-run/react-router — codebase unpack

> Canonical page: https://codevetter.com/unpack/react-router

This is a deterministic Repo Unpack scan of remix-run/react-router — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: a6090382ed467b5a2d46c8de1a13b331f14959f8 (2026-09-30)
- Last upstream commit: chore(deps): bump github/gh-aw-actions/setup from 0.89.21 to 0.89.22 (#15574)
- Generated by codevetter 1.15.0 on 2026-10-02
- 1187 files scanned · 8.5 MB

Source inspection; upstream code and tests were not executed.

## Languages

- TypeScript: 667 files
- Markdown: 287 files
- JSON: 86 files
- JavaScript: 46 files
- YAML: 26 files
- CSS: 20 files
- Shell: 3 files
- TOML: 2 files

## Repository structure

- packages/ — 474 files
- playground/ — 216 files
- docs/ — 209 files
- integration/ — 160 files
- .github/ — 33 files
- scripts/ — 26 files
- decisions/ — 20 files
- .agents/ — 12 files

Probable source entrypoint: `packages/` (inferred from the tree, not upstream docs)

## Package

- package.json: @remix-run/react-router — 41 declared dependencies

## Structural health signals

Average score 5.4/10 across 96 files; 89 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- a6090382ed46 (2026-09-30) chore(deps): bump github/gh-aw-actions/setup from 0.89.21 to 0.89.22 (#15574)
- 54fd9629cc46 (2026-09-28) chore(deps): bump github/gh-aw-actions/setup from 0.89.17 to 0.89.21 (#15564)
- 291a913bf132 (2026-09-27) docs(useNavigation): fix JSDoc comment parsing and clean up generated documentation (#15561)
- 40faa3305d3c (2026-09-25) Document Session API methods, including session.flash (#15555)
- 2d9827bc09bc (2026-09-23) chore(deps): bump github/gh-aw-actions/setup from 0.89.13 to 0.89.17 (#15536)

## Overview

React Router is a React routing library and application framework for developers who need nested navigation, loader/action data handling, and server rendering. This pinned checkout packages the browser routing engine, Vite tooling, server adapters, session utilities, and unstable React Server Component integrations in a pnpm monorepo. Its distinctive architecture shares routing semantics across browser and server runtimes while keeping framework compilation and platform adaptation in separate packages.

## System map

The repository distributes a routing engine and framework tooling rather than one deployed application. Browser history, React rendering, Fetch-based server handling, and Vite compilation form distinct boundaries. Persistence is supplied through session strategies rather than a central database. The inspected configuration establishes pnpm, Jest, Playwright, and package-specific builds.
- The root workspace builds package projects and discovers Jest projects under packages/*; packageManager is pnpm@11.7.0. — [package.json#L5-48](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/package.json#L5-L48)
- react-router exposes separate root, DOM, route-pattern, and React server conditional entrypoints. — [packages/react-router/package.json#L22-70](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/package.json#L22-L70)
- createRouter owns route normalization, an ID-keyed manifest, DataRoutes, and the selected data strategy. — [packages/react-router/lib/router/router.ts#L1081-1100](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1081-L1100)
- createBrowserRouter adapts browser history, hydration data, context, instrumentation, and route discovery into the shared engine. — [packages/react-router/lib/dom/lib.tsx#L647-664](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L647-L664)
- @react-router/dev publishes configuration, route helpers, Vite integration, and the react-router CLI. — [packages/react-router-dev/package.json#L23-54](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/package.json#L23-L54)
- The server runtime builds a static handler from compiled routes and dispatches requests using Fetch Request/Response interfaces. — [packages/react-router/lib/server-runtime/server.ts#L60-83](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L60-L83) [packages/react-router/lib/server-runtime/server.ts#L215-264](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L215-L264)
- Express and Cloudflare adapters bridge platform context into the same core request handler. — [packages/react-router-express/server.ts#L37-65](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L37-L65) [packages/react-router-cloudflare/worker.ts#L44-69](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-cloudflare/worker.ts#L44-L69)
- Session persistence supports strategy callbacks, whole-cookie storage, and a Node filesystem implementation. — [packages/react-router/lib/server-runtime/sessions.ts#L281-325](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L281-L325) [packages/react-router/lib/server-runtime/sessions/cookieStorage.ts#L34-70](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts#L34-L70) [packages/react-router-node/sessions/fileStorage.ts#L31-60](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L31-L60)
- The RSC framework playground combines unstable_reactRouterRSC, React, MDX preprocessing, and @vitejs/plugin-rsc. — [playground/rsc-vite-framework/vite.config.ts#L1-23](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/playground/rsc-vite-framework/vite.config.ts#L1-L23)
- Core package builds use Wireit to run tsdown for ordinary and RSC outputs; published files include dist and documentation. — [packages/react-router/package.json#L72-90](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/package.json#L72-L90) [packages/react-router/package.json#L121-129](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/package.json#L121-L129)

## Feature catalog

The user-facing surface primarily consists of developer APIs and CLI commands. Inspected capabilities include browser routing, data loading, mutation submission, independent fetchers, URL state, server rendering, and session persistence. Framework tooling adds route configuration, type generation, and server/client separation. Playground entrypoints demonstrate ordinary framework, RSC, and Cloudflare integration shapes.
- Data mode applications declare routes with loaders and Components, mount RouterProvider, and consume results with useLoaderData. — [playground/data/src/main.tsx#L3-24](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/playground/data/src/main.tsx#L3-L24)
- useSubmit supports navigation submissions and non-navigation fetcher submissions with configurable method, encoding, body, and revalidation behavior. — [packages/react-router/lib/dom/lib.tsx#L2570-2615](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L2570-L2615)
- useSearchParams returns URLSearchParams and a setter that performs navigation while accepting functional updates. — [packages/react-router/lib/dom/lib.tsx#L2363-2404](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L2363-L2404)
- History navigation blockers can restore a blocked POP, proceed later, or reset to idle. — [packages/react-router/lib/router/router.ts#L1340-1373](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1340-L1373)
- The CLI dispatches routes, build, reveal, dev, and typegen commands; help exposes JSON route output and watched type generation. — [packages/react-router-dev/cli/run.ts#L43-78](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/cli/run.ts#L43-L78) [packages/react-router-dev/cli/run.ts#L209-228](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/cli/run.ts#L209-L228)
- Framework route modules support clientLoader, clientAction, clientMiddleware, metadata, links, ErrorBoundary, HydrateFallback, and Layout exports. — [packages/react-router-dev/vite/plugin.ts#L140-156](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/vite/plugin.ts#L140-L156)
- The server runtime supports SPA fallback behavior and rejects non-prerendered .data paths when SSR is disabled. — [packages/react-router/lib/server-runtime/server.ts#L146-177](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L146-L177)
- flatRoutes offers optional filesystem routing with ignoredRouteFiles and a configurable route directory. — [packages/react-router-fs-routes/index.ts#L12-44](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-fs-routes/index.ts#L12-L44)
- Cookie session storage persists the entire session in a cookie and rejects serialized values over 4096 characters. — [packages/react-router/lib/server-runtime/sessions/cookieStorage.ts#L47-68](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions/cookieStorage.ts#L47-L68)
- Cloudflare Pages handling tries ASSETS.fetch first, accepts successful or redirect asset responses, then falls back to application routing. — [packages/react-router-cloudflare/worker.ts#L85-106](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-cloudflare/worker.ts#L85-L106)

## Data flow

Route configuration becomes normalized route objects and runtime matching state. Browser submissions become Fetch Requests whose results update route data and errors. Server adapters convert platform inputs into the same request abstraction and return streamed responses. Session data follows a separate cookie-to-storage lifecycle controlled by application code.
- createBrowserRouter feeds route objects, browser history, and hydration data into createRouter before initialization. — [packages/react-router/lib/dom/lib.tsx#L647-664](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L647-L664)
- navigate resolves relative targets through normalizeTo and transforms navigation options into a path, submission, or error. — [packages/react-router/lib/router/router.ts#L1720-1732](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1720-L1732)
- startNavigation aborts the previous navigation, matches the new location, and creates a Request with an AbortController signal. — [packages/react-router/lib/router/router.ts#L1944-1967](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1944-L1967) [packages/react-router/lib/router/router.ts#L2029-2040](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2029-L2040)
- Mutation submissions run handleAction before handleLoaders; completion commits action data, loader data, errors, and working fetchers. — [packages/react-router/lib/router/router.ts#L2052-2068](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2052-L2068) [packages/react-router/lib/router/router.ts#L2116-2155](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2116-L2155)
- Express copies request headers, streams non-GET/HEAD bodies into Fetch Requests, and aborts when the response closes before finishing. — [packages/react-router-express/server.ts#L68-85](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L68-L85) [packages/react-router-express/server.ts#L111-131](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L111-L131)
- Document rendering collects loaderData, actionData, and sanitized errors into a Turbo Stream handoff alongside build metadata. — [packages/react-router/lib/server-runtime/server.ts#L504-545](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L504-L545)
- callRouteHandler forwards request, URL, params, context, and route pattern, converting redirect data wrappers into thrown Responses. — [packages/react-router/lib/server-runtime/data.ts#L11-33](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/data.ts#L11-L33)
- getSession parses a cookie identifier and reads backing data; commitSession updates or creates backing data and serializes the identifier. — [packages/react-router/lib/server-runtime/sessions.ts#L294-315](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L294-L315)
- File sessions serialize data and expiry as JSON, generate random hexadecimal IDs, and remove expired data during reads. — [packages/react-router-node/sessions/fileStorage.ts#L37-84](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L37-L84)
- Type generation creates context, clears the generated type directory, and writes generated server-build and route files. — [packages/react-router-dev/typegen/index.ts#L24-39](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/typegen/index.ts#L24-L39)

## Behavior traces

Four concrete flows were followed through source: browser startup, mutation submission, server document handling, and file session persistence. These traces describe call order and state transitions without asserting runtime success. Initialization and submissions converge on the shared navigation machinery. Server and persistence flows cross explicit adapter and serialization boundaries.
- Browser startup begins in playground/data/src/main.tsx: createBrowserRouter(route array) constructs the router before createRoot renders RouterProvider. — [playground/data/src/main.tsx#L6-24](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/playground/data/src/main.tsx#L6-L24) [packages/react-router/lib/dom/lib.tsx#L647-664](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L647-L664)
- Startup continues through createRouter → initialize → history.listen; when state is not initialized, initialize starts a POP navigation with initialHydration. — [packages/react-router/lib/router/router.ts#L1317-1321](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1317-L1321) [packages/react-router/lib/router/router.ts#L1383-1405](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1383-L1405)
- Initial loading enters startNavigation → createClientSideRequest → handleLoaders → completeNavigation, committing loader results for the playground Component to read. — [packages/react-router/lib/router/router.ts#L2029-2040](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2029-L2040) [packages/react-router/lib/router/router.ts#L2116-2155](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2116-L2155) [playground/data/src/main.tsx#L10-15](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/playground/data/src/main.tsx#L10-L15)
- Submission begins with useSubmit → getFormSubmissionInfo → router.navigate, or router.fetch when navigate is false. — [packages/react-router/lib/dom/lib.tsx#L2578-2611](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L2578-L2611)
- Mutation navigation enters handleAction, interrupts active loads, updates navigation to submitting, and returns a 405 error when the targeted route has neither action nor lazy. — [packages/react-router/lib/router/router.ts#L2171-2180](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2171-L2180) [packages/react-router/lib/router/router.ts#L2238-2250](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2238-L2250)
- After the action, startNavigation builds loading navigation, calls handleLoaders, and commits action and loader results through completeNavigation. — [packages/react-router/lib/router/router.ts#L2096-2110](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2096-L2110) [packages/react-router/lib/router/router.ts#L2116-2155](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2116-L2155)
- Express document handling follows createRemixRequest → getLoadContext → core handleRequest → handleDocumentRequest → staticHandler.query → renderHtml → sendRemixResponse. — [packages/react-router-express/server.ts#L53-59](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L53-L59) [packages/react-router/lib/server-runtime/server.ts#L279-288](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L279-L288) [packages/react-router/lib/server-runtime/server.ts#L470-490](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L470-L490)
- The response path sets status and headers, flushes event-stream headers, streams the body, and cancels the body if the Express response is already closed. — [packages/react-router-express/server.ts#L134-166](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L134-L166)
- New file-session persistence follows createFileSessionStorage → createSessionStorage → commitSession → createData → getFile → mkdir/writeFile → cookie.serialize. — [packages/react-router-node/sessions/fileStorage.ts#L31-55](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L31-L55) [packages/react-router/lib/server-runtime/sessions.ts#L300-315](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L300-L315)
- A subsequent session read follows cookie.parse → readData → getFile → readFile/JSON.parse → expiry check → createSession; destroySession deletes backing data and expires the cookie. — [packages/react-router/lib/server-runtime/sessions.ts#L294-323](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L294-L323) [packages/react-router-node/sessions/fileStorage.ts#L61-84](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L61-L84) [packages/react-router-node/sessions/fileStorage.ts#L96-110](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L96-L110)

## Testing signals

Tests and CI were inspected, not executed; test existence is not a passing result. The inspected unit configuration uses Jest, with jsdom for the core React package and Node overrides for filesystem sessions. Playwright integration tests exercise application fixtures and browser behavior. This is a bounded inspection, so coverage outside the cited tests remains unassessed.
- The root test script invokes Jest with experimental VM modules, and Jest enumerates package projects. — [package.json#L27-28](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/package.json#L27-L28) [package.json#L40-46](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/package.json#L40-L46)
- Shared Jest configuration maps workspace imports to source, transforms JS/TS, and matches *-test files. — [jest/jest.config.shared.js#L12-30](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/jest/jest.config.shared.js#L12-L30)
- The core package uses jest-environment-jsdom, a package setup file, and jest-dom matchers. — [packages/react-router/jest.config.js#L1-9](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/jest.config.js#L1-L9)
- Navigation tests assert committed loaderData, valid null results, and JSON Response unwrapping. — [packages/react-router/__tests__/router/navigation-test.ts#L68-105](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/__tests__/router/navigation-test.ts#L68-L105)
- Fetcher action tests assert submitting → loading → idle and distinguish fetcher action data from revalidated page loaderData. — [packages/react-router/__tests__/router/fetchers-test.ts#L267-303](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/__tests__/router/fetchers-test.ts#L267-L303)
- Node session tests cover persistence across requests, cookie tampering, invalid IDs, and destroying an empty session. — [packages/react-router-node/__tests__/sessions-test.ts#L26-92](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/__tests__/sessions-test.ts#L26-L92)
- Middleware integration tests use PlaywrightFixture and assert client middleware effects before/after loaders and actions. — [integration/middleware-test.ts#L12-20](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/integration/middleware-test.ts#L12-L20) [integration/middleware-test.ts#L278-306](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/integration/middleware-test.ts#L278-L306)
- Playwright runs tests in parallel, marks package modules external, forbids focused tests in CI, and retries three times in CI. — [integration/playwright.config.ts#L15-34](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/integration/playwright.config.ts#L15-L34)
- Unit CI configures Node 22.22 and 24, then installs, builds, typechecks, lints, and invokes pnpm test; these configured steps were not executed in this investigation. — [.github/workflows/test-unit.yml#L24-33](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/.github/workflows/test-unit.yml#L24-L33) [.github/workflows/test-unit.yml#L58-71](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/.github/workflows/test-unit.yml#L58-L71)
- Integration CI installs a selected Playwright browser and invokes pnpm test:integration with that browser; root scripts add a pre-build and post-run cleanup. — [.github/workflows/test-integration-run.yml#L50-58](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/.github/workflows/test-integration-run.yml#L50-L58) [package.json#L31-35](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/package.json#L31-L35)

## Risk map

The observations below identify security and correctness boundaries, not confirmed vulnerabilities. Cookie signing, filesystem identifiers, client/server module separation, request origins, and proxy-derived URLs deserve focused review when changed. The shared navigation engine has a large behavioral blast radius because cancellation, hydration, actions, and loading meet there. Runtime failures, deployment policy, and uninspected tests remain unverified.
- Cookie signing is optional: createCookie defaults secrets to an empty array, while session storage warns about unsigned cookies rather than rejecting them. — [packages/react-router/lib/server-runtime/cookies.ts#L81-99](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/cookies.ts#L81-L99) [packages/react-router/lib/server-runtime/sessions.ts#L328-335](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L328-L335)
- Cookie session content is JSON/base64 encoded and optionally HMAC signed, so signing supplies integrity rather than encryption. — [packages/react-router/lib/server-runtime/cookies.ts#L169-179](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/cookies.ts#L169-L179) [packages/react-router/lib/server-runtime/cookies.ts#L200-206](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/cookies.ts#L200-L206) [packages/react-router/lib/server-runtime/crypto.ts#L3-12](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/crypto.ts#L3-L12)
- The cookie defaults shown set path and sameSite=lax; this default construction does not set secure or httpOnly. — [packages/react-router/lib/server-runtime/cookies.ts#L81-89](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/cookies.ts#L81-L89)
- File storage performs filesystem IO beneath a caller-selected dir, and getFile rejects identifiers outside the 16-character hexadecimal format before path construction. — [packages/react-router-node/sessions/fileStorage.ts#L31-54](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L31-L54) [packages/react-router-node/sessions/fileStorage.ts#L115-124](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L115-L124)
- Hypothesis: concurrent file-session updates merit additional verification because updateData directly overwrites JSON without locking or atomic replacement in the inspected implementation. (inferred) — [packages/react-router-node/sessions/fileStorage.ts#L87-94](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-node/sessions/fileStorage.ts#L87-L94)
- Document mutation requests invoke throwIfPotentialCSRFAttack with configured allowedActionOrigins and return 400 when that check throws. — [packages/react-router/lib/server-runtime/server.ts#L456-468](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L456-L468)
- Express request URL construction depends on trust proxy, forwarded host/host ports, and req.protocol; hostname delimiters are stripped before URL creation. — [packages/react-router-express/server.ts#L92-109](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L92-L109)
- Client/server separation depends on both removal of server-only route exports and the dot-server resolve hook rejecting surviving client references. — [packages/react-router-dev/vite/plugin.ts#L2140-2160](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/vite/plugin.ts#L2140-L2160) [packages/react-router-dev/vite/plugin.ts#L2174-2192](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/vite/plugin.ts#L2174-L2192) [packages/react-router-dev/vite/plugin.ts#L2273-2284](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/vite/plugin.ts#L2273-L2284)
- Application scaffolding can launch package-manager installation through child_process.spawn with a supplied working directory. — [packages/create-react-router/index.ts#L613-654](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/create-react-router/index.ts#L613-L654)
- The shared navigation path aborts previous work and later commits combined action, loader, error, and fetcher state, making edits here relevant across several observable behaviors. — [packages/react-router/lib/router/router.ts#L1944-1951](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1944-L1951) [packages/react-router/lib/router/router.ts#L2144-2155](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2144-L2155)
- Typegen removes generated directories before writing, and root clean scripts invoke git clean; these commands have filesystem side effects and were not run. — [packages/react-router-dev/typegen/index.ts#L33-39](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/typegen/index.ts#L33-L39) [package.json#L14-16](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/package.json#L14-L16)

## Extension points

Extension seams exist at route configuration, data execution, context injection, observability, persistence, and platform adaptation. Framework route exports provide a convention-based interface, while Data mode exposes explicit constructor options. Filesystem routing is an adapter over route configuration rather than the only route discovery model. Most seams are typed factory inputs or exports rather than a single global plugin registry.
- Browser router options accept dataStrategy, patchRoutesOnNavigation, getContext, and instrumentations. — [packages/react-router/lib/dom/lib.tsx#L647-664](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L647-L664)
- createRouter wraps mapRouteProperties with instrumentation-derived updates and selects a custom data strategy or defaultDataStrategyWithMiddleware. — [packages/react-router/lib/router/router.ts#L1052-1073](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1052-L1073) [packages/react-router/lib/router/router.ts#L1087-1100](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L1087-L1100)
- @react-router/dev/routes exports route, index, layout, prefix, relative, and getAppDirectory helpers. — [packages/react-router-dev/routes.ts#L1-10](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/routes.ts#L1-L10)
- The routes.ts architecture accepts exported route configuration arrays and deliberately places filesystem conventions in a separate package. — [decisions/0011-routes-ts.md#L45-73](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/decisions/0011-routes-ts.md#L45-L73)
- flatRoutes converts a convention-generated route manifest into RouteConfigEntry objects and exposes directory and ignore options. — [packages/react-router-fs-routes/index.ts#L18-44](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-fs-routes/index.ts#L18-L44)
- SessionIdStorageStrategy supplies readData, updateData, and deleteData, while createSessionStorage also receives createData and cookie configuration. — [packages/react-router/lib/server-runtime/sessions.ts#L250-267](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L250-L267) [packages/react-router/lib/server-runtime/sessions.ts#L281-290](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/sessions.ts#L281-L290)
- Express getLoadContext can incorporate middleware-generated platform values before invoking the core handler. — [packages/react-router-express/server.ts#L15-26](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L15-L26) [packages/react-router-express/server.ts#L53-57](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L53-L57)
- Server entry modules can supply handleError, handler instrumentation, and handleDataRequest response customization. — [packages/react-router/lib/server-runtime/server.ts#L69-81](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L69-L81) [packages/react-router/lib/server-runtime/server.ts#L235-249](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L235-L249)
- Framework route export lists explicitly distinguish server execution hooks from client data hooks and rendering components. — [packages/react-router-dev/vite/plugin.ts#L140-156](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/vite/plugin.ts#L140-L156)
- RSC and Cloudflare integrations compose with ordinary Vite plugins at playground configuration entrypoints. — [playground/rsc-vite-7-framework/vite.config.ts#L8-18](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/playground/rsc-vite-7-framework/vite.config.ts#L8-L18) [playground/vite-plugin-cloudflare/vite.config.ts#L26-35](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/playground/vite-plugin-cloudflare/vite.config.ts#L26-L35)

## Contributor handoff

Use the pinned checkout and mode-specific source as the authority for future work. Tests and CI were inspected, not executed, and this inventory is bounded rather than exhaustive. Start edits at the runtime or tooling boundary responsible for the behavior, preserving generated artifacts and package conventions. Any future validation report must distinguish configured checks from commands actually run.
- Identify Declarative, Data, Framework, RSC Data, or RSC Framework scope before changing a feature. — [AGENTS.md#L15-33](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/AGENTS.md#L15-L33)
- For browser data behavior, first read createBrowserRouter, useSubmit, and startNavigation; they expose the constructor-to-request-to-state path. — [packages/react-router/lib/dom/lib.tsx#L647-664](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L647-L664) [packages/react-router/lib/dom/lib.tsx#L2570-2615](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/dom/lib.tsx#L2570-L2615) [packages/react-router/lib/router/router.ts#L2029-2068](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/router/router.ts#L2029-L2068)
- For adapter work, inspect both platform conversion and the core runtime context check: initialContext must be a RouterContextProvider instance. — [packages/react-router-express/server.ts#L53-59](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-express/server.ts#L53-L59) [packages/react-router/lib/server-runtime/server.ts#L99-108](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/lib/server-runtime/server.ts#L99-L108)
- Use the repository's Jest and Playwright scripts when execution is authorized; the inspected scripts and CI are configuration evidence, not passing results. — [package.json#L27-35](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/package.json#L27-L35) [.github/workflows/test-unit.yml#L58-71](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/.github/workflows/test-unit.yml#L58-L71) [.github/workflows/test-integration-run.yml#L50-58](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/.github/workflows/test-integration-run.yml#L50-L58)
- For fetcher mutations, preserve separate fetcher action data and page loaderData, including submitting/loading/idle transitions asserted in the inspected test. — [packages/react-router/__tests__/router/fetchers-test.ts#L275-303](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/__tests__/router/fetchers-test.ts#L275-L303)
- Generated API documentation and generated route types are not direct edit targets; modify JSDoc or generators instead. — [AGENTS.md#L107-113](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/AGENTS.md#L107-L113) [packages/react-router-dev/typegen/index.ts#L24-39](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/typegen/index.ts#L24-L39)
- User-affecting changes require a package-local patch, minor, major, or unstable change file; existing unshipped change files should be updated rather than duplicated. — [AGENTS.md#L128-138](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/AGENTS.md#L128-L138)
- Do not assume older package requirements: this core manifest declares version 8.4.0, React peers >=19.2.7, and Node >=22.22.0. — [packages/react-router/package.json#L1-5](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/package.json#L1-L5) [packages/react-router/package.json#L112-119](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/package.json#L112-L119) [packages/react-router/package.json#L128-130](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router/package.json#L128-L130)
- Preserve explicit client/server separation when editing framework transforms; the architecture decision requires server-export removal and errors for remaining .server imports. — [decisions/0010-splitting-up-client-and-server-code-in-vite.md#L77-90](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/decisions/0010-splitting-up-client-and-server-code-in-vite.md#L77-L90) [packages/react-router-dev/vite/plugin.ts#L2273-2284](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/packages/react-router-dev/vite/plugin.ts#L2273-L2284)
- Choose mode-appropriate unit or integration validation, rebuild after package changes for integration work, and use Chromium unless explicitly directed otherwise. — [AGENTS.md#L46-82](https://github.com/remix-run/react-router/blob/a6090382ed467b5a2d46c8de1a13b331f14959f8/AGENTS.md#L46-L82)

Source repository: https://github.com/remix-run/react-router
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/react-router.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
