A comprehensive example demonstrating React Router v7 with unstable middleware feature, running on Cloudflare Workers. This project showcases how to integrate Cloudflare Worker context (bindings, execution context) with React Router's context system, enabling seamless server-side context sharing across your application.
This project solves a common challenge when building full-stack applications with React Router on Cloudflare Workers: how to inject server-side context (like API clients, database connections, or environment variables) into React Router's context system.
├── app/ # React Router application
│ ├── context.ts # Centralized context definitions and utilities
│ ├── entry.server.tsx # Server entry point
│ ├── root.tsx # Root layout component
│ ├── routes/
│ │ └── home.tsx # Example route using injected context
│ └── routes.ts # Route configuration
├── workers/ # Cloudflare Worker code
│ ├── app.ts # Main Worker entry point
│ └── api/
│ └── index.ts # Hono API routes
├── react-router.config.ts # React Router configuration
├── wrangler.jsonc # Cloudflare Worker configuration
└── vite.config.ts # Vite build configuration
Why here? createContext() must be executed within React Router's framework runtime, which has its own context system.
// Centralized context definition with accessor utilities
function createContextWithAccessor<T>() {
const ctx = createContext<T>();
return {
get: (provider: Readonly<RouterContextProvider>) => provider.get(ctx),
set: (provider: RouterContextProvider, value: T) =>
provider.set(ctx, value),
};
}
// Define context instances with built-in accessors
export const cloudflareContext =
createContextWithAccessor<CloudflareBindings>();
export const apiClientContext =
createContextWithAccessor<ReturnType<typeof hc<APIRoutes>>>();
export const executionContextContext =
createContextWithAccessor<ExecutionContext>();When using createRequestHandler to connect React Router with your custom web server, you must inject the React Router context at this layer. This is the bridge between the Worker runtime and React Router's framework runtime.
Warning
If you see an error like this when implementing context injection:
Unable to create initial `unstable_RouterContextProvider` instance.
Please confirm you are returning an instance of `Map<unstable_routerContext, unknown>` from your `getLoadContext` function.
This error appears when your context injection implementation is incorrect.
However, the error message itself refers to the standard React Router approach using getLoadContext. When using a custom web server with createRequestHandler (like this repository), you should ignore this specific error message and use the implementation pattern shown below instead.
If you implement the pattern correctly as shown in this repository, this error message will not appear.
import { createRequestHandler, RouterContextProvider } from "react-router";
import * as build from "virtual:react-router/server-build";
import {
apiClientContext,
cloudflareContext,
executionContextContext,
} from "../app/context";
const reactRouterHandler = createRequestHandler(build, import.meta.env.MODE);
app.all("*", async (c) => {
const rrCtx = new RouterContextProvider();
// Inject React Router's Context using centralized accessors
cloudflareContext.set(rrCtx, c.env);
apiClientContext.set(rrCtx, c.get("apiClient"));
executionContextContext.set(rrCtx, c.executionCtx);
// Pass context to React Router
return reactRouterHandler(c.req.raw, rrCtx);
});export function loader({ context }: Route.LoaderArgs) {
// Access injected context using centralized accessors
const cf = cloudflareContext.get(context);
const api = apiClientContext.get(context);
return { message: cf.VALUE_FROM_CLOUDFLARE };
}- Node.js 18+
- pnpm (recommended) or npm
- Cloudflare account (for deployment)
# Clone the repository
git clone <your-repo-url>
cd react-router-with-container
# Install dependencies
pnpm install
# Generate Cloudflare types
pnpm run typegen# Start development server
pnpm devOpen http://localhost:5173 to see the application.
# Build for production
pnpm build
# Deploy to Cloudflare Workers
pnpm deployConfigure environment variables in wrangler.jsonc:
{
"vars": {
"VALUE_FROM_CLOUDFLARE": "Hello from Cloudflare"
}
}The project uses React Router v7 with experimental features enabled in react-router.config.ts:
export default {
ssr: true,
future: {
unstable_viteEnvironmentApi: true,
v8_middleware: true, // Required for context injection
},
} satisfies Config;MIT