On March 18, 2026, TanStack Start tagged v1.0. The release post was short. The tagline on the homepage is shorter: "Full-stack Framework powered by TanStack Router for React and Solid." No keynote. No conference launch. No new cloud.
That understatement is the story. For the first time in roughly five years, a new React app team has a non-Vercel option that does not feel like a hobby project or a hedge. Start is not trying to be Next.js for hipsters. It is built on a different premise, and the premise has finally caught up with the rest of the ecosystem.
What v1 actually contains
The v1 RC announcement listed the surface area in plain bullets. Type-safe file-based routing on top of TanStack Router. Isomorphic server functions. Streaming SSR. URL-as-state primitives with runtime validation. Deep integration with TanStack Query for prefetching, caching, and hydration.
What is not there is worth saying out loud: React Server Components. The team is shipping RSC as a non-breaking 1.x addition, not as part of 1.0. If your mental model of "modern React framework" is app/ directories and "use server" directives, Start is missing your main feature.
Server functions cover most of the same ground. You declare a function, mark it server-only, and call it from the client with full types. The difference is that Start is honest about the boundary - the function executes on the server, the client gets a typed RPC. There is no rendering-on-the-server illusion to maintain.
import { createServerFn } from "@tanstack/start";
import { z } from "zod";
export const getPost = createServerFn("GET", async (slug: string) => {
const post = await db.posts.findUnique({ where: { slug } });
return post;
}).validator(z.string());
// In a route loader - inferred return type, no client bundle for db.
export const Route = createFileRoute("/posts/$slug")({
loader: ({ params }) => getPost(params.slug),
component: PostView,
});URL state, in practice
The cleanest way to feel the philosophical difference is to look at a typical scenario: a paginated, filterable list view. In Next.js, you reach for searchParams on a page component, decide whether to revalidate or stream, parse strings into numbers, and write client-side handlers that update the URL through router.push with a manually constructed query string. Type safety stops at the function boundary.
In Start, you describe the URL as a schema and the framework does the rest:
import { createFileRoute } from "@tanstack/react-router";
import { z } from "zod";
const searchSchema = z.object({
page: z.number().int().min(1).catch(1),
status: z.enum(["draft", "published", "all"]).catch("all"),
q: z.string().optional(),
});
export const Route = createFileRoute("/posts/")({
validateSearch: searchSchema,
loaderDeps: ({ search }) => search,
loader: ({ deps }) => listPosts(deps),
component: PostList,
});
function PostList() {
const search = Route.useSearch(); // fully typed
const navigate = Route.useNavigate();
return (
<button
onClick={() =>
navigate({ search: (prev) => ({ ...prev, page: prev.page + 1 }) })
}
>
Next page ({search.page})
</button>
);
}Three things are happening that no Next.js equivalent gives you. First, search.page is number - not string | undefined that you have to coerce. Second, the .catch() branches make every URL valid by construction: a hand-crafted ?page=banana snaps back to 1 instead of throwing. Third, navigate takes a typed updater, so renaming page to pageIndex is a refactor, not an archaeological dig through string interpolation.
This is not novel. Remix had a version of this. So did SvelteKit. What is novel is that Start treats it as the default shape of the application rather than a feature you opt into.
Router-first, not page-first
Every other React framework starts from "a page is a thing the user navigates to" and adds routing as plumbing. TanStack Start inverts that. The router is the application. Routes are typed objects. The URL is a piece of state with a schema. Loaders and pending states are properties of the route, not lifecycle ceremonies inside a component.
In Next.js, useSearchParams() returns URLSearchParams. You parse it. You validate it. You re-parse it on every render. In Start, search params are a typed object validated by Zod at route boundaries, and the framework will reject navigations with invalid shapes before the component renders. You can refactor a search param rename across the codebase with the TypeScript language server, the same way you rename a function.
TanStack Start treats your application as a single-page app that gains SSR benefits, not a server application that happens to have client interactions.
That sentence, lifted from the project's own positioning, is the entire architectural disagreement with Next.js compressed into one line. Next.js 16's upgrade guide runs to thousands of words because the page model leaks: cookies are async now, params are promises, middleware renamed to proxy, PPR replaced by cacheComponents, AMP gone, next lint gone. Each individual change is reasonable. The cumulative weight is the cost of "server-first that happens to be a client app."
Vite, by choice
Start runs on Vite. This sounds like a footnote and is not. Two things follow from it.
First, dev startup is fast in a way Next.js stopped pretending to compete on. Vite 8 shipped with Rolldown in March, and the Rust-based bundler is the default. Next.js 16 made Turbopack default for next dev and next build, which is the right move, but Turbopack is a Vercel project that primarily exists to serve Next.js. Vite has eight years of community plugins, a different funding model, and a roadmap that does not have to optimize for App Router's quirks.
Second, deployment is no longer a partnership question. Anywhere Vite can output a Node or worker bundle, Start can run. The homepage lists Netlify and Cloudflare as partners, but the more honest claim is the one buried in the docs: "compatible with any Vite-supported hosting provider." You write your app. You pick a host. The host is not a stakeholder in your framework.
This matters more this month than it did a year ago. Cloudflare announced on May 7 that it is cutting 1,100 roles to restructure around an "agentic AI-first operating model." Vercel's compute story has its own pricing turbulence. Framework decisions and infrastructure decisions used to be the same decision. They no longer have to be.
Migrating from React Router 7
The most likely Start adopter is not a Next.js refugee. It is a team that has been running Vite plus React Router 7 since the framework mode landed in late 2024, and has been quietly wondering when to commit to a heavier framework. For that team, Start is barely a migration. It is an upgrade.
React Router 7 in framework mode and TanStack Router share enough conceptual DNA that the route file structure, loaders, and actions translate almost mechanically. The differences sit at the edges:
- Loaders return typed data in Start without
useLoaderData<typeof loader>()generic gymnastics; the type flows from the route definition. - Actions become
createServerFncalls, which are less HTTP-shaped but more refactorable - you can rename, extract, and share them like any other function. - Search params become first-class state instead of a
URLSearchParamsobject you have to babysit.
The teams I have seen attempt this migration report a day per developer for a 30-route app, most of which is spent rewriting Zod schemas they should have written years ago. The codemod story is thin - there is no official one - but the textual replacement is so close that sed and grep get you most of the way.
The harder question is whether you should migrate at all. React Router 7 is going nowhere; it ships with Remix 3 and has a guaranteed maintenance trajectory through Shopify. If your app does not need server functions and your team is comfortable with the loader/action paradigm, the gain from Start is incremental, not transformative. The question to ask is whether you find yourself reaching for useEffect to sync URL state. If yes, Start pays for itself.
What the benchmarks actually show
Numbers from the community comparisons of Start v1 against Next.js 16, on a representative dashboard app with around 40 routes and TanStack Query on the client:
- Local dev startup: roughly 2-3 seconds for Start versus 10-12 seconds for Next.js 16 with Turbopack. Both are warm-cache numbers; cold is worse for Next.
- Baseline client bundle: around 42KB gzipped for a Start hello-world, against 92KB gzipped for an equivalent Next.js App Router page. The delta is mostly the RSC runtime that Start does not ship.
- Build time for the 40-route app: Start with Vite 8 finishes in roughly half the time of Next.js with Turbopack, though both are now in the seconds-not-minutes range that makes the comparison less interesting than it would have been in 2024.
These numbers are real and they are also not the point. Nobody picks a framework because dev server starts seven seconds faster. They matter as proxies for architectural weight - and the architectural weight of Start is meaningfully lower, which shows up in less obvious places: fewer footguns around hydration, smaller dependency trees to audit, faster CI.
The thing that is harder to benchmark, and that I think actually moves teams, is how much of the framework you have to keep in your head. A Next.js 16 developer needs a working model of server components, server actions, Suspense, the route segment cache, the data cache, the full-route cache, revalidateTag versus updateTag, cookies() timing, partial prerendering, and the proxy/middleware split. A Start developer needs routes, loaders, server functions. The smaller surface area is its own form of performance.
The Next.js 16 contrast, in three changes
Pulling specific things from the Next.js 16 upgrade guide makes the trade-off concrete:
- Async request APIs are no longer optional.
cookies(),headers(),params, andsearchParamsall return promises. Existing 15-era code that read them synchronously breaks. The codemod helps, but the conceptual cost - "every request boundary is now async" - is permanent. middleware.tsbecomesproxy.ts, and the file no longer supports the edge runtime. If you were using middleware to do edge-level redirects, you have to migrate to a different mental model.revalidateTagnow requires acacheLifeargument and the framework introducesupdateTagfor read-your-writes semantics. The cache surface area grew faster than the documentation for when to use which.
None of these are bad changes. Each one fixes something real. But they are the changes of a framework that is converging on a particular vision - server-first React with a cache as the central abstraction - and asking everyone to converge with it.
Start is doing the opposite: holding the client-first position and adding server capabilities as opt-in tools. If you believed App Router was the future, you can ignore Start. If you ever quietly wondered whether App Router was a future you wanted, Start is the first answer that does not require giving up TypeScript-level rigor.
How it gets paid for
Worth pausing on the governance question, because framework durability is mostly a question of who funds maintenance. Next.js is a Vercel product; its roadmap is shaped by what helps Vercel sell compute. That is not pejorative - it is a stable arrangement, and it explains why App Router rewards co-locating data fetching with rendering on edge functions. Remix is a Shopify product since the acquisition; its roadmap leans toward stable primitives that survive long-term.
TanStack is something different: a maintainer-funded project, primarily through GitHub Sponsors and corporate partnerships with hosts (Netlify, Cloudflare, AG Grid) that pay for placement rather than direction. Tanner Linsley publishes the financials. The numbers are healthy enough to sustain a small core team but small enough that the project cannot afford to chase a vendor's preferred deployment shape. That is the source of the vendor-neutrality, and also the reason the docs are sometimes thin: there is no army of devrel writers.
Whether you view this as a strength or a risk depends on your tolerance for projects that are not owned by a public company. The track record - TanStack Query has been a foundational React library for seven years - is the answer the project gives, and it is a credible one.
Where it falls short
Three honest gaps.
RSC is not here. If your team has standardized on server components - co-located data fetching, async components, the works - Start cannot give you that today. The roadmap commits to it as a non-breaking addition, which in practice means a v1.4 or v1.5 release. That could be six months. It could be eighteen.
The ecosystem is thinner. Auth, image optimization, observability - the recipes exist, but you assemble them. Auth.js works. The @tanstack/start-cloudflare and @tanstack/start-netlify adapters work. But there is no equivalent of next/image with a CDN baked in, no equivalent of Vercel Analytics that just appears in your dashboard. You are operating one layer closer to the metal.
And the docs are still uneven. Some pages assume you have read the Router docs. Some assume you have not. The Router docs themselves have been stable longer than Start has, and the seams show.
The Solid footnote that is not a footnote
The homepage tagline says "for React and Solid." That second half is the quiet thesis. TanStack Router has always been framework-agnostic at its core; Start is following. SolidJS support arrived alongside React in the same release train, sharing the same router, the same server function model, the same Vite pipeline.
This is the part Next.js cannot copy, structurally. App Router is React-the-rendering-model all the way down: server components, suspense boundaries, the cache, the streaming protocol - all React internals. Start's server-function-and-typed-router foundation is a thinner abstraction. If a third reactive library shows up in 2027 and somebody writes a renderer for it, Start can adopt it without rewriting itself. That is a hedge against the framework-lock-in problem the React ecosystem has had since hooks.
Whether you ever ship Solid is beside the point. The fact that the framework could means the abstractions are honest.
Who should pick it up this week
If you are starting a new app in May 2026 and any of the following is true, Start is worth a serious read:
- You want type safety to extend into the URL, not stop at the component boundary.
- You have a strong opinion about your hosting provider and do not want the framework to have one too.
- You already use TanStack Query and are tired of duplicating its caching logic against an opaque server cache.
- You are migrating from Vite + React Router and the App Router rewrite has been on the backlog for a year because nobody wants to do it.
If you are running a large App Router codebase that ships features every week, do not migrate. The win is not there yet. But it is worth spending an afternoon with create-tsr-app to see what the alternative shape feels like - because for the first time in a long time, there is an alternative shape, and the next React framework debate will not be settled without it.
