Como estruturar um projeto Next.js escalável com App Router

February 10, 2026 (3mo ago)

Problema

Times crescem, rotas multiplicam-se e o App Router facilita colocar tudo em app/ sem critério. O resultado comum é: lógica de negócio misturada a UI, fetch duplicado, componentes client gigantes e imports circulares. Em produção isso vira débito técnico rápido.

Solução

Tratar app/ como camada de composição (rotas, layouts, loading e error boundaries) e extrair regras para módulos estáveis: features/, lib/, server/, components/. Definir regras explícitas: o que é Server Component por padrão, onde use client é permitido e como acessar dados (Server Actions, route handlers, serviços).

Arquitetura

app/
  (marketing)/...
  (dashboard)/...
  api/...
features/
  billing/
    ui/
    actions.ts
    service.ts
lib/
  db.ts
  env.ts
components/
  ui/   # primitivos reutilizáveis

Código

// features/orders/service.ts — sem "use client"
import { db } from "@/lib/db";
 
export async function listOrdersForUser(userId: string) {
  return db.order.findMany({ where: { userId }, take: 50 });
}
// app/(app)/orders/page.tsx — Server Component
import { listOrdersForUser } from "@/features/orders/service";
import { OrderTable } from "@/features/orders/ui/order-table";
 
export default async function OrdersPage() {
  const userId = "..."; // sessão / claims
  const orders = await listOrdersForUser(userId);
  return <OrderTable initial={orders} />;
}

Performance

Server Components por padrão reduzem JS no bundle. Segmentar dados por rota evita waterfalls: cada layout busca só o necessário. Use React.cache para deduplicar leituras no mesmo request tree quando vários componentes precisam do mesmo recurso.

Melhorias futuras

Camada de contratos (Zod/OpenAPI) compartilhada entre actions e clients; feature flags por ambiente; testes de integração em rotas críticas com Playwright.

Conclusão

Escalabilidade no App Router é menos sobre pastas “bonitas” e mais sobre fronteiras claras entre roteamento, UI e domínio. Quem revisa seu repositório precisa enxergar decisões — não só arquivos.