Skip to content

React Router

Neon.Website.ReactRouter builds a framework-mode React Router app and wraps its server handler in a Node 24 Fetch entry. Server and browser output ship together in a Neon Function ZIP, not a container or an S3 hosting stack. For a client-only React Router SPA, use Vite.

Use a framework-mode app or the runnable React Router example. Configure deployment credentials, then install in the app directory:

Install Alchemy and its matching Effect dependencies first; use Node 24 for this build toolchain.

Terminal window
pnpm add -D @alchemy.run/frontend-frameworks @vercel/nft

Keep the reactRouter() plugin from @react-router/dev/vite in vite.config.* and your route configuration in the application. No separate listening server or deployment adapter is needed in the app.

alchemy.run.ts
import * as Alchemy from "alchemy";
import * as Neon from "alchemy/Neon";
import * as Effect from "effect/Effect";
export default Alchemy.Stack(
"NeonReactRouter",
{ providers: Neon.providers(), state: Alchemy.localState() },
Effect.gen(function* () {
const site = yield* Neon.Website.ReactRouter("Web", {
rootDir: ".",
});
return { url: site.url };
}),
);

The framework handler receives SSR, loader, action, and resource-route requests; static files are served from the Function artifact. Server loaders/actions can read process.env; Vite’s VITE_* values are embedded in the browser build. Do not return private tokens from loaders or place them in public-prefixed values.

Terminal window
pnpm exec alchemy dev
pnpm exec alchemy deploy
pnpm exec alchemy destroy

Run separately, destroying when finished. Dev uses React Router’s native Vite server and HMR, with a local URL and no implicit Neon resources. Append .pipe(Alchemy.remote()) to the Website Effect to opt into live deployment during dev.

Omitting scope creates an Ohio Project on deploy. Pass either project or branch for a shared backend, and choose Ohio when combining with storage. Read scope and credentials before wiring backend access.