Engineering

Why we chose TanStack Start over Next.js

The unglamorous engineering decision that shaped every subsequent product decision — and why we would make it again.

Marek Novák · Engineering LeadMarch 18, 2026 8 min read
Share Post LinkedIn
Why we chose TanStack Start over Next.js

Framework choice is the least interesting decision a startup makes and one of the most consequential. It shapes hiring, deployment, cost, and speed of iteration for years. When we started nctools we spent three weeks prototyping in Next.js, Remix, and TanStack Start. We picked TanStack Start. Here is why.

The requirement

nctools needed three things from a framework: fast page-load, strong routing primitives (nested routes, loaders, type-safe params), and an escape hatch for the moments when server-side rendering fights us.

All three frameworks meet those requirements. Next.js does so with the largest ecosystem, Remix with the tightest data-loading story, TanStack Start with the most flexible primitives. In prototyping, TanStack Start consistently produced the smallest bundle and the fastest development loop.

The escape hatch

Our tools ship large browser-only dependencies — pdfjs-dist, tesseract.js WebAssembly, docx, xlsx. None of those work under SSR. In Next.js this requires dynamic({ ssr: false }) wrappers everywhere. In TanStack Start, ClientOnly is a single component and the rest of the code stays plain. That difference is not a deal-breaker on its own, but it removes an entire category of production bugs.

File-based routing without the surprises

TanStack Router's file-based routing is deliberate. Dots in filenames map to slashes in URLs. Underscores mark layouts. Dollar signs mark params. No magic; nothing behaves unexpectedly. Coming from Next.js's App Router (which layers several conventions on top of each other), the clarity is refreshing.

// src/routes/tools.pdf-to-word.tsx
export const Route = createFileRoute("/tools/pdf-to-word")({
  component: PdfToWord,
});

Loader-first data

Every route can define a loader that runs before render. Combine it with TanStack Query and you get server-rendered, client-hydrated, cache-consistent data with no useEffect boilerplate. The pattern encourages you to think about data flow upfront instead of hacking it in later.

Bundle size

On our production build, the client entry is 68 KB gzipped for the shared framework code. Each route adds 4-15 KB on average. A comparable Next.js App Router build was 92 KB shared. Not a landslide, but noticeable in latency-sensitive markets.

What we gave up

A smaller ecosystem. Some Next.js patterns (parallel routes, intercepting routes) do not have exact equivalents. Some vendors ship 'Next.js' plugins with no TanStack equivalent. We have not missed anything essential in six months.

Would we choose it again?

Yes. If your product is largely CRUD-with-forms, Next.js will still be a fine choice and has more hires. If your product is any flavour of interactive tooling — dashboards, editors, browser-side compute — TanStack Start's flexibility pays dividends every week.

MN

Marek Novák

Engineering Lead at nctools