Full-stack frameworks
Deploy a React Router app on Enzonic
React Router 7 in framework mode (the successor of Remix) builds with react-router build. Deploy serves the server build with react-router-serve, or deploys a static single-page app when react-router.config sets ssr: false.
At a glance
What Enzonic Deploy does with a React Router project when you connect it. You can override any of it in the project settings.
- Language
- JavaScript / TypeScript
- Detected from
- @react-router/dev in dependencies; react-router.config.ts, .js or .mjs (read to spot ssr: false)
- Build command
- react-router build
- Output
- build (server) or build/client (SPA)
- Runs as
- Server or SPA
Dependencies install with the package manager your lockfile names: npm ci, pnpm install --frozen-lockfile, yarn install --immutable (Berry) or --frozen-lockfile, or bun install --frozen-lockfile. Node.js 18, 20, 22 and 24 are available. Deploy reads engines.node in package.json, then .nvmrc or .node-version, and uses Node.js 22 when nothing pins a version.
How it runs
Server
The default: build/server/index.js is started with react-router-serve.
SPA
When react-router.config sets ssr: false: build/client is served and every route falls back to index.html.
Deploy React Router step by step
- 1Keep @react-router/serve in dependencies for server mode.
- 2Connect the repository on deploy.enzonic.com and deploy.
import type { Config } from '@react-router/dev/config';
export default {
// true (default): server rendering on Enzonic. false: a static SPA.
ssr: true,
} satisfies Config;Connect a database to React Router
Create a database on Enzonic Databases (or from the project's settings) and its connection string is added to the project's environment variables. This example uses PostgreSQL.
import postgres from 'postgres';
import type { Route } from './+types/home';
const sql = postgres(process.env.DATABASE_URL!);
export async function loader() {
return { posts: await sql`select id, title from posts limit 20` };
}
export default function Home({ loaderData }: Route.ComponentProps) {
return <ul>{loaderData.posts.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;
}Postgres projects get two variables: DATABASE_URL through the connection pooler for the app, and DATABASE_URL_UNPOOLED for migrations.
PostgreSQL on Enzonic DatabasesEvery database engineThings to know
- Prerendered routes (prerender in the config) are served as files; loaders of those routes run at build time, so the database must be reachable from the build too.
Plan limits that matter here
From the live plan data. Every plan includes previews for each branch, instant rollback, environment variables and logs.
| Limit | Free | Pro |
|---|---|---|
| Build minutes | 3,000/mo, 1 concurrent | 10,000/mo, 3 concurrent |
| Servers | 1 instance, 512 MB, sleeps after 15 min idle | 3 always-on, 2 GB |
| Bandwidth | 150 GB/mo | 2 TB/mo |
Related guides
- Deploy a Remix appRemix v2 (Vite or classic compiler) served with remix-serve.
- Deploy a Vite siteVite single-page apps with React, Vue, Svelte, Solid, Preact or Lit.
- Deploy a Next.js appApp Router and Pages Router apps as a Node.js server, or a static export.
Ship your React Router project tonight
Connect the repository and the build settings fill themselves in. Free plan, no card.