Gabriel Malenowitch
15 de março de 2026 · Gabriel Malenowitch

Como arquitetar um front-end complexo de CRM

arquitetura
frontend
react
CRM
organização
boas práticas
desenvolvimento

Como arquitetar um front-end complexo de CRM

Essa é minha experiência depois de 4 anos trabalhando em um CRM complexo em uma empresa grande, mais freelancer, projetos pessoais e desenvolvimento de SaaS. Minha maior experiência é em React, então vamos focar nisso.

Lembre-se: todo sistema é diferente. Adapte o que fizer sentido para o seu contexto — crie subpastas onde precisar, ignore o que não se aplicar.


A estrutura

src/
├── app.tsx
├── pages/
├── components/
│   ├── core/
│   └── shared/
├── hooks/
│   ├── core/
│   └── shared/
├── api/
├── models/
└── utils/

app.tsx

Entrada da aplicação. É aqui que ficam os providers globais: tema, idioma, autenticação, rotas, permissionamento granular, e afins.


components/ e hooks/

Ambos seguem a mesma lógica de separação:

PastaO que vai aqui
core/Sem regra de negócio — usados em qualquer contexto
shared/Com regra de negócio — compartilháveis entre telas

Por que separar core de shared? Core tende a ser usado dezenas de vezes mais do que shared. Separar facilita manutenção e organização.

Autenticação não tem regra de negócio?

Autenticação é uma funcionalidade usada em todas as páginas — a empresa inteira segue a mesma lógica. Quando uma regra é global e não varia por página ou área, ela pode ser tratada como core.

Mas certamente existem exceções. Não existe receita de bolo — pense bem no tipo de aplicação que você está criando. E lembre-se do equilíbrio entre KISS, YAGNI e DRY.


pages/

Cada pasta dentro de pages/ representa uma página, não uma funcionalidade. Componentes, hooks e providers específicos de uma página ficam dentro da pasta daquela página — não em components/ ou hooks/.

E se eu precisar compartilhar uma página?

Aí vale criar um componente em shared/. Se a página for grande demais, divida em componentes e mova para shared/.


api/

Camada de comunicação com o backend. Vale usar uma lib de query como React Query ou RTK Query. Cada arquivo representa uma API ou serviço, organizado da forma que fizer mais sentido dado o backend.

Regra de negócio não costuma ter lugar aqui.


models/

Tipagens e modelos da aplicação. A organização depende de como você estruturou api/ e pages/ — e isso varia bastante de projeto para projeto.


utils/

Funções utilitárias, com ou sem regra de negócio. Geralmente não precisa separar — mas separe se necessário (KISS & YAGNI).


Regras de dependência

Evite dependência circular ao máximo. Implemente lint para garantir isso, se possível.

core        → não importa de shared
core        → importa de api apenas em casos muito específicos
              (ex: feature flags, autenticação)
shared      → importa de core
pages       → importa de qualquer lugar, e não exporta pra lugar nenhum
api         → importa de models
models      → NÃO importa de api
utils sem regra de negócio  → pode ser importado por qualquer lugar
utils com regra de negócio  → qualquer lugar, exceto core

Comentários