Tech Talks
Aqui eu compartilho o que aprendi durante minha jornada como desenvolvedor full-stack. Este é meu espaço para discutir boas práticas reais, padrões de design que realmente funcionam, organização de projetos e tudo que considero essencial para escrever código de qualidade. Meu objetivo é ser prático e honesto: trazer soluções que eu uso no dia a dia e que fizeram diferença na minha carreira. Se você quer aprimorar suas skills e entender melhor as decisões por trás do bom desenvolvimento, você está no lugar certo.
Content Security Policy (CSP) no Frontend
O que é CSP e como funciona
CSP (Content Security Policy) é uma camada de segurança no browser que define de quais origens o frontend pode carregar scripts, estilos, imagens, fontes, iframes e conexões.
Ela é enviada normalmente via header HTTP Content-Security-Policy. Ao receber a página, o navegador aplica as regras e bloqueia tudo que não estiver permitido pela política.
Para que serve no frontend
- Reduz risco de XSS, porque scripts injetados por atacante tendem a ser bloqueados.
- Controla chamadas externas (connect-src) para evitar exfiltração de dados para domínios não confiáveis.
- Impede incorporação indevida do app em iframes de terceiros com frame-ancestors.
- Define padrão mínimo de segurança para assets do frontend, inclusive em ambiente de produção.
Benefícios práticos
- Menor superfície de ataque para scripts maliciosos.
- Mais previsibilidade do que o app pode carregar em runtime.
- Melhora postura de segurança em auditorias e compliance.
- Ajuda a detectar comportamento suspeito com modo report-only.
Exemplo de política base
Content-Security-Policy: default-src 'self'; base-uri 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.seu-dominio.com; frame-ancestors 'none'; object-src 'none'; upgrade-insecure-requests;
Em apps com CSS-in-JS ou scripts inline, pode ser necessário ajustar a política com nonce/hash. Evite liberar 'unsafe-inline' e 'unsafe-eval' em produção sempre que possível.
Configuração no Next.js
Em Next.js, um caminho comum é definir a CSP em next.config.ts usando headers().
// next.config.ts
const csp = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"connect-src 'self' https://api.github.com",
"frame-ancestors 'none'",
"object-src 'none'",
].join('; ');
export default {
async headers() {
return [
{
source: '/(.*)',
headers: [{ key: 'Content-Security-Policy', value: csp }],
},
];
},
};Configuração no Vite
No Vite, o ideal é usar header no servidor de produção (Nginx/CDN). Para ambiente de desenvolvimento, você pode adicionar headers no vite.config.ts.
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
server: {
headers: {
'Content-Security-Policy':
"default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: http: https:;",
},
},
});Observação: em dev, HMR costuma exigir ws: e em alguns casos 'unsafe-eval'. Em produção, restrinja a política.
Outros frameworks frontend
Em React/Vue/Svelte (SPA), a melhor prática é configurar CSP no servidor web, proxy reverso ou CDN. O frontend sozinho não garante proteção se os headers não forem enviados na resposta HTTP.
# exemplo Netlify (_headers) /* Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:;
Exemplo com Nginx
server {
listen 443 ssl;
server_name app.seu-dominio.com;
root /usr/share/nginx/html;
index index.html;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.seu-dominio.com; frame-ancestors 'none'; object-src 'none'; base-uri 'self';" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location / {
try_files $uri /index.html;
}
}Resumo
CSP não substitui validação de input e sanitização, mas reduz bastante o impacto de falhas de XSS no frontend. O ganho maior vem quando você aplica política mínima em produção e evolui de forma iterativa.
Desenvolvido por: Aureo Bueno - Desenvolvedor full stack web
07/04/2026
Arquiteturas Hexagonal vs Clean vs Onion
Visão geral: o que as 3 arquiteturas tentam resolver?
As três surgiram para resolver o mesmo problema: manter regras de negócio protegidas de frameworks, banco de dados, UI e detalhes técnicos que mudam com o tempo.
Em termos práticos, elas aplicam Dependência Invertida para que o domínio continue estável e testável, enquanto adaptadores externos podem ser trocados com menor custo.
Como geralmente são desenhadas
1) Hexagonal (Ports and Adapters)
[Driver Adapter: HTTP/CLI/Test]
|
[Input Port]
|
[Application + Domain]
|
[Output Port]
|
[Driven Adapter: DB/API/Queue/File]O centro é a aplicação com domínio. Entradas e saídas acontecem por portas (interfaces). Adaptadores plugam nas portas.

2) Clean Architecture
[Frameworks & Drivers]
[Interface Adapters]
[Use Cases]
[Entities]É desenhada em círculos concêntricos. Regra principal: dependências sempre apontam para dentro. O que é mais interno é mais estável.

3) Onion Architecture
[UI / Infra / DB / Integrations]
[Application Services]
[Domain Services]
[Entities + Value Objects]Também usa anéis concêntricos. O domínio fica no núcleo e tudo ao redor depende dele. Infraestrutura é o anel mais externo.

Camadas e responsabilidade de cada arquitetura
Hexagonal: camadas lógicas
- Núcleo (Application + Domain): executa casos de uso, entidades, regras de negócio e políticas de negócio.
- Input Ports: contratos de entrada para acionar casos de uso (exemplo: criar pedido, aprovar pagamento).
- Output Ports: contratos que o núcleo precisa para sair (persistir, publicar evento, chamar API externa).
- Driver Adapters (entrada): REST, GraphQL, CLI, testes de aceitação; traduzem request para input port.
- Driven Adapters (saída): repository SQL/NoSQL, client HTTP, mensageria; implementam output ports.
Clean: camadas clássicas
- Entities: regras de negócio empresariais mais estáveis.
- Use Cases: regras de negócio da aplicação, orquestração de fluxo, validações de processo.
- Interface Adapters: converte modelos externos para internos e vice-versa (controllers, presenters, gateways).
- Frameworks & Drivers: DB, web framework, UI, devices, filas e detalhes de infraestrutura.
- Regra de dependência: camadas externas conhecem internas, nunca o contrário.
Onion: anéis comuns no dia a dia
- Core Domain: entities, value objects, invariantes e eventos de domínio.
- Domain Services: regras que não pertencem naturalmente a uma única entidade.
- Application Layer: casos de uso, coordenação de transações, autorização e orquestração de portas.
- Infrastructure Layer: implementação de repositórios, clients externos, observabilidade e persistência.
- Presentation/API: endpoints, controllers e handlers apenas adaptando entrada/saída.
Diferenças práticas entre elas
- Hexagonal: linguagem mais forte em portas/adaptadores e fronteiras de integração.
- Clean: linguagem mais forte em níveis de políticas e separação de responsabilidades por círculos.
- Onion: linguagem mais forte no domínio no centro e em serviços de aplicação ao redor dele.
- Na prática: muitas bases reais misturam os três termos porque os princípios são quase os mesmos.
Quando usar cada uma
- Prefira Hexagonal: quando seu problema principal é integrar vários canais de entrada e várias dependências externas.
- Prefira Clean: quando você quer uma comunicação didática para time grande e separação explícita de políticas em níveis.
- Prefira Onion: quando o domínio é rico e você quer reforçar a centralidade das regras de negócio ao longo de todo o design.
- Evite over-engineering: para sistemas pequenos, uma versão enxuta desses princípios costuma ser melhor que camadas em excesso.
Resumo direto
Hexagonal, Clean e Onion pertencem à mesma família arquitetural: variam mais na forma de organizar e comunicar as camadas do que nos princípios de base.
Na escolha entre elas, o ganho real vem da consistência na aplicação: fronteiras bem-definidas, contratos claros e infraestrutura isolada das regras de negócio.
Desenvolvido por: Aureo Bueno - Desenvolvedor full stack web
28/03/2026
Arquitetura de Pastas: Next.js 15 vs Vite + React 18
Next.js 15 - App Router Architecture
Arquitetura escalável para Next.js 15 com App Router
Estrutura de Pastas
src/ ├── app/ # App Router - Routing principal │ ├── layout.tsx # Layout raiz │ ├── page.tsx # Home page │ ├── (auth)/ # Route group (não afeta URL) │ │ ├── login/page.tsx │ │ └── register/page.tsx │ ├── dashboard/ │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── [id]/page.tsx # Dynamic routes │ └── api/ # API Routes │ └── users/route.ts ├── components/ │ ├── ui/ # Componentes reutilizáveis │ │ ├── Button/ │ │ │ ├── Button.tsx │ │ │ ├── Button.test.tsx │ │ │ └── index.ts │ │ ├── Card/ │ │ ├── Modal/ │ │ └── index.ts # Barrel exports │ ├── layout/ # Componentes de layout │ │ ├── Header/ │ │ ├── Footer/ │ │ └── Sidebar/ │ └── features/ # Componentes específicos de features │ ├── Auth/ │ └── Dashboard/ ├── lib/ # Lógica complexa e integrações │ ├── db.ts # Database connection │ ├── auth.ts # Auth service │ └── api-client.ts ├── server/ # Server-side logic │ ├── actions/ # Server actions │ │ └── user.actions.ts │ └── services/ │ ├── user.service.ts │ └── email.service.ts ├── hooks/ # Custom React hooks │ ├── useAuth.ts │ ├── useFetch.ts │ └── index.ts ├── utils/ # Utility functions │ ├── formatters.ts │ ├── validators.ts │ └── helpers.ts ├── types/ # TypeScript types │ ├── index.ts │ ├── user.ts │ └── api.ts ├── styles/ # Global styles │ ├── theme.ts # Styled-components theme │ ├── globals.css │ └── variables.css ├── public/ # Static assets │ ├── images/ │ ├── icons/ │ └── fonts/ └── env.example
Explicação das Pastas
app/
CRÍTICAContém toda a estrutura de routing do App Router. Cada pasta = uma rota. Arquivos especiais: layout.tsx, page.tsx, loading.tsx, error.tsx.
components/ui
ALTAComponentes reutilizáveis (Button, Card, Modal). Podem ser usados em múltiplas features.
components/features
ALTAComponentes específicos de funcionalidades (Auth, Dashboard). Apenas usados em suas features.
lib/
ALTAConfigurações e serviços complexos (DB, Auth, API client). Reutilizáveis em toda app.
server/
ALTALógica server-side, Server Actions e serviços backend. Isolados do cliente.
hooks/
MÉDIACustom hooks reutilizáveis. Encapsulam lógica de estado e side effects.
utils/
MÉDIAFunções puras e utilitários (formatação, validação). Sem dependências externas.
types/
MÉDIADefinições TypeScript centralizadas. Interfaces e tipos compartilhados.
Boas Práticas Essenciais
Use route groups () para organizar rotas sem afetar URLs.
Coloque Server Components por padrão e use 'use client' apenas quando necessário.
Server Actions para mutações de dados (melhor que API routes).
Mantenha lib/ para configurações e server/ para lógica.
Index files (index.ts) para barrel exports e melhor organização.
Componentes UI devem ser agnósticos ao contexto da app.
TypeScript centralizado reduz duplicação.
Comparação Rápida
| Feature | Next.js | React |
|---|---|---|
| Roteamento | App Router integrado (file-based) | React Router ou TanStack Router |
| Server/Client | Server Components por padrão | Tudo é Client-side por padrão |
| API | API Routes integradas | Chamadas externas a backend |
| Deploy | Vercel ou qualquer Node host | Qualquer servidor web estático |
| Melhor para | Full-stack apps com backend integrado | SPAs, PWAs, Frontend puro |
💡 Dicas Implementação
Padrão de Import
Use path aliases no tsconfig.json: "@/*", "@/features/*", "@/shared/*"
Index Files
Sempre exporte de index.ts para facilitar imports. Ex: import { Card } from "@/shared/card"
Não Importe Entre Features
Features devem ser independentes. Reutilize via shared/ para UI e utilitários comuns
TypeScript Strict Mode
Ative strict mode no tsconfig.json para máxima type safety
Desenvolvido por: Aureo Bueno - Desenvolvedor full stack web
26/11/2025
Boas Práticas de Code Review em React
O que é Code Review?
Code Review é uma prática essencial que envolve a revisão do código por outros desenvolvedores para garantir qualidade, evitar erros e fortalecer a manutenção do projeto.
Checklist para Revisar Código React
- Legibilidade: Código claro, comentado quando necessário e consistente com padrões do time.
- Componentização: Verificar se os componentes são pequenos, reutilizáveis e com responsabilidades claras.
- Estado e Props: Usa props adequadamente, evita estado desnecessário e respeita a imutabilidade.
- Desempenho: Usa técnicas como memoização e evita renderizações desnecessárias.
- Acessibilidade: Confirma uso correto de atributos ARIA, roles e navegação teclado.
- Estilo: Consistência no uso de CSS-in-JS, classes, e aderência ao design system.
- Testes: Cobre os componentes e hooks com testes unitários e de integração adequados.
Dicas para um Code Review Eficiente
- Seja construtivo e focado no código, evite críticas pessoais.
- Priorize entender o contexto do código antes de sugerir mudanças.
- Use ferramentas de revisão integradas para anotação rápida e discussões.
- Garanta que as mudanças não introduzam bugs ou regressões.
- Considere a escalabilidade e manutenibilidade ao sugerir melhorias.
Desenvolvido por: Aureo Bueno - Desenvolvedor full stack web
25/11/2025
Design Patterns no React
HOCs (Higher-Order Components)
Higher-Order Components são um padrão avançado que permite envolver um componente para adicionar funcionalidades extras, como layouts, logging ou controle de acesso, sem modificar o componente original. São uma forma poderosa de reutilizar lógica de forma declarativa e manter seus componentes simples.
function withLog<P>(Component: React.ComponentType<P>) {
return (props: P) => {
useEffect(() => console.log(`Componente ${Component.name} montado`), []);
return <Component {...props} />;
};
}Custom Hooks
Hooks personalizados são funções que encapsulam lógica relacionada a estados e efeitos, facilitando o reuso e organização do código. Por exemplo, um hook para buscar dados de uma API gerencia o estado de carregamento, resposta e possíveis erros, deixando o componente que o usa mais limpo e focado na interface.
function useFetchData(url: string) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(res => {
if (!res.ok) throw new Error("Erro na requisição");
return res.json();
})
.then(json => setData(json))
.catch(err => setError(err.message))
.finally(() => setLoading(false))
}, [url]);
return { data, loading, error };
}Compound Components
Compound Components é um padrão para construir componentes compostos e flexíveis que compartilham estado interno, permitindo que seus subcomponentes se comuniquem e ofereçam uma API declarativa e intuitiva para quem utiliza o componente. Um exemplo comum é um dropdown onde o botão controla o menu de opções de forma encapsulada.
function Dropdown({ children }) {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(!isOpen);
return <div>{children({ isOpen, toggle })}</div>;
}
function DropdownButton({ toggle, label }) {
return <button onClick={toggle}>{label} ▼</button>;
}
function DropdownMenu({ isOpen, children }) {
if (!isOpen) return null;
return <ul>{children}</ul>;
}Desenvolvido por: Aureo Bueno - Desenvolvedor full stack web
25/11/2025