React Router v7
This guide starts with an existing React Router v7 framework-mode app. It is verified with v7.18.1; if your config does not recognize v8_viteEnvironmentApi, update to the latest v7 release.
Enable the Vite Environment API
React Router v7 keeps the Vite Environment API behind a future flag. Enable the required flag and set an explicit build directory:
Create the React Router server handler
Create server/ssr.ts:
This adapts React Router's generated server build to the Fetch API handler Nitro expects.
Configure Vite
Update vite.config.ts:
Keep dirs: ["workflows"] so subsequent builds do not scan generated files under build. Place reactRouter() before nitro() in the plugin array.
Create a workflow
Create workflows/greeting.ts:
Start the workflow from a Nitro route
Create server/routes/api/greeting.post.ts:
React Router continues to handle your application routes. Nitro handles this server route at POST /api/greeting, as well as Workflow SDK's internal routes.
Run the app
Start the development server:
Then start a workflow:
Build and start the production server:
You can inspect local runs with pnpm workflow web.
Troubleshooting
Vite reports an invalid SSR input or path.replace is not a function
Set future.v8_viteEnvironmentApi to true in react-router.config.ts.
React Router pages return 404
Check that the ssr environment input points to ./server/ssr.ts.
A second build tries to compile files under build/server
Use workflow({ dirs: ["workflows"] }), remove the existing build directory once, and rebuild.
vite build finishes output but does not exit
Use workflow@5.0.0 or later with Nitro v3.