Skip to content
Dashboard

TanStack Start: A route-first full-stack React framework

Copy link to headingBuild full-stack React with TanStack Start

Copy link to headingRoutes define your app's shape

Copy link to headingSetup stays close to the build tool

src/
router.tsx
routeTree.gen.ts
routes/
__root.tsx
index.tsx
posts/
$postId.tsx

Copy link to headingFile routes carry types

src/routes/products/$productId.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/products/$productId')({
component: ProductPage,
})
function ProductPage() {
const { productId } = Route.useParams()
return <ProductDetail productId={productId} />
}

src/routes/orders.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
const orderSearch = z.object({
status: z.enum(['open', 'closed', 'all']).default('open'),
page: z.number().int().min(1).default(1),
sort: z.enum(['newest', 'oldest']).default('newest'),
})
export const Route = createFileRoute('/orders')({
validateSearch: orderSearch,
component: OrdersPage,
})
function OrdersPage() {
const search = Route.useSearch()
return <OrdersTable filters={search} />
}

Copy link to headingLoaders make data explicit

src/routes/orders.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
const orderSearch = z.object({
status: z.enum(['open', 'closed', 'all']).default('open'),
page: z.number().int().min(1).default(1),
})
export const Route = createFileRoute('/orders')({
validateSearch: orderSearch,
loaderDeps: ({ search }) => ({
status: search.status,
page: search.page,
}),
loader: ({ deps, abortController }) =>
fetchOrders(deps, { signal: abortController.signal }),
component: OrdersPage,
})
function OrdersPage() {
const orders = Route.useLoaderData()
return <OrdersTable orders={orders} />
}

Copy link to headingServer functions are explicit

src/server/orders.ts
import { createServerFn } from '@tanstack/react-start'
import { z } from 'zod'
const input = z.object({
status: z.enum(['open', 'closed', 'all']),
page: z.number().int().min(1),
})
export const getOrders = createServerFn({ method: 'GET' })
.validator(input)
.handler(async ({ data }) => {
return fetchOrdersFromDatabase(data)
})

Copy link to headingSSR streams the document

Copy link to headingDeferred hydration controls startup work

import { Hydrate } from '@tanstack/react-start'
import { visible } from '@tanstack/react-start/hydration'
export function ProductPage() {
return (
<Hydrate when={visible({ rootMargin: '400px' })}>
<Reviews />
</Hydrate>
)
}

Copy link to headingVercel deploys Start directly

Copy link to headingA framework comparison

Copy link to headingWhen TanStack Start is the right choice for your application

Copy link to headingFAQ

Copy link to headingWhat is TanStack Start?

Copy link to headingHow is TanStack Start different from Next.js App Router?

Copy link to headingCan TanStack Start deploy to Vercel?

Ready to deploy?