Skip to content

Commit 606241e

Browse files
justin808claude
andauthored
docs: add "RoR Pro vs TanStack Start" architecture comparison (#4246)
## What Adds **`docs/pro/react-server-components/tanstack-start-comparison.md`** — a dedicated architecture comparison of React on Rails Pro and **TanStack Start**, paralleling the merged [RSC vs. Next.js doc](https://reactonrails.com/docs/pro/react-server-components/nextjs-comparison) (#4158). It sits next to the Next.js comparison in the RSC docs section but takes a different axis: the Next.js doc compares two _RSC implementations_, whereas TanStack Start is _client-first_ rather than RSC-first — so this doc compares **two ways to own the full stack**. Companion to the decision-guide section in #4242 (that's the short "which do I pick" entry; this is the deep architecture explainer it can point to). ## Framing (calibrated to mid-2026) - **Splits the TanStack suite.** Query/Router/Table are complementary and run on top of Rails; only **Start** (the framework) substitutes — and specifically for the **server tier**. - **Grounded in Start's current shape.** SSR-first (server-rendered by default; selective per-route SSR); ships **no ORM/database** ("bring your own backend"; Drizzle common). Rails is that backend, batteries included. - **RSC = the colocation answer**, described as Pro-supported (Node renderer), **not** "experimental." - **Honest about RoR's costs.** Two languages; untyped JSON boundary (closed via generated types — flagged as roadmap); extra dev processes vs. Start's single Vite command. - **Fair to Start.** Explicitly concedes greenfield / no-Rails / one-language / velocity-first. - Mirrors the exemplar's neutral tone ("neither is better") and "as of 2026" accuracy hedges. ## Gates - `npx prettier@3.6.2 --write` ✓ - `node script/generate-llms-full.mjs` ✓ (`llms-full.txt` + `llms-full-pro.txt` regenerated) - `script/check-docs-sidebar` ✓ (registered in `docs/sidebars.ts` next to `nextjs-comparison`) - `lychee` ✓ 8/8 OK, 0 errors (only external link is the starter repo; TanStack Start is described conceptually with no external link, matching the Next.js doc's precedent) ## Note Independent of #4242 (different files), so they can merge in any order. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added a new guide comparing React on Rails Pro and TanStack Start for teams evaluating full-stack React approaches. * Includes a side-by-side look at architecture, rendering behavior, type safety, developer workflow, and decision guidance. * **Chores** * Updated the documentation navigation and machine-readable docs list so the new page appears in the React Server Components section. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 0eb39c5 commit 606241e

3 files changed

Lines changed: 384 additions & 0 deletions

File tree

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
---
2+
sidebar_label: 'RoR Pro vs TanStack Start'
3+
description: 'How React on Rails Pro and TanStack Start divide the full stack: which TanStack libraries complement Rails, where server logic and data live, RSC vs. server functions, type safety, and a capability comparison.'
4+
---
5+
6+
# React on Rails Pro and TanStack Start: Two Ways to Own the Full Stack
7+
8+
> [!NOTE]
9+
> The TanStack client libraries (Query, Router, Table) work with open-source React on Rails. React
10+
> Server Components and TanStack Router **SSR** require [React on Rails Pro](../react-on-rails-pro.md)
11+
> with the Node renderer.
12+
13+
> [!NOTE]
14+
> **Summary for AI agents:** Use this page to understand how React on Rails Pro and TanStack Start
15+
> divide responsibility for the full stack — and why most of the "TanStack vs. React on Rails"
16+
> confusion dissolves once you separate the TanStack _libraries_ (Query, Router, Table) from the
17+
> TanStack _framework_ (Start). It is an _architectural_ explainer, not a how-to. For building with the
18+
> libraries on Rails, route to [TanStack Router](../../oss/building-features/tanstack-router.md). For the
19+
> RSC contract this page references, route to [RoR Pro vs. Next.js RSC](./nextjs-comparison.md). For
20+
> "which should I pick," route to the
21+
> [Decision Guide](../../oss/getting-started/comparing-react-on-rails-to-alternatives.md).
22+
23+
> [!NOTE]
24+
> **Accuracy note.** React on Rails Pro details are verified against this repository. TanStack Start
25+
> details are described at the **conceptual** level and reflect TanStack Start as of **2026** (it reached
26+
> a stable 1.x release earlier in the year). The TanStack ecosystem evolves quickly; treat specific
27+
> TanStack names and feature labels here as illustrative of an idea, not as a stable API.
28+
29+
"Should we use TanStack or React on Rails?" is the wrong question, because **"TanStack" is not one
30+
thing.** TanStack publishes a suite of client libraries _and_ a full-stack framework, and they sit on
31+
opposite sides of the line that matters to a Rails team. Once you split them, the comparison is clear:
32+
the libraries are complementary, and only the framework is a genuine either/or.
33+
34+
## "TanStack" is two different things
35+
36+
| What | What it is | Role for a Rails team |
37+
| ------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
38+
| **TanStack Query** | Client-side server-state cache (fetch, cache, invalidate) | **Complement.** Point it at a Rails JSON API. |
39+
| **TanStack Router** | Type-safe client router with data loading + search-param validation | **Complement.** Client-only works in OSS; SSR is a Pro feature (see [TanStack Router](../../oss/building-features/tanstack-router.md)). |
40+
| **TanStack Table** | Headless table/data-grid primitives | **Complement.** Renders from Rails-served data. |
41+
| **TanStack Start** | Full-stack React framework (TanStack Router + Vite + Nitro + server functions) | **Substitute.** This is the layer that overlaps with Rails. |
42+
43+
Adopting Query, Router, and Table does **not** require leaving Rails — React on Rails apps use them on
44+
top of a Rails backend today. The only part you are choosing _between_ is the framework: **TanStack
45+
Start or Rails as the thing behind your React app.** The rest of this page is about that one choice.
46+
47+
## Two ways to get a server
48+
49+
A mental model before the mechanics. Every non-trivial React app needs a server for the same jobs:
50+
data access, authorization, persistence, background work, and rendering HTML for first paint and SEO.
51+
The two stacks supply that server very differently.
52+
53+
- **TanStack Start brings the _wiring_ for a server, and you supply the server.** Start is
54+
**SSR-first**: routes are server-rendered by default, with fine-grained selective SSR to opt a route
55+
out (`ssr: false` / `'data-only'`, or SPA mode). Its server story is **server functions** — typed functions guaranteed to run server-side,
56+
callable from the client as if they were local. But Start ships **no database, ORM, or auth of its
57+
own**; it works with "any database, bring your own stack" (Drizzle is the common choice). You assemble
58+
the backend; Start types the boundary to it.
59+
- **React on Rails Pro brings the React station, and Rails is already the server.** Your Rails app has
60+
the kitchen — ActiveRecord, authorization, jobs, caching, mature libraries. React on Rails (and React
61+
on Rails Pro for SSR/RSC) adds React as the view layer on top, with the TanStack client libraries
62+
where they help. You keep Rails and add React; you do not assemble a backend.
63+
64+
Neither is "better." They answer different questions. _"I'm building a React app and have no backend
65+
yet"_ points toward TanStack Start. _"I have, or want, Rails, and want a modern React frontend on it"_
66+
points toward React on Rails.
67+
68+
## Where your server logic lives
69+
70+
The strongest line in the TanStack Start pitch is **colocation**: server code sits next to the
71+
component that needs it, with no separate API endpoint and no serializer. A server function reads from
72+
your database and returns typed data to the component.
73+
74+
React on Rails Pro's answer to that colocation pitch is **React Server Components**. An RSC runs on the
75+
server and renders from data your Rails controller prepared — passed as props, or streamed as
76+
[async props](../../oss/migrating/rsc-data-fetching.md) for slow data — with no `/api` round-trip and
77+
no serializer for that view. You get the colocation benefit; the difference is _what_ the server code
78+
is: a Rails-prepared data flow rather than a TypeScript function, so authorization, caching, and the
79+
database stay in Rails where they already live. (RSC is a Pro feature requiring the
80+
[node renderer](../node-renderer.md); for how the RSC contract itself works, see
81+
[RoR Pro vs. Next.js RSC](./nextjs-comparison.md).)
82+
83+
For the interactive pieces that **mutate**, both stacks still cross a network boundary: Start calls a
84+
typed server function; React on Rails posts to a Rails controller (often with TanStack Query driving the
85+
request). Start's server-function shorthand is genuinely less boilerplate for that path today; the trade
86+
is that the function — and the business logic inside it — lives in your UI's runtime rather than in
87+
Rails.
88+
89+
## The backend you assemble vs. the backend you have
90+
91+
This is the difference that usually decides it for an existing Rails team. TanStack Start is, by design,
92+
a frontend framework with a server-function transport — **it does not provide the backend**.
93+
Persistence, schema and migrations, an ORM, authentication, authorization, and background jobs are all
94+
things you add from separate libraries and own yourself.
95+
96+
Rails _is_ that backend, batteries included. So the choice is rarely "Start vs. Rails" as peers; it is
97+
"a backend you assemble out of Drizzle-plus-libraries behind Start's server functions" vs. "the Rails
98+
backend you already have, with React in front." If you have no Rails investment and want one language
99+
end to end, assembling is reasonable. If you have Rails — or would choose it for the data layer — Start
100+
is solving a problem you have already solved, in a second language.
101+
102+
## Rendering and first paint
103+
104+
- **TanStack Start** is **SSR-first**: routes are server-rendered by default. It offers fine-grained
105+
**selective SSR** — opt a route out with `ssr: false` or `ssr: 'data-only'`, or use SPA mode — which
106+
is a genuine strength for tuning per-route rendering.
107+
- **React on Rails** server-renders React from Rails — in open-source via ExecJS, or via the Node
108+
renderer in **React on Rails Pro**, which adds streaming SSR and RSC: the HTML shell streams
109+
immediately and server-rendered data streams in progressively. TanStack Router state can be SSR'd and hydrated via Pro
110+
([TanStack Router](../../oss/building-features/tanstack-router.md)), and a TanStack Query cache can be
111+
seeded from Rails so the first page of data is in the initial HTML rather than fetched after
112+
hydration.
113+
114+
## Type safety across the boundary
115+
116+
Type safety is a real Start advantage worth stating plainly. Because Start's server functions are
117+
TypeScript on both sides, the client/server boundary is **end-to-end typed** with no codegen.
118+
119+
React on Rails talks to Rails over a JSON boundary that is **not typed by default** — a Ruby backend and
120+
a TypeScript client do not share a type system. Teams close this by generating TypeScript types from the
121+
Rails side (serializers or schema). That is the honest gap: Start gets cross-boundary types for free; on
122+
Rails you generate them. (Improving this out of the box is on the roadmap — check the
123+
[release notes](../release-notes/index.md) for the current state.)
124+
125+
## Comparing capabilities
126+
127+
> Marked "as of 2026" where a row reflects a current state rather than a permanent design choice. Both
128+
> ecosystems move quickly — check each project's release notes before treating a label as permanent.
129+
130+
| Capability | React on Rails (+ Pro) | TanStack Start |
131+
| --------------------------------- | --------------------------------------------------- | --------------------------------------- |
132+
| Client data cache (Query) | Yes — TanStack Query against Rails | Yes — TanStack Query |
133+
| Type-safe client routing (Router) | Yes — TanStack Router; SSR is Pro | Yes — built in (Router is the core) |
134+
| Headless tables (Table) | Yes — TanStack Table | Yes — TanStack Table |
135+
| Backend (DB, ORM, auth, jobs) | Rails, batteries included | Bring your own (e.g. Drizzle) |
136+
| Server-logic colocation | RSC (Pro) + Rails controllers | Server functions |
137+
| Typed client/server boundary | Generate types from Rails (as of 2026) | Built-in (TypeScript on both sides) |
138+
| Default rendering | Server-rendered (Rails); streaming SSR + RSC in Pro | SSR by default; selective per-route SSR |
139+
| Language(s) | Ruby + TypeScript | TypeScript end to end |
140+
| Hosting model | Your Rails app + a Node renderer process (Pro) | One Node (or Edge) server process |
141+
142+
The pattern mirrors the framework-vs.-libraries split: **the TanStack client libraries are shared
143+
ground** — both stacks use Query, Router, and Table. The divergence is entirely in the **server tier**:
144+
Start gives you a typed transport to a backend you assemble in one language; React on Rails gives you
145+
Rails as the backend with React (and RSC) in front, at the cost of two languages and, for Pro SSR/RSC, a
146+
couple more moving parts.
147+
148+
## Developer experience: one process vs. several
149+
150+
TanStack Start development is a single Vite-driven command with one server process and a fast dev loop —
151+
a real strength, and part of why teams cite it when leaving heavier frameworks.
152+
153+
React on Rails Pro development orchestrates several processes — Rails, the client dev-server (HMR), the
154+
bundle watchers, and the node renderer — typically managed together by `bin/dev` and a Procfile. That is
155+
the honest price of bolting onto Rails rather than owning the server. Choosing **Rspack** (Rust + SWC)
156+
closes much of the compile-speed gap while keeping the webpack-compatible config Shakapacker relies on.
157+
158+
## When you should choose TanStack Start
159+
160+
To keep this honest: if you are **greenfield with no backend**, want **one language** end to end, and
161+
are a small team **optimizing for raw velocity**, TanStack Start is a genuinely good choice and React on
162+
Rails is not the pitch. Start is a mature, well-designed framework; the case for React on Rails is
163+
specifically about teams that have, or want, **Rails as a real backend** under a modern React frontend.
164+
165+
## Which should you choose?
166+
167+
This page is about _architecture_, not selection. For the decision itself:
168+
169+
- [Decision Guide: React on Rails vs. TanStack Start and other alternatives](../../oss/getting-started/comparing-react-on-rails-to-alternatives.md)
170+
- [RoR Pro vs. Next.js RSC](./nextjs-comparison.md) — the RSC contract referenced above, compared across stacks
171+
- [React on Rails Pro + TanStack starter](https://github.com/shakacode/react-on-rails-starter-tanstack) — a runnable app using TanStack Query, Router, and Table against a Rails backend, with Pro SSR/RSC
172+
173+
## Summary
174+
175+
"TanStack vs. React on Rails" is really two questions. The TanStack **client libraries** — Query,
176+
Router, and Table — are **complementary**: React on Rails apps use them on top of a Rails backend today.
177+
Only TanStack **Start**, the full-stack framework, is a **substitute**, and the substitution is
178+
specifically for the **server tier**. TanStack Start is SSR-first (server-rendered by default, with
179+
selective per-route SSR) and a typed **server-function** transport, but it ships **no backend** — you
180+
bring the database, ORM, auth, and jobs. React on Rails keeps **Rails** as that backend, batteries included, with React as the view layer;
181+
React on Rails Pro adds streaming SSR and **React Server Components**, which remove the extra `/api`
182+
round-trip for a view while keeping data access in Rails. Start wins on one language and a free
183+
end-to-end type boundary; React on Rails wins when you want a real backend — Rails — under your React,
184+
and would rather adopt the TanStack libraries on top of it than rebuild the backend in JavaScript.
185+
186+
## Related documentation
187+
188+
- [TanStack Router on React on Rails](../../oss/building-features/tanstack-router.md) — using TanStack Router, with Pro SSR support
189+
- [RoR Pro vs. Next.js RSC](./nextjs-comparison.md) — how the RSC contract works, compared across stacks
190+
- [React Server Components overview](./index.md) — the full RSC documentation set
191+
- [Decision Guide](../../oss/getting-started/comparing-react-on-rails-to-alternatives.md) — choosing between React on Rails, TanStack Start, Next.js, and other alternatives

docs/sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ const sidebars: SidebarsConfig = {
253253
'pro/react-server-components/per-request-data',
254254
'pro/react-server-components/rspack-compatibility',
255255
'pro/react-server-components/nextjs-comparison',
256+
'pro/react-server-components/tanstack-start-comparison',
256257
'pro/react-server-components/glossary',
257258
{
258259
type: 'category',

0 commit comments

Comments
 (0)