Skip to content
← Voltar para o Skalablog

Artigo publicado

TanStack Start: 6 diferenças em relação ao Next.js

48% dos watchers de um vídeo sobre frameworks React não são inscritos, mas o tema rendeu: o TanStack Start chamou atenção de quem vinha do Next.js. O framework, criado por Tanner Linsley, aposta em uma premissa simples: tudo o que uma rota precisa — dados, parâmetros e busca — vive em um único lugar, tipado de ponta a ponta.

O que é o TanStack Start e a quem ele se destina

O TanStack Start é um framework full-stack para React criado por Tanner Linsley, o mesmo autor do TanStack Query. Ele roda sobre o TanStack Router e o Vite, e se posiciona como uma alternativa ao Next.js para quem quer SSR, data fetching e tipagem de ponta a ponta sem trocar de modelo mental a cada versão.

Este artigo é um overview, não um curso. O conteúdo acompanha o raciocínio de quem já conhece o Next.js e quer entender, em uma leitura, como o TanStack Start organiza rotas, dados, cache e deploy. Se você quer se aprofundar em frameworks modernos, o Bootcamp do Dev Doido e o Crazystack Typescript, disponíveis em Crazystack, são caminhos de estudo complementares citados pela comunidade brasileira — inclusive por quem acompanha criadores como Gustavo Dev Doido.

A premissa central do framework é a explicitação: tudo o que uma rota precisa — loader, autenticação, search params, pré-renderização — fica declarado dentro da definição da rota. Isso elimina o efeito de espalhar configuração por arquivos soltos, algo que desenvolvedores que mantêm projetos grandes no Next.js costumam sentir na prática.

Como funciona o roteamento baseado em arquivos com createFileRoute

Você cria uma rota de duas formas no TanStack Start. A primeira é criar um arquivo dentro de src/routes, por exemplo about.tsx, e exportar uma constante que chama createFileRoute, importada do pacote do framework. Você passa o caminho da página, como /about, e um objeto com o componente.

A segunda forma é a rota dinâmica. Para uma página de detalhe, você cria o arquivo todos/$todoId.tsx. O segmento $todoId define o parâmetro, e dentro do componente você acessa o valor com a opção params da própria rota. O valor chega tipado como string: se você passar um número no link, o TypeScript acusa erro antes do build.

Depois de criar ou renomear rotas, você roda o comando de desenvolvimento (por exemplo, pnpm run dev). Nesse momento o TanStack Start gera automaticamente o routeTree, um arquivo com todas as rotas da aplicação e seus tipos. É esse arquivo gerado que alimenta a navegação tipada descrita na próxima seção.

Essa geração automática é a base do contrato de tipagem do framework. Sem ela, o autocomplete de rotas não existe; com ela, toda a aplicação compartilha um mapa único de caminhos conhecidos pelo compilador.

Para navegar, você importa o componente Link do TanStack Router e usa a propriedade to. O autocomplete oferece todas as rotas geradas no routeTree, inclusive rotas dinâmicas. Ao navegar para /todos/$todoId, você precisa passar o objeto params, e o campo todoId aparece tipado.

O mesmo vale para o useNavigate, útil quando a navegação acontece em código e não em um clique de link. Passar um valor de tipo errado em qualquer um desses pontos gera erro de TypeScript imediatamente, o que reduz uma classe inteira de bugs de rota quebrada que só aparecem em runtime em outros stacks.

Essa tipagem de navegação é um dos pontos que o autor do vídeo sentiu falta no Next.js. Lá, caminhos de Link e objetos de params dependem de convenções e testes manuais; aqui, o compilador garante a consistência entre a declaração da rota e todos os pontos que a referenciam.

Renderização e hydration: a diferença em relação ao Next.js

No primeiro acesso, o servidor renderiza o componente e envia o HTML ao cliente sem interatividade. Depois, o processo de hydration adiciona event listeners e torna a página interativa — o mesmo fluxo que você conhece do Next.js.

A diferença importante é que não existe a divisão entre client components e server components. Todos os componentes podem ter interatividade por padrão: um useState funciona em qualquer arquivo de rota sem erro e sem diretivas. Se você vem do Next.js, essa é provavelmente a maior mudança de modelo mental.

A segunda diferença está na navegação subsequente. Depois do primeiro carregamento, as trocas de página acontecem no cliente, como em uma SPA tradicional. Na prática: primeiro acesso vem do servidor com hydration; navegações seguintes são client-side. Isso explica por que o loader de uma rota roda em ambientes diferentes dependendo do momento, como você verá a seguir.

Loaders, beforeLoad e getRouteApi na definição da rota

O createFileRoute aceita um loader assíncrono, que pode chamar uma API ou buscar dados. O que o loader retorna fica disponível no componente por meio de route.useLoader, já com tipo inferido: se o loader devolve um objeto com message, o componente enxerga data.message tipado.

Uma regra prática acompanha esse loader: ele roda tanto no servidor quanto no cliente. No primeiro acesso ele executa no servidor; em navegações seguintes, executa no cliente. Por isso você não pode chamar o banco de dados diretamente dentro dele — o código precisa funcionar nos dois ambientes. Acesso a banco deve ficar atrás de uma API ou de server functions.

Para autenticação, existe o beforeLoad, que executa antes do loader. Ali você verifica se o usuário está autenticado e, se não estiver, redireciona para outra página. Como tudo fica declarado na rota, fica simples revisar quem pode acessar o quê.

Componentes filhos também conseguem os dados do loader. Em um componente Message qualquer da árvore, você chama getRouteApi passando a rota (por exemplo, /about) e usa routeApi.useLoader(). A requisição não é repetida: o mesmo dado circula pela árvore de componentes sem prop drilling e sem refetch.

validateSearch e a integração com TanStack Query

No ecossistema Next.js, muita gente usa o nuqs, biblioteca de search params para guardar estado na URL — filtros de tabela, modal aberto, paginação. No TanStack Start você não precisa de uma biblioteca extra: o método validateSearch tipa os search params da URL, normalmente com um schema do Zod.

Com o schema declarado, você lê os parâmetros com route.useSearch e recebe tudo tipado. Um parâmetro como ?creating=1 chega convertido para boolean, porque o Zod declarou o tipo. Se você passar o valor errado em código, o TypeScript acusa. Isso cobre o caso clássico de URL state: recarregar a página e manter o filtro, ou compartilhar um link que abre o modal já aberto.

A integração com o TanStack Query é o outro destaque. Dentro do loader, você chama ensureQuery passando a query que já usaria no useQuery. O QueryClient é compartilhado entre servidor e cliente: o servidor começa a buscar a query durante a renderização e vai transmitindo (streaming) os dados ao cliente, reduzindo o tempo de loading e evitando o flash de interface vazia. No componente, você consome o resultado com useSuspenseQuery passando a mesma query.

O cache também é explícito. Para pré-renderizar uma página — o equivalente ao static site generation — você declara um prerender com as rotas desejadas. Para cache HTTP, você define headers de cache-control na rota, o que também permite um comportamento semelhante ao ISR do Next.js. Tudo fica visível na definição da rota, em vez de implícito em convenções.

Deploy do TanStack Start: adapters para qualquer nuvem

O TanStack Start é enfático em um ponto: você pode fazer deploy em qualquer lugar. O projeto usa o Nitro como camada de deployment, e cada provedor tem um adapter mantido pelo próprio framework. Isso reduz o risco de ficar preso a uma única plataforma — uma preocupação comum entre quem avalia o Next.js e a Vercel.

As opções citadas incluem:

Na prática, o fluxo típico de deploy segue três passos: você escolhe o adapter do provedor no arquivo de configuração do Vite; roda o build do projeto; e aponta o serviço de hospedagem para o output gerado. Em plataformas como Vercel e Netlify, o build detecta o framework e o processo fica quase automático. Na comparação direta com o Next.js, a diferença está na filosofia: em vez de uma plataforma oficial preferencial, o TanStack Start mantém adapters equivalentes para vários provedores.

Vale uma nota de escopo: desempenho e suporte variam por provedor e por recurso. O que o framework garante é o caminho de build e deploy; SLAs, limites de runtime e preços são de cada plataforma.

TanStack Start ou Next.js: resumo comparativo

A tabela abaixo resume as diferenças que mais afetam a decisão de quem já trabalha com Next.js:

DimensãoTanStack StartNext.js
ComponentesTodos interativos por padrão, sem server componentsDivisão entre client e server components
Tipagem de rotasAutocomplete e validação completa via routeTree geradoTipagem parcial, depende de convenções
Search paramsvalidateSearch nativo com schemas do ZodRequer biblioteca externa como nuqs
Cache de dadosQueryClient compartilhado entre servidor e cliente via TanStack QuerySoluções próprias ou bibliotecas da comunidade
DeployAdapters do Nitro para múltiplos provedoresIntegração mais profunda com a Vercel
BaseTanStack Router + ViteFramework próprio com compilador dedicado

Não há veredito único. Se sua equipe já domina server components e depende de recursos específicos do Next.js, a migração precisa de justificativa forte. Se você valoriza tipagem explícita, cache previsível e liberdade de hospedagem, o TanStack Start merece um projeto piloto.

FAQ

  • O TanStack Start substitui o Next.js? Ele é uma alternativa madura para aplicações React full-stack, mas não uma substituição automática. Times que dependem de server components, image optimization e do ecossistema Vercel tendem a permanecer no Next.js; projetos que priorizam tipagem e portabilidade de deploy se beneficiam do TanStack Start.
  • O loader roda no servidor ou no cliente? Nos dois. No primeiro acesso à página ele executa no servidor; em navegações seguintes, roda no cliente, porque a navegação é client-side. Por isso o loader não deve acessar o banco de dados diretamente.
  • Preciso de uma biblioteca de search params no TanStack Start? Não. O método validateSearch, combinado com um schema do Zod, tipa os parâmetros da URL e fornece leitura tipada via route.useSearch.
  • Em quais provedores eu posso fazer deploy? O framework usa adapters do Nitro mantidos pelo próprio projeto, com suporte para Vercel, Netlify, Cloudflare Workers, Firebase, AWS e outros provedores.
  • Como o TanStack Start se integra ao TanStack Query? Você chama ensureQuery no loader, e o QueryClient é compartilhado entre servidor e cliente. O servidor inicia o fetch e faz streaming dos dados; no componente, você consome com useSuspenseQuery.

Do vídeo ao artigo escrito

Este overview mostrou como o TanStack Start concentra rota, dados e cache em um único ponto tipado da aplicação. Se você produziu um vídeo com esse tipo de explicação — comparativos de frameworks, walkthroughs de código, decisões de arquitetura —, esse conhecimento merece existir também em texto, onde mecanismos de busca e leitores podem encontrá-lo.

O Skala Blog resolve exatamente isso: você cola a URL do vídeo do YouTube, ele transcreve o conteúdo e gera um artigo estruturado e pronto para revisão. O fluxo é simples — vídeo, transcrição, artigo — e preserva a sequência de raciocínio que já funcionou na versão falada.

Source video

YouTube thumbnail: Esse framework me surpreendeu muito (e você também vai gostar!)

Source video

Esse framework me surpreendeu muito (e você também vai gostar!)

Create from this video

This article was created automatically from a new video.

Automate my channel

Turn your YouTube videos into articles

Built for creators with a backlog and no editor on staff. This page started as a video — Skalablog drafts from the transcript, you review every word, then publish on a first-party /p/{slug} page. Nothing goes live until you publish it.

Turn your videos into articles

Published with Skalablog