Inertia + React starter
Rails 8.1 + Inertia + React 19 + TypeScript + Vite + Tailwind v4 + shadcn/ui starter kit, with Supabase Auth via supabase-rails in :web mode and optional Inertia SSR.
The Inertia + React starter is a Rails 8.1 monolith with a typed React frontend served through Inertia.js. Pages are React components rendered against props the Rails controller hands over; navigation goes through Inertia's XHR-driven page swaps. Auth is owned by supabase-rails in :web mode — the browser holds an encrypted sb-session cookie, not a token, and every request reaches the React tree with auth.user already populated.
What is it
A Rails 8.1 + React 19 starter pre-wired for a productive day-one experience:
- Inertia Rails — controllers
render inertia: "pages/<name>"instead of ERB; React resolves the component and renders againstprops. No separate API tier, no client-side router. - Vite + React + TypeScript — Vite drives dev (HMR), build, and (optional) SSR. React 19 with the React Compiler preset turned on, TypeScript across the entire
app/javascript/tree. - shadcn/ui (new-york) — full
components.jsonis checked in.@/components/ui/*ships ~25 primitives (button,card,dialog,dropdown-menu,field,input,sidebar,sonner, etc.) built on Radix UI + Tailwind v4 +class-variance-authority. - Cookie-backed auth —
supabase-railsin:webmode issues an encryptedsb-sessioncookie and exposesCurrent.useron every controller; anInertiaControllerparent forwards it to React as a sharedauth.userprop. - Typed routes — Typelizer generates
app/javascript/routes/*.tsfrom Railsroutes.rb, sodashboard.index().url,sessions.create(), andsettingsPasswords.show()are type-checked. - Optional Inertia SSR — shipped wired but disabled. Flip
config.ssr_enabled = trueand the Pumainertia_ssrplugin boots the Node renderer in-process. - Local Supabase — a checked-in
supabase/config.tomlletssupabase startboot a full Auth + Postgres + Studio + Mailpit stack in Docker. - Kamal deploy —
Dockerfileandconfig/deploy.ymlare scaffolded; the SSR bundle is gated by aSSR_ENABLEDbuild arg.
Who it's for
Pick this kit when:
- You want a typed React frontend (TypeScript + shadcn) but no separate Rails API + Next.js split.
- You're happy with Rails owning routing, controllers, and props — and React owning the view layer.
- You want Supabase Auth to handle the identity surface (email + password, sign-up with confirmation, password reset, magic-link) and not write that code yourself.
- You're comfortable holding session state in an encrypted cookie rather than an
Authorizationheader — the browser never sees the Supabase access token.
If you'd rather render server-side HTML with Hotwire and skip the JS build step entirely, look at the Hotwire starter. If your client is a mobile or third-party SPA, the Rails API starter is the JWT-only counterpart.
What's included
| Layer | What ships in the box |
|---|---|
| Auth | supabase-rails in :web mode, Authentication concern, parent InertiaController shares auth.user to React |
| Auth UI | pages/sessions/new.tsx, pages/registrations/new.tsx, pages/passwords/{new,edit}.tsx, pages/otp/{new,verify}.tsx, wrapped in AuthCardLayout |
| Routes | Public /, authenticated /dashboard, /settings/{email,password,appearance}, plus the gem's supabase_authentication_routes |
| React tree | app/javascript/{pages,components,layouts,hooks,lib,routes,types}/ with shadcn/ui primitives under components/ui/ |
| Typed routes | Typelizer regenerates app/javascript/routes/*.ts on every server reload |
| Build | Vite + @vitejs/plugin-react + @tailwindcss/vite + @inertiajs/vite + rails-vite-plugin; React Compiler preset enabled |
| Data | SQLite for primary, cache, queue, cable; Supabase Postgres holds auth.users (no domain table out of the box) |
| Tests | RSpec request specs under spec/requests/; system-test infrastructure (Capybara + Selenium) is configured but not exercised by shipped specs |
| Deploy | Dockerfile (multi-stage, SSR-gated by build arg) and Kamal config/deploy.yml |
What's not included
The kit stops short of two large surfaces so you can grow into them:
- MFA / passkeys / sudo mode. Same shape as the other kits — none of
rotp,webauthn,bcryptare in the Gemfile, and the settings tree has no security section. - An ActiveRecord
Usermodel.Current.useris a value object built from the verified Supabase claims;InertiaController#current_user_propsshapes it for React asauth.user. Runbin/rails generate supabase:user_modelwhen you need a host-appuserstable. - A domain resource. Unlike the Hotwire kit's
/notesview, the React dashboard ships empty — three placeholder cards from@/components/placeholder-pattern. Add your own as your first feature; the Architecture and Customization pages walk the pattern. - End-to-end test harness. RSpec request specs run against
SupabaseAuthHelpersstubs (inspec/support/). There's nobin/e2eequivalent — Inertia request specs verify the JSON props contract, which is usually enough. - Per-target deploy guides.
Dockerfileand Kamal config are generic; turning them into a Fly / Render / ECS flow is up to you. - Production observability. Logs go to STDOUT. Wire APM (Sentry, Datadog, OpenTelemetry) when you need it.
Next
Getting started
Prerequisites, clone, install, env, and a signed-in dashboard in 15 minutes.
Project structure
Walk through app/, config/, supabase/, db/, and spec/ — including the React tree under app/javascript/.
Architecture
The Inertia request lifecycle, the Vite + React frontend layer, shadcn/ui wiring, and the Supabase integration points.
Customization
React/Inertia recipes — add a new page, add a shadcn component, wire Supabase Realtime into a React component.
Deployment
Production-readiness checklist — secrets, SSR build flag, TLS, cache, health checks, observability.
Troubleshooting
First-run failures and how to read them — Vite not serving, typed-route stale, SSR fallback loops, shadcn add fails.
Repository
- Source:
supabase-ruby/starter-kit-inertia-react - Underlying gem:
supabase-rails - Based on: Laravel React Starter Kit (re-implemented for Rails + Inertia)
Troubleshooting
Most likely first-run failures with the Hotwire starter — missing env, expired-session loops, empty notes list, Tailwind not building, Importmap pin missing, Letter Opener empty — and how to resolve them.
Getting started
Clone the Inertia + React starter, install Ruby + Node dependencies, point it at a Supabase project, and sign in for the first time.