Skip to main content

Tipos de rotas | (), [] | Next.js

  • Tipos de rotas | (), [] | Next.js

No Next.js 16, o modelo principal de rotas é o App Router, baseado na pasta app.

A regra principal é:

Uma rota só vira uma página acessível no navegador quando existe um arquivo page.tsx dentro da pasta.

Exemplo:

app/
page.tsx

Cria a rota:

/

Exemplo:

app/
produtos/
page.tsx

Cria a rota:

/produtos

Segundo a documentação oficial, uma página é uma UI renderizada em uma rota específica, criada com um arquivo page dentro do diretório app. (Next.js)


1. Rota estática

É a rota mais simples. O caminho da URL segue diretamente a estrutura das pastas.

Estrutura

app/
sobre/
page.tsx

URL gerada

/sobre

Exemplo

export default function SobrePage() {
return <h1>Sobre</h1>;
}

Use quando a rota tem um caminho fixo, como:

/
/sobre
/contato
/login
/dashboard

2. Rota aninhada

Uma rota aninhada é uma rota dentro de outra rota.

Estrutura

app/
dashboard/
usuarios/
page.tsx

URL gerada

/dashboard/usuarios

Exemplo

export default function UsuariosPage() {
return <h1>Usuários</h1>;
}

Use quando a URL representa hierarquia.

Exemplos:

/dashboard/usuarios
/dashboard/configuracoes
/produtos/categorias
/admin/permissoes

3. Rota dinâmica

Use quando parte da URL muda conforme um dado.

Estrutura

app/
produtos/
[id]/
page.tsx

URL gerada

/produtos/10
/produtos/25
/produtos/abc

O segmento dinâmico é criado usando colchetes, como [id] ou [slug]. (Next.js)

Exemplo

type Props = {
params: Promise<{
id: string;
}>;
};

export default async function ProdutoPage({ params }: Props) {
const { id } = await params;

return <h1>Produto {id}</h1>;
}

Use quando você precisa buscar algo por identificador.

Exemplos:

/produtos/123
/usuarios/42
/pedidos/abc-123
/posts/meu-primeiro-post

4. Rota dinâmica com slug

É uma rota dinâmica mais amigável para SEO.

Estrutura

app/
blog/
[slug]/
page.tsx

URL gerada

/blog/como-usar-nextjs
/blog/introducao-ao-react

Exemplo

type Props = {
params: Promise<{
slug: string;
}>;
};

export default async function BlogPostPage({ params }: Props) {
const { slug } = await params;

return <h1>Post: {slug}</h1>;
}

Use slug quando a URL precisa ser legível.

Bom:

/blog/como-criar-rotas-no-nextjs

Ruim para SEO:

/blog/123

5. Rota catch-all

Use quando você quer capturar vários segmentos da URL.

Estrutura

app/
docs/
[...slug]/
page.tsx

URLs aceitas

/docs/nextjs
/docs/nextjs/rotas
/docs/nextjs/rotas/dinamicas

Exemplo

type Props = {
params: Promise<{
slug: string[];
}>;
};

export default async function DocsPage({ params }: Props) {
const { slug } = await params;

return (
<div>
<h1>Documentação</h1>
<p>Caminho: {slug.join(" / ")}</p>
</div>
);
}

Use quando a profundidade da URL pode variar.

Exemplos:

/docs/backend/dotnet/signalr
/docs/frontend/nextjs/app-router
/categorias/eletronicos/notebooks/gamer

6. Rota catch-all opcional

Parecida com a anterior, mas também aceita a rota base.

Estrutura

app/
docs/
[[...slug]]/
page.tsx

URLs aceitas

/docs
/docs/nextjs
/docs/nextjs/rotas

Exemplo

type Props = {
params: Promise<{
slug?: string[];
}>;
};

export default async function DocsPage({ params }: Props) {
const { slug } = await params;

if (!slug) {
return <h1>Página inicial da documentação</h1>;
}

return <h1>Docs: {slug.join(" / ")}</h1>;
}

Use quando a página principal e as subpáginas podem compartilhar a mesma estrutura.


7. Route Groups

Route Groups servem para organizar o projeto sem alterar a URL.

Você cria uma pasta com parênteses:

(marketing)

Essa pasta não entra na URL. A documentação oficial descreve Route Groups como uma forma de organizar rotas sem afetar a estrutura da URL, além de permitir layouts por grupo. (Next.js)

Estrutura

app/
(site)/
sobre/
page.tsx
(admin)/
dashboard/
page.tsx

URLs geradas

/sobre
/dashboard

Repare que (site) e (admin) não aparecem na URL.

Uso comum

app/
(public)/
layout.tsx
page.tsx
sobre/
page.tsx

(auth)/
login/
page.tsx
cadastro/
page.tsx

(dashboard)/
layout.tsx
dashboard/
page.tsx

Use para separar áreas da aplicação.

Exemplo:

(public)
(auth)
(app)
(admin)
(marketing)

8. Layout por rota

O arquivo layout.tsx permite criar uma estrutura compartilhada entre páginas.

Estrutura

app/
dashboard/
layout.tsx
page.tsx
usuarios/
page.tsx

Exemplo

export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<aside>Menu lateral</aside>
<main>{children}</main>
</div>
);
}

Esse layout será usado em:

/dashboard
/dashboard/usuarios

Use para elementos persistentes:

Header
Sidebar
Menu lateral
Footer
Tabs
Área autenticada

9. Página de loading por rota

O arquivo loading.tsx cria uma UI de carregamento para uma rota.

Estrutura

app/
produtos/
loading.tsx
page.tsx

Exemplo

export default function Loading() {
return <p>Carregando produtos...</p>;
}

No App Router, loading.js envolve page.js, not-found.js e layouts aninhados em um boundary de Suspense. (Next.js)

Use quando a página faz busca de dados e você quer mostrar feedback visual.


10. Página de erro por rota

O arquivo error.tsx trata erros dentro de um segmento de rota.

Estrutura

app/
dashboard/
error.tsx
page.tsx

Exemplo

"use client";

export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<h1>Erro ao carregar dashboard</h1>
<p>{error.message}</p>
<button onClick={reset}>Tentar novamente</button>
</div>
);
}

Ponto importante: error.tsx precisa ser Client Component, por isso usa:

"use client";

Use para tratar falhas específicas de uma área da aplicação.


11. Página 404 por rota

O arquivo not-found.tsx define a UI para quando uma rota ou recurso não for encontrado.

Estrutura

app/
produtos/
[id]/
not-found.tsx
page.tsx

Exemplo

import { notFound } from "next/navigation";

type Props = {
params: Promise<{
id: string;
}>;
};

export default async function ProdutoPage({ params }: Props) {
const { id } = await params;

const produto = null;

if (!produto) {
notFound();
}

return <h1>Produto {id}</h1>;
}
export default function ProdutoNotFound() {
return <h1>Produto não encontrado</h1>;
}

O Next.js possui convenções para not-found.js e global-not-found.js. O not-found.js é usado quando a função notFound é chamada dentro de um segmento de rota. (Next.js)


12. Global Not Found

Use global-not-found.tsx para definir uma página 404 global para rotas não encontradas.

Estrutura

app/
global-not-found.tsx

Exemplo

export default function GlobalNotFound() {
return (
<html>
<body>
<h1>404 - Página não encontrada</h1>
</body>
</html>
);
}

Diferença prática:

ArquivoUso
not-found.tsx404 dentro de um segmento específico
global-not-found.tsx404 global para rotas não correspondidas

13. Route Handlers

Route Handlers servem para criar endpoints HTTP dentro do Next.js.

São o equivalente moderno das antigas API Routes do pages.

A documentação oficial define Route Handlers como manipuladores customizados de request usando as APIs Web Request e Response, disponíveis dentro do diretório app. (Next.js)

Estrutura

app/
api/
produtos/
route.ts

URL gerada

/api/produtos

Exemplo GET

export async function GET() {
return Response.json([
{
id: 1,
nome: "Notebook",
},
]);
}

Exemplo POST

export async function POST(request: Request) {
const body = await request.json();

return Response.json(
{
message: "Produto criado",
data: body,
},
{
status: 201,
}
);
}

Métodos suportados

export async function GET() {}
export async function POST() {}
export async function PUT() {}
export async function PATCH() {}
export async function DELETE() {}
export async function HEAD() {}
export async function OPTIONS() {}

Use para:

/api/login
/api/produtos
/api/pedidos
/api/webhooks/stripe
/api/upload

14. Rota dinâmica em Route Handler

Você também pode criar endpoints dinâmicos.

Estrutura

app/
api/
produtos/
[id]/
route.ts

URL gerada

/api/produtos/10

Exemplo

type Context = {
params: Promise<{
id: string;
}>;
};

export async function GET(
request: Request,
context: Context
) {
const { id } = await context.params;

return Response.json({
id,
nome: "Produto exemplo",
});
}

Use quando o endpoint depende de um identificador.

Exemplos:

GET /api/produtos/10
PUT /api/produtos/10
DELETE /api/produtos/10

15. Rotas paralelas

Parallel Routes permitem renderizar páginas diferentes ao mesmo tempo dentro do mesmo layout.

Você cria slots usando @.

Estrutura

app/
dashboard/
layout.tsx
page.tsx
@analytics/
page.tsx
@team/
page.tsx

Segundo a documentação oficial, Parallel Routes permitem renderizar simultaneamente ou condicionalmente uma ou mais páginas dentro do mesmo layout, sendo úteis para dashboards e feeds dinâmicos. (Next.js)

Exemplo de layout

export default function DashboardLayout({
children,
analytics,
team,
}: {
children: React.ReactNode;
analytics: React.ReactNode;
team: React.ReactNode;
}) {
return (
<div>
<main>{children}</main>

<section>{analytics}</section>

<section>{team}</section>
</div>
);
}

Use quando uma tela tem regiões independentes.

Exemplos:

Dashboard com gráficos + lista de usuários
Feed + modal + sidebar
Tela administrativa com múltiplos painéis

16. Rotas interceptadas

Intercepting Routes servem para carregar uma rota dentro do layout atual, sem trocar totalmente o contexto visual.

São muito usadas para modal com URL.

A documentação oficial diz que rotas interceptadas permitem carregar uma rota de outra parte da aplicação dentro do layout atual, mascarando a URL no navegador. (Next.js)

Exemplo de cenário

Você tem:

/feed
/foto/123

Quando o usuário clica em uma foto dentro do feed, você quer abrir:

/foto/123

Mas visualmente como um modal sobre o feed.

Convenções

ConvençãoSignificado
(.)mesmo nível
(..)um nível acima
(..)(..)dois níveis acima
(...)a partir da raiz do diretório app

Exemplo estrutural

app/
feed/
page.tsx
@modal/
(..)foto/
[id]/
page.tsx

foto/
[id]/
page.tsx

Use quando precisa de:

Modal com URL compartilhável
Preview de item
Abrir detalhe sem perder contexto
Galeria de fotos
Produto em modal dentro de listagem

17. Private Folders

Pastas privadas usam _ no começo do nome.

Elas não viram rota.

Estrutura

app/
dashboard/
_components/
menu.tsx
page.tsx

URL gerada

/dashboard

A pasta _components não vira rota.

Use para organizar arquivos internos da rota:

_components
_lib
_utils
_hooks
_services

Exemplo:

app/
produtos/
_components/
produto-card.tsx
produto-list.tsx
page.tsx

18. Arquivos especiais de rota

No App Router, alguns nomes de arquivos têm significado especial.

ArquivoFunção
page.tsxCria uma página acessível por URL
layout.tsxLayout compartilhado entre rotas
template.tsxSimilar ao layout, mas recria instância em navegações
loading.tsxUI de carregamento
error.tsxUI de erro
not-found.tsxUI de 404 por segmento
global-not-found.tsxUI global de 404
route.tsEndpoint HTTP
default.tsxFallback para Parallel Routes
forbidden.tsxUI para erro 403
unauthorized.tsxUI para erro 401

A documentação oficial lista essas convenções de arquivos dentro do App Router, incluindo page, layout, loading, error, not-found, route, Parallel Routes e Intercepting Routes. (Next.js)


19. Diferença entre page.tsx e route.ts

ArquivoServe paraRetorna
page.tsxCriar telaJSX/React
route.tsCriar endpoint HTTPResponse/JSON/texto

Página

app/produtos/page.tsx
export default function ProdutosPage() {
return <h1>Produtos</h1>;
}

Acessa no navegador:

/produtos

Endpoint

app/api/produtos/route.ts
export async function GET() {
return Response.json([
{
id: 1,
nome: "Notebook",
},
]);
}

Acessa como API:

/api/produtos

20. Organização recomendada

Para um projeto comum com área pública, login e dashboard:

app/
layout.tsx
page.tsx

(public)/
sobre/
page.tsx
contato/
page.tsx

(auth)/
login/
page.tsx
cadastro/
page.tsx

(app)/
dashboard/
layout.tsx
page.tsx

produtos/
page.tsx
[id]/
page.tsx

pedidos/
page.tsx
[id]/
page.tsx

api/
produtos/
route.ts
pedidos/
route.ts

URLs geradas:

/
/sobre
/contato
/login
/cadastro
/dashboard
/produtos
/produtos/123
/pedidos
/pedidos/456
/api/produtos
/api/pedidos

21. Pegadinhas importantes

Pasta sem page.tsx não vira página

Isto não cria rota acessível:

app/
produtos/
components/
produto-card.tsx

Para criar /produtos, precisa:

app/
produtos/
page.tsx

Route Group não entra na URL

app/
(admin)/
dashboard/
page.tsx

URL:

/dashboard

Não é:

/admin/dashboard

route.ts e page.tsx não devem disputar a mesma rota

Evite fazer isso:

app/
produtos/
page.tsx
route.ts

Na prática, se você quer tela, use:

app/produtos/page.tsx

Se você quer endpoint, prefira:

app/api/produtos/route.ts

Dynamic route retorna params

Para:

app/produtos/[id]/page.tsx

Você acessa:

const { id } = await params;

Catch-all retorna array

Para:

app/docs/[...slug]/page.tsx

A URL:

/docs/nextjs/rotas

Gera:

slug = ["nextjs", "rotas"];

22. Resumo rápido

TipoExemplo de pastaURL
Estáticaapp/sobre/page.tsx/sobre
Aninhadaapp/dashboard/users/page.tsx/dashboard/users
Dinâmicaapp/produtos/[id]/page.tsx/produtos/123
Slugapp/blog/[slug]/page.tsx/blog/meu-post
Catch-allapp/docs/[...slug]/page.tsx/docs/a/b/c
Catch-all opcionalapp/docs/[[...slug]]/page.tsx/docs e /docs/a/b
Route Groupapp/(admin)/dashboard/page.tsx/dashboard
Route Handlerapp/api/produtos/route.ts/api/produtos
Parallel Routeapp/dashboard/@analytics/page.tsxSlot interno
Intercepting Routeapp/feed/@modal/(..)foto/[id]/page.tsxModal com URL