Skip to content

Inertia RustInertia Rails, in Rust.

The Inertia Rails starter kit, ported to Loco. React 19 and shadcn/ui pages, rendered by a Rust server that has auth, accounts, live updates and generators built in. One binary, SQLite, no API layer.

Inertia Rust

A controller and the page it renders โ€‹

The controller loads the data and hands it to a React page as props. There's no JSON API in between, and nothing to keep in sync.

rs
// src/controllers/projects.rs
async fn index(
    current: CurrentAccount,
    State(ctx): State<AppContext>,
    inertia: Inertia,
) -> Result<Response> {
    let projects: Vec<Value> = projects::Model::list(&ctx.db, current.account.id)
        .await?
        .iter()
        .map(projects::Model::to_props)
        .collect();
    render(inertia, "projects/index", json!({ "projects": projects })).await
}
tsx
// frontend/pages/projects/index.tsx
import { Link } from "@inertiajs/react"

import { useCurrentAccount } from "@/hooks/use-current-account"
import { projects as routes } from "@/routes"

interface Project {
  id: number
  name: string
}

export default function Projects({ projects }: { projects: Project[] }) {
  const { slug: accountSlug } = useCurrentAccount()

  return (
    <ul>
      {projects.map((project) => (
        <li key={project.id}>
          <Link href={routes.show({ accountSlug, id: project.id })}>
            {project.name}
          </Link>
        </li>
      ))}
    </ul>
  )
}

cargo loco generate scaffold projects name:string! writes both, plus the model, migration, routes and tests.

The Inertia way โ€‹

No API layer

Controllers render pages, not JSON. Inertia sends the page's props on navigation and React renders them.

Props from Rust to React

A controller passes props to render(inertia, "projects/index", โ€ฆ). Routes are typed on both sides, generated from one route table.

Mutations redirect

Forms post, the controller validates and redirects with a flash or an error bag. The same loop as Rails, with the same messages.

If you know Inertia Rails, you already know how this app works: the routes, pages and flash messages match the Inertia Rails React Starter Kit it was ported from. Rails โ†’ Loco maps every rails command to its equivalent here.

The kit's home page, light themeThe kit's home page, dark theme

The numbers โ€‹

Both kits as production Docker images on the same workstation, 4 pinned CPUs each, SQLite, SSR off, Rails with YJIT and Puma 4ร—3. Medians of 5 runs, 2026-10-04.

57 ms
boot to first response, vs 1.6 s for the Rails kit
5โ€“8ร— less
memory: 42 / 65 MiB idle / after load, vs 210 / 509 MiB
4.5โ€“11ร—
requests per second, e.g. 26,435 vs 5,928 on the signed-in page (Inertia visit)
2.1 ms
p99 on the signed-in page, vs 11.2 ms (5.4ร— lower)
52 MB
compressed Docker image, vs 207 MB

The caveats are real. Under a 4 GB container limit, 0.17% of SQLite writes from 32 writers failed with a 500 (pool timeouts during write stalls; none with 32 GB), where Rails had none. With SSR on, Node is the bottleneck and throughput is about equal. The Rails kit builds its image faster from cold and reloads code instantly. Method, ranges and every caveat: the full benchmark.

Get started โ€‹

Click Use this template on GitHub, or clone it. You need Rust (rustup) and Node 22.

sh
git clone https://github.com/cole-robertson/inertia-rust-starter-kit.git myapp
cd myapp
bin/rename my_app "My App"   # optional, but do it before the first bin/setup (see below)
bin/setup                    # npm ci, cargo build, migrate, seed, then bin/dev

Open http://localhost:5150 and sign in as [email protected] / Secret1*3*5*. Then build your app: rename it, scaffold a resource, add jobs and mail, deploy.

FAQ โ€‹

Why Rust? โ€‹

For one small binary that boots in milliseconds, uses a fraction of the memory and serves more requests per core, with the compiler checking the server code and typed routes shared with React. Loco brings Rails' shape to Rust: generators, migrations, jobs, mailers, tasks. The trade is slower builds and no autoloading; see the benchmark for both sides.

How close is it to the Rails kit? โ€‹

It's a port of the Inertia Rails React Starter Kit: the same routes, pages, texts and flash messages, checked by a parity oracle that compares both kits' responses. Organizations are added on top. Every intended difference is listed in Parity with the Rails kit.

Can I use Postgres? โ€‹

Not out of the box. The kit ships SQLite (WAL mode) for the app and its job queue, and the benchmark, the deploy targets and some code (src/db.rs) assume it. Loco and SeaORM support Postgres, so a switch is possible, but you'd be doing it yourself.

Do I need to know Rust? โ€‹

You'll read and write some. The generators write most of the server code, the pages are plain React and TypeScript, and AGENTS.md plus the kit's skills give a coding agent the exact steps for each task. Rails experience carries over: Rails โ†’ Loco.

Is it production-ready? โ€‹

It's v0.1. It has tests (Rust request and protocol tests, Playwright in client- and server-rendered modes), a security review and CI on every change, and the live demo runs it. But it's new, it has few users yet, and SQLite means one app server per database. Read the changelog and judge for yourself.

Why accounts by default? โ€‹

Most business software keeps data per organization, and accounts are cheap to keep but expensive to add to an app that already has data. If your app has no teams, the accounts guide shows how to flatten it.

Released under the MIT License.