react · migration
Porting a Next.js Portfolio to TanStack Start
A field guide from the migration — what mapped one-to-one, what changed shape, and what disappeared entirely.
Moving from Next.js App Router to TanStack Start turned out to be mostly mechanical. Here's the mapping table I wish I had before starting.
Concept mapping
| Next.js | TanStack Start |
|---|---|
app/layout.tsx | __root.tsx shellComponent |
app/page.tsx | routes/index.tsx |
| Server Components fetching DB | route loaders + createServerFn |
NEXT_PUBLIC_* env vars | import.meta.env.VITE_* |
next/font/google | @fontsource/* packages |
next/image | plain <img> + CSS |
Things that got simpler
Routing. File-based routing exists in both, but TanStack Router generates a fully typed tree. Links like <Link to="/blog/$slug" params={{ slug }}> are compile-checked.
Hash scrolling. The old site hand-rolled smooth scrolling between sections. TanStack Router has it built in:
createTanStackRouter({
hashScrollIntoView: true,
})
Things that needed care
"use client"directives vanish — components render on both server and client by default- Canvas/rAF code must live inside effects (it already did)
useId()output contains colons — sanitize before using inurl(#id)references for SVG clipPaths
Verdict
Same visual site, fewer abstractions, faster dev server under Bun. The main win isn't performance though — it's that the framework stays out of the way.