ui
Frontend
React, Next.js, TypeScript, Tailwind y patrones de componentización.
Visão geral do ecossistema
core
React 19
Server Components, use() hook, Actions, melhorias de performance e novo compilador.
framework
Next.js 15
App Router estável, Turbopack, PPR (Partial Prerendering), React 19 suporte nativo.
lang
TypeScript
Tipagem estática, interfaces, generics, type inference. Padrão para projetos sérios.
styles
Tailwind CSS
Utility-first CSS framework. Design tokens, responsividade, dark mode sem CSS customizado.
state
Zustand / Jotai
Estado global simples e performático. Alternativas leves ao Redux para projetos modernos.
data
TanStack Query
Data fetching, cache, sync e servidor state management. Elimina boilerplate de useEffect+fetch.
App Router vs Pages Router
O App Router (Next.js 13+) é o modelo atual e recomendado. Pages Router ainda funciona mas está em modo de manutenção.
- App Router usa React Server Components por padrão
- Layouts aninhados, loading.tsx, error.tsx nativos
- generateStaticParams para exportação estática
- generateMetadata para SEO por rota
Estrutura App Router
app/
layout.tsx ← layout raiz
page.tsx ← rota /
[locale]/
layout.tsx ← layout do locale (html lang, providers)
page.tsx ← rota /[locale]
dashboard/
layout.tsx ← layout aninhado
page.tsx ← rota /[locale]/dashboard
loading.tsx ← fallback de Suspense automático
error.tsx ← Error Boundary automático
not-found.tsx ← 404 da rotaℹ️ Info
Server Components são renderizados no servidor e não têm acesso a hooks, eventos ou browser APIs. Para essas features, adicione
"use client" no topo do componente.Padrões de componentização
Hierarquia de componentes
- Pages : recebem params/searchParams, orquestram layout e fetch de dados
- Layouts : estrutura persistente entre navegações
- Feature Components : encapsulam lógica de domínio
- UI Components : puros, reutilizáveis, sem estado de aplicação
- Hooks : lógica stateful reutilizável
Exemplo de componente UI puro
// src/components/ui/Badge.tsx
type BadgeVariant = "default" | "success" | "warning" | "danger";
const variantClasses: Record<BadgeVariant, string> = {
default: "bg-slate-800 text-slate-300 border-slate-700",
success: "bg-green-950 text-green-400 border-green-800",
warning: "bg-yellow-950 text-yellow-400 border-yellow-800",
danger: "bg-red-950 text-red-400 border-red-800",
};
type BadgeProps = {
children: React.ReactNode;
variant?: BadgeVariant;
};
export function Badge({ children, variant = "default" }: BadgeProps) {
return (
<span className={`inline-flex items-center text-xs font-medium px-2 py-0.5 rounded border ${variantClasses[variant]}`}>
{children}
</span>
);
}