Design de Software Frontend
O SDK te dá as peças. Esta seção ensina a arrumar as peças.
Um app React quebra por motivos previsíveis: o componente que era pequeno virou
um arquivo de 900 linhas, o fetch que era um só virou dezoito espalhados, o
estado que era um useState virou seis fontes de verdade que discordam entre si.
Nada disso é falta de biblioteca — é falta de desenho.
Você não precisa saber tudo antes de começar
Cada página aqui é curta e assume só as anteriores. Comece na primeira, aplique no seu app, volte pra próxima. Nada aqui exige refatorar tudo de uma vez.
O problema, em uma frase
Todo app frontend cresce. O que decide se ele fica agradável ou insuportável é quantas coisas você precisa ter na cabeça pra mudar uma linha.
Design de software é o trabalho de manter esse número baixo. As técnicas são sempre as mesmas três:
- Separar o que muda por motivos diferentes (camadas).
- Limitar o tamanho de cada peça (limites objetivos).
- Deixar o compilador cobrar o que você não quer revisar à mão (tipagem).
As quatro perguntas
Quando você abre um arquivo e não sabe se aquele código deveria estar ali, é sempre uma dessas quatro:
| Pergunta | Onde a resposta mora |
|---|---|
| Em que camada isso vive? | Camadas de um app frontend |
| Em que arquivo/pasta isso vai? | Estrutura de pastas |
| Quem sabe falar com o backend? | Fluxo de dados |
| Onde esse estado deveria morar? | Onde mora cada estado |
E quando o arquivo já existe e você precisa decidir se ele está bom:
| Pergunta | Onde a resposta mora |
|---|---|
| Esse componente está grande demais? | Limites objetivos |
| Como quebro sem virar sopa de props? | Pensando em componentes |
| Como o tipo impede o bug? | Tipagem forte |
| O que eu testo disso? | Estratégia de testes |
O caminho recomendado
flowchart LR
A[Camadas] --> B[Pastas]
B --> C[Fluxo de dados]
C --> D[Estado]
D --> E[Componentes]
E --> F[Limites]
F --> G[Tipagem]
G --> H[Testes]
H --> I[Anti-padrões]
I --> J[Checklist]
Desenho do sistema (as quatro primeiras) responde onde as coisas moram. Escrevendo o código (as três do meio) responde como cada peça é escrita. Sustentando (as três últimas) responde como isso continua verdade em seis meses.
O resumo de tudo, numa tabela
Se você só ler uma coisa desta seção, leia esta tabela. Todo o resto é a justificativa dela.
| Regra | Por quê | Página |
|---|---|---|
Arquivo .tsx de componente: ≤ 150 linhas |
Acima disso ninguém lê o arquivo inteiro antes de editar | Limites |
| Hook customizado: ≤ 100 linhas, uma responsabilidade | Hook grande é serviço disfarçado | Limites |
| Props de um componente: ≤ 7 | Mais que isso é sinal de dois componentes num só | Componentes |
Zero any. unknown na borda, tipo estreito depois |
any desliga o compilador exatamente onde você mais precisa |
Tipagem |
| Toda resposta de rede passa por schema zod | Backend muda sem avisar; a borda é o único lugar de validar | Fluxo de dados |
Componente nunca chama fetch direto |
Amarra UI a transporte e mata o teste | Fluxo de dados |
Dado de servidor vive no TanStack Query, não em useState |
Cache, revalidação e loading de graça, sem sincronizar à mão | Estado |
| Filtro/paginação/aba vivem na URL | Link compartilhável, botão voltar funcionando | Estado |
| Camada de baixo não importa camada de cima | A seta única é o que permite testar e mover código | Camadas |
| Uma pasta por feature, não por tipo de arquivo | Você edita features, não "todos os hooks do app" | Pastas |
Regra não é dogma — é default
Cada limite aqui tem uma saída de emergência documentada na página dele. Passar de 150 linhas num arquivo de tabela com 30 colunas pode ser a escolha certa. O que não é aceitável é passar sem perceber.
Como isso se conecta ao SDK
O tempest-react-sdk já implementa a maior parte da infraestrutura que este
desenho pede. Você não constrói as camadas do zero:
| Camada | O que o SDK já entrega |
|---|---|
| Bootstrap/providers | <AppProviders> — ErrorBoundary → Query → Theme → i18n num bloco |
| Rotas | defineRoutes, <AppRouter>, <RouteGuard> |
| Serviços/HTTP | createApiClient, parseResponse, createDataProvider |
| Estado de servidor | QueryProvider, createQueryKeys, usePaginatedQuery |
| Estado de cliente | createStore, createSelectors |
| Formulários | useZodForm, <FormField> |
| UI | 117 componentes com tokens --tempest-* |
| Ferramenta | tempest doctor / lint / fix |
Recap
- Design existe pra manter baixo o número de coisas na cabeça por mudança.
- Três alavancas: separar por motivo de mudança, limitar tamanho, tipar pra o compilador cobrar.
- A tabela de regras acima é o contrato; cada página explica o porquê e a saída de emergência.
- O SDK já implementa as camadas — seu trabalho é não furar as fronteiras.
Próxima página: Camadas de um app frontend 🚀