Frontend cresceu. O que antes cabia em alguns arquivos HTML e um jQuery no final da página virou aplicações com centenas de componentes, gerenciamento de estado complexo, múltiplos ambientes e times inteiros dedicados só ao cliente.
Uma aplicação React com 50 componentes e 3 desenvolvedores não tem os mesmos problemas que uma com 500 componentes e 30 devs. Quando o projeto é pequeno, qualquer organização funciona — e é exatamente por isso que tantos times chegam num ponto de inflexão sem ter percebido o crescimento acontecendo. Arquitetura é a resposta para esse crescimento: o conjunto de decisões conscientes sobre como organizar um sistema para que ele escale junto com o time.
O que arquitetura frontend resolve
Arquitetura não é um tema abstrato reservado para projetos grandes. Ela resolve problemas concretos que você já encontrou ou vai encontrar.
Saber onde cada coisa deve ficar sem precisar perguntar para ninguém. Um novo componente de formulário vai onde? A chamada de API fica no componente ou num hook? Com arquitetura definida, a resposta é óbvia.
Adicionar features sem quebrar o que já existe. Quando o código está bem estruturado, uma nova funcionalidade tem um lugar natural para morar — e não exige refatorar metade do projeto para caber.
Entender código escrito há 6 meses, por você ou por outra pessoa. Um código bem arquitetado comunica intenção. Um código sem estrutura força o leitor a reconstruir o raciocínio do autor do zero.
Novos devs produtivos mais rápido. Quando a arquitetura é consistente, um desenvolvedor novo aprende o padrão uma vez e consegue navegar qualquer parte do projeto com autonomia.
O problema real: acoplamento
A maioria dos problemas de arquitetura frontend tem um nome: acoplamento. Quando partes do código que mudam por razões diferentes estão juntas, qualquer mudança vira um risco.
Pense num componente assim:
function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
// processa os dados, normaliza, filtra...
const normalized = normalizeUser(data);
setUser(normalized);
// atualiza estado global também
userStore.set(normalized);
});
}, [userId]);
return <div className="...">{/* renderiza tudo */}</div>;
}Esse componente faz quatro coisas ao mesmo tempo: busca dados, processa dados, controla estado global e renderiza UI. Cada uma dessas responsabilidades muda por razões diferentes — e estão todas no mesmo lugar.
Quando o endpoint muda, você mexe no componente. Quando a lógica de normalização muda, você mexe no componente. Quando o design muda, você mexe no componente. Quando o estado global muda, você mexe no componente. Esse é o sinal mais claro de arquitetura ruim: a mesma unidade de código tem múltiplos motivos para mudar.
A solução não é escrever mais código — é separar o que pertence em lugares diferentes.
As camadas de decisão arquitetural
Decisões de arquitetura acontecem em diferentes granularidades. Entender em qual nível você está operando ajuda a tomar a decisão certa.
- Nível micro: o componente
Como você organiza um único componente. Separação entre apresentação e lógica, onde o estado vive, quais responsabilidades o componente tem. É o nível mais granular e mais frequente.
- Nível meso: a feature
Como você organiza uma funcionalidade completa. Colocation (manter arquivos relacionados juntos), módulos, boundaries entre features. Uma feature de "autenticação" deve ser autocontida ou espalhada pelo projeto?
- Nível macro: o projeto
Como o projeto inteiro está estruturado. Monorepo ou múltiplos repositórios? Feature-first (organizado por domínio) ou layer-first (organizado por tipo de arquivo)? Essas decisões afetam como times inteiros trabalham em paralelo.
- Nível sistema: a integração
Como o frontend se comunica com o backend e outros serviços. REST, GraphQL, BFF (Backend for Frontend)? Onde fica a camada de tradução entre a API e o modelo de dados do frontend? Esse nível tem impacto direto em performance e experiência do usuário.
Uma startup com 2 desenvolvedores não precisa da mesma arquitetura que uma empresa com 200. O custo de arquitetura prematura é real: abstrações que ninguém usa, convenções que ninguém segue, complexidade que não resolve nenhum problema atual. Comece com a arquitetura mais simples que funciona — e evolua quando a dor aparecer, não antes.
O que este blog cobre
Este artigo é a introdução de uma série sobre arquitetura frontend. Os próximos artigos entram em tópicos específicos:
- Arquitetura CSS — BEM, ACSS, ITCSS e como cada metodologia resolve o problema de escalar estilos em projetos grandes
- Arquitetura de componentes — Separação de responsabilidades, composição e como construir componentes que são fáceis de testar e reutilizar
- Gerenciamento de estado — Quando usar estado local, contexto, estado global e como evitar o caos de estado distribuído
- Design Systems — Como criar uma camada de UI consistente que escala com múltiplos times e produtos
Resumo
Não é sobre usar o framework certo — é sobre tomar decisões conscientes sobre como o código se organiza para que ele escale junto com o time.
Separe o que muda por razões diferentes. Um componente que tem múltiplos motivos para ser modificado é um componente com responsabilidades demais.
Arquitetura prematura tem custo. Adote a estrutura mais simples que funciona hoje — e adicione complexidade quando a dor aparecer de verdade.
As minhas notas
Selecione um trecho e use Destacar no menu (somente neste aparelho).