← Templates

React Router SSR, with no Node server to keep running

React Router SSR from one Function: a list page with a loader, a detail page, and a form with an action. The client build goes up in the same deploy, and nothing runs between visits.

There's no server to keep running

You want React rendered on the server, but you don't want a Node process up all day, waiting for visitors. Here, each visit starts your code, renders the page, and stops. Between visits nothing runs.

The whole template is public. Read it before you trust it.

Or scaffold it

$ npx wawesome init --template react-ssr
$ npx wawesome deploy

What you get

A React Router v7 app in framework mode, deployed as one Function called root. The server and the client build deploy together and roll back together. If you know the React Router docs, you know where everything is:

app/root.tsx              the document and the error page
app/routes/home.tsx       the list: a loader, and a form with an action
app/routes/book.tsx       one book: a loader that answers 404 for an unknown id
app/books.ts              the data, as a fixed list
server.ts                 the Function: React Router's request handler as `fetch`

The list page reads its data in a loader, so the books are in the HTML before any script runs:

export async function loader({ request }: Route.LoaderArgs) {
  const suggested = new URL(request.url).searchParams.get("suggested");
  return { books: await listBooks(), suggested };
}

The form posts to an action in the same file. A blank title gets a 400. Otherwise the action redirects, so a reload doesn’t post again.

Run it

npx wawesome init --template react-ssr

It offers to log you in if you aren’t. Then it asks for a Function name and an App slug. Keep the name root, the only one that answers at your App’s own hostname. If you haven’t deployed yet, it offers to change your workspace address, which locks at your first deploy. There’s nothing else to set. It deploys and prints the address. Open it and view the page source. The list is already in the HTML.

To work on it locally, run npm run dev, React Router’s own dev server.

What to change first

The data in app/books.ts. It’s a fixed list, and the form doesn’t save anything. To keep what people send, have the action write it to a database you reach over fetch, such as a Supabase table. Add that host to your App’s allowlist first, because outbound calls are closed by default.

What it doesn’t do

It doesn’t answer under a preview URL. The engine has no Intl, and toLocaleString ignores the locale, so a price that shows 1,234.50 on your machine shows 1234.5 in production. npm test fails on each use, so run it before you deploy. One render has a fixed fuel budget, so paginate long lists. When a render throws, the page shows the error boundary in app/root.tsx, and we put the stack in your logs: npx wawesome logs --follow.

  • react
  • react-router
  • ssr
  • vite
  • frontend
  • typescript

Ready in about a minute

Sign in with GitHub, deploy, and get a public HTTPS endpoint.

Deploy this template