Mateus Cavalcanti13 de set. de 20263 minArquitetura
App RouterArquiteturaNext.jsReactServer Actions

Como estruturar projetos Next.js escaláveis com App Router

A estrutura de um projeto Next.js com App Router precisa favorecer dois pilares fundamentais: clareza e previsibilidade para o time e capacidade de evolução sustentável.

O modelo de App Router é orientado a rotas, layouts compartilhados e componentes de servidor por padrão (React Server Components). Compreender como desenhar limites de arquitetura limpos é o que separa uma aplicação rápida e fácil de manter de um projeto com acoplamento e re-renderizações desnecessárias.

Estrutura base recomendada

Adotar uma estrutura limpa na raiz da aplicação facilita a navegação e a separação de responsabilidades:

src/
  app/
    (site)/
      layout.tsx
      page.tsx
      blog/
        page.tsx
        [slug]/
          page.tsx
    api/
  components/
    ui/
    common/
  features/       # ou módulos de domínio (ex: auth, blog, checkout)
    blog/
      actions/
      components/
      hooks/
      schemas/
  lib/
    db/
    services/
    utils/

Diretrizes práticas de arquitetura

  1. Rotas em app/ apenas para composição: Evite colocar regras de negócio pesadas dentro dos arquivos page.tsx. Use as páginas para coordenar data fetching e injetar props nos componentes.
  2. Server Components por padrão: Não adicione "use client" a menos que precise de hooks de estado local (useState, useReducer), efeitos (useEffect), ouvintes de eventos do DOM ou bibliotecas que dependem do navegador.
  3. Mantenha os limites de cliente nas folhas da árvore: Em vez de marcar uma página inteira como Client Component, isole apenas o botão ou widget interativo.
  4. Centralize conexões de infraestrutura em lib/: Clientes de banco (como Prisma ou Drizzle), serviços de email e APIs de terceiros devem residir fora do escopo de rotas.

Server Actions e Mutações de Dados

Com Server Actions, mutações de dados acontecem diretamente no servidor, eliminando a necessidade de criar endpoints de API avulsos apenas para receber formulários. No entanto, segurança e validação são inegociáveis:

"use server";

import { z } from "zod";
import { revalidatePath } from "next/cache";

const CreateCommentSchema = z.object({
  postId: z.string().uuid(),
  author: z.string().min(2).max(50),
  content: z.string().min(5).max(1000),
});

export async function addCommentAction(formData: FormData) {
  const parsed = CreateCommentSchema.safeParse({
    postId: formData.get("postId"),
    author: formData.get("author"),
    content: formData.get("content"),
  });

  if (!parsed.success) {
    return { success: false, errors: parsed.error.flatten().fieldErrors };
  }

  // Execução no banco de dados com segurança
  await db.comment.create({ data: parsed.data });

  revalidatePath(`/blog/${parsed.data.postId}`);
  return { success: true };
}

Checklist para manter o projeto saudável

  • Consistência de nomenclatura: Mantenha convenções bem documentadas para pastas e arquivos.
  • Evite vazar segredos: Utilize pacotes como server-only para garantir que módulos com chaves de API nunca sejam importados por componentes de cliente acidentalmente.
  • Tipagem estrita: Compartilhe schemas (Zod) entre o backend/actions e os formulários no cliente.

Uma boa arquitetura não é a que usa o maior número de abstrações, mas a que permite que qualquer desenvolvedor encontre o que precisa e entregue código confiável com facilidade.

Busca Global e Comandos

Navegue por artigos, projetos, certificações ou execute comandos rápidos.