Faz tempo que sabemos deixar um agente escrevendo código que passa nos testes, e até como montar um time de agentes de IA. O que a gente não sabia era fazer ele escrever código que parece rápido. “Deixa essa navegação instantânea” é um requisito difuso: não existe assertion de Jest para “isso aqui tá fluido”. Um agente pode refatorar às cegas, medir no olho e declarar vitória sem que nada tenha melhorado de verdade.
A Vercel acabou de contar como resolveram exatamente isso no v0, a plataforma de geração de apps deles: um agente em loop, armado com um teste determinístico e um Skill cheio de padrões provados, que derrubou os tempos de navegação em produção para perto de zero. E o interessante não é o case de marketing, é a peça técnica que torna o loop possível e que você já pode usar na sua app: o helper instant() que vem no Next.js 16.3.

O problema: apps dinâmicas que “parecem site”
Numa app server-driven com React Server Components, navegar normalmente significa um roundtrip de rede: você clica, nada acontece, o servidor responde, a página aparece. Até agora o Next.js oferecia duas saídas: pré-renderizar estaticamente no build (impossível com dados personalizados por usuário) ou marcar os links com prefetch completo (caro, e com um request de prefetch por link — algo que o próprio time admite no post do Next.js 16.3 que ficava ridículo: vinte chats numa sidebar, vinte requests).
A solução da 16.3, chamada Instant Navigations, copia o truque das SPAs: em vez de prefetch por link, o Next.js faz prefetch de um shell reutilizável por rota, cacheado inteiro no navegador. O shell guarda tudo que pode aparecer sem esperar o servidor: layout, títulos, skeletons. No clique, o shell aparece na hora e o conteúdo dinâmico chega depois por streaming.
Para ativar são duas flags no next.config.ts:
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
cacheComponents: true,
partialPrefetching: true,
};
export default nextConfig;
Com cacheComponents ligado, quando uma rota faz await de dados no servidor você tem três opções — e essa é a parte conceitual que importa:
- Stream com
<Suspense>: o usuário vê o fallback na hora, e o conteúdo entra depois. - Cache com
'use cache': o usuário vê na hora uma UI cacheada de uma execução anterior. - Block: se você prefere que aquela rota espere o servidor (um post de blog que você nunca quer mostrar como skeleton), declara explicitamente com
export const instant = falsena página ou no layout.
Em desenvolvimento, o painel Instant Insights aponta automaticamente quais rotas não estão instantâneas, transformando a navegação lenta num erro visível em vez de uma sensação vaga.
A peça-chave: um teste que prova que é “rápido”
Aqui está o que muda o jogo para os agentes. O Next.js 16.3 inclui um helper para Playwright, instant(), importado de @next/playwright, que pausa a navegação e deixa você verificar quais partes da UI ficam visíveis sem nenhum request de rede:
import { expect, test } from '@playwright/test';
import { instant } from '@next/playwright';
test('navegar para chats é instantâneo', async ({ page }) => {
await page.goto('/');
await instant(page, async () => {
await page.getByRole('link', { name: 'Chats' }).click();
await expect(page.getByTestId('app-title')).toBeVisible();
});
});
Se o conteúdo esperado dependia da rede, o teste falha. Repare no que acabou de acontecer: um requisito qualitativo (“tem que parecer instantâneo”) virou uma verificação binária e determinística. E verificações binárias e determinísticas são exatamente o combustível de que um loop agêntico precisa.
O loop que deixou o v0 instantâneo
O caso prático foi publicado em Making Navigations Instant in v0. O loop é o clássico de agentes bem feitos, com as três coisas que todo fluxo sério com agentes precisa: um objetivo verificável, guardrails com padrões provados —como os que você define em AGENTS.MD—, e feedback real de produção:
- Definir o objetivo como um teste que falha: o agente escreve um teste com
instant()para uma navegação lenta específica (por exemplo, de/para/chats). - Aplicar o fix usando os padrões do Skill: refatorar até o teste passar.
- Repetir se não passar: o teste é a condição de saída do loop.
- Commitar o código E o teste: o teste fica no CI como guarda contra regressões.
O Skill que contém os padrões se instala com:
npx skills add vercel/next.js --skill next-cache-components-optimizer
E depois é só dar ao agente um prompt simples tipo “Make the navigation from ’/’ to ‘/chats’ instant using the next-cache-components-optimizer skill”. Não subestime o papel do Skill: sem ele, o agente improvisa refactors; com ele, o agente aplica receitas verificadas para cada tipo de bloqueio (rotas paralelas, auth gates, o modo de falha do shell vazio, skeletons responsivos).
E como são os fixes? Na maioria dos casos, algo surpreendentemente modesto: descer o acesso a dados dinâmicos para baixo de um boundary de Suspense, para o resto da página entrar no shell:
// antes: o await bloqueia a página inteira
export default async function WorkspacePage() {
const session = await getServerSession();
const team = await fetchTeam(session);
return <TeamSettings team={team} />;
}
// depois: o shell pinta na hora, os dados entram por streaming
export default function WorkspacePage() {
return (
<SettingsPageLayout>
<SettingsHeader title="Workspace" />
<Suspense fallback={<WorkspaceSkeleton />}>
<WorkspaceContent />
</Suspense>
</SettingsPageLayout>
);
}
async function WorkspaceContent() {
const session = await getServerSession();
const team = await fetchTeam(session);
return <TeamSettings team={team} />;
}
Outros casos exigiram refactors maiores, como tirar uma dependência bloqueante do root layout e movê-la para os componentes que realmente a usam. Exatamente o tipo de mudança que mexe em várias features, que um humano adia por meses, e que um loop test-driven ataca sem drama.
O resultado: a home (logada e deslogada), a página de detalhe do chat e todas as subpáginas de settings passaram de bloqueantes para instantâneas, com 16 testes novos impedindo que qualquer mudança futura — humana ou feita por agente — as deixe lentas de novo. Esse último ponto é o que mais me agrada: se os seus agentes vão continuar mexendo no repo, você precisa de verificadores que imponham limites, e “não quebre as navegações instantâneas” acabou de virar um deles.
Como ativar navegações instantâneas no Next.js 16.3
A 16.3 saiu como preview em junho (anúncio oficial) e se instala pela tag preview do npm:
npm install next@preview
Se a sua app ainda não usa Cache Components, existe um segundo Skill, next-cache-components-adoption, que guia o agente pela migração. Os dois estão documentados no guia de AI agents com Next.js e na doc de Instant Navigations.
Minha sugestão de ordem: ative cacheComponents numa branch, veja o que o Instant Insights aponta em desenvolvimento, escreva (ou deixe o agente escrever) um teste com instant() para a sua navegação mais importante, e rode o loop só nela. Não migre metade da app de uma vez: uma navegação verde no CI vale mais que vinte promessas.
A lição de fundo vai além do Next.js. Os frameworks que vão vencer na era dos agentes não serão os que geram mais código, e sim os que exportam verificadores: primitivas que transformam qualidades difusas — velocidade percebida, acessibilidade, UX — em testes determinísticos. É a mesma ideia de transformar capturas de tela em testes com Claude Code e TestSprite; aqui o verificador é o instant() e a qualidade é a velocidade percebida.
Perguntas frequentes
Preciso usar o v0 ou a Vercel para isso?
Não. O helper instant(), as flags e os Skills fazem parte do Next.js open source. O caso do v0 é só a demonstração; o loop funciona em qualquer app Next.js 16.3 com Cache Components.
Isso é a mesma coisa que Partial Prerendering?
Não. O PPR pré-renderiza em build time; aqui o pré-render do shell acontece em runtime, enquanto o usuário navega, e é cacheado no navegador. O próprio time da Vercel faz questão da distinção: conseguir navegações instantâneas dá bem menos trabalho que uma migração para PPR estático.
E se eu quiser que uma rota continue server-bound?
Declare export const instant = false na página ou no layout, e o erro do Instant Insights some. Você decide quais rotas são forçadas a ser instantâneas e quais não.


O que você achou?
Deixe sua opinião, pergunta ou sugestão. Os comentários são sincronizados com GitHub Discussions .