ssr config option enables or disables server-side rendering
The ssr option controls server-side rendering. If true, React Router will server render the application. If false, React Router will pre-render the application and save it as an index.html file with assets for deployment as a SPA without server-rendering. It defaults to true.
allowedActionOrigins config option
The allowedActionOrigins option is an array of allowed origin hosts for action submissions to UI routes (does not apply to resource routes). It supports micromatch glob patterns where * matches one segment and ** matches multiple segments. Example: ['example.com', '*.example.com', '**.example.com']. The value can also be set at runtime on the server build in a custom server.
future config option
The future option enables future flags for opting into upcoming features in React Router.
presets config option
The presets option is an array of React Router plugin config presets to ease integration with other platforms and tools.
react-router.config.ts is optional framework mode file
react-router.config.ts is an optional configuration file for customizing aspects of a React Router application, available only in framework mode. It lets you customize server-side rendering, directory locations, build settings, and other framework features.
SPA mode disables server-side rendering
Setting ssr to false in react-router.config.ts disables server-side rendering and enables SPA mode. In SPA mode, React Router pre-renders the application and saves it as an index.html file with assets for deployment without a server.
serverBundles config option
The serverBundles option is a function for assigning routes to different server bundles. This function receives a branch parameter and should return a server bundle ID which will be used as the bundle's directory name within the server build directory.
Remix layered on React Router 6.4 architecture
Remix is layered on top of React Router 6.4 with changes to both server-side data-fetching and client-side rendering. The implementation is split into independent functional aspects: server data loading, server react component rendering, client hydration, and client data loading. Server data loading (1) can be implemented independently. Server rendering (2) and client hydration (3) must happen together since contexts and components must match. Client data loading (4) comes for free once loaders and actions are included on created routes.
useTransition backwards compatibility with Form get
In React Router DOM, forms with method='get' do not trigger a submitting state in useTransition. Remix preserves the older behavior where useTransition.submission and useTransition.type are populated for all form submissions including GET requests to maintain backwards compatibility.
Feature flag for static handler migration on server
The ENABLE_REMIX_ROUTER flag is a runtime-agnostic boolean committed as false initially and toggled to true during local development and tests. It cannot use process.env since the code being changed is runtime agnostic. The flag enables running both old and new approaches in parallel, asserting that matches, loaderData (mapped from routeData), and actionData are identical, and that error/catch boundary errors match.
Remote Context is opaque API
The RemixContext sent through entry.server.ts is considered an opaque API, so changes to its shape are not considered breaking changes.
Server-side migration uses createStaticHandler
The server-side data-fetching migration moves from the old approach to using createStaticHandler from React Router. The three request types are handled in order: handleResourceRequest (simplest), handleDataRequest (slightly more complex), and handleDocumentRequest (most complex with largest surface area). The migration uses the strangler pattern with a feature flag (ENABLE_REMIX_ROUTER) to compare old and new approaches in parallel before removing the old code.
RemixContext replaces EntryContext
A new RemixContext replaces the old EntryContext during the rendering layer update. RemixContext contains: manifest, routeModules, staticHandlerContext, and serverHandoffString. This context is provided via RemixContext.Provider wrapping DataStaticRouter or DataBrowserRouter. The staticHandlerContext is used on the server during SSR to track error and catch boundaries.
React Router components re-exported from remix
Several React Router DOM components and hooks became fully redundant and are re-exported directly from @remix-run/react without modification: Form, useFormAction, useSubmit, useMatches, and useFetchers.
Remix hooks adjusted for backwards compatibility
Several hooks retain Remix-specific enhancements: useLoaderData and useActionData retain their generics (not generic in react-router), useTransition includes submission and type properties, useFetcher includes type property. The Form method='get' no longer enters a submitting state in react-router-dom, so Remix must preserve this behavior.
Remix boundary differentiation in React Router
React Router's @remix-run/router does not distinguish between CatchBoundary and ErrorBoundary. Remix implements differentiateCatchVersusErrorBoundaries to map this distinction. When a route has a CatchBoundary but not an ErrorBoundary, it is represented in DataRouteObject with hasErrorBoundary=true. If the loader throws an error, the router catches it at the errorElement but Remix must re-bubble it upwards to the nearest ErrorBoundary.
History inlined as implementation detail
React Router inlined the history library directly into the router as a single file instead of maintaining it as a separate @remix-run/history package. This was done because history is now intertwined with data-aware routing rather than being a simple reactive process. The router needed to manage both route data loading/mutations and URL updates with different behaviors for PUSH/REPLACE navigations versus POP navigations.
Framework-agnostic router core
React Router moved the bulk of routing logic to a framework-agnostic @remix-run/router package with zero dependencies. This router handles decisions like 'what route am I on?', 'what route am I going to?', 'how do I load data?', and 'how do I interrupt ongoing navigations?' without importing React or react-router. It only needs to know whether routes have components and error boundaries, not how to render them. This design enables future support for UI libraries other than React, such as Preact and Vue.
Pre-rendering is a framework mode feature
Pre-rendering is only available in framework mode, not in other modes.