Anti-Patterns LAND BILHON

Catalogo de erros visuais, estruturais e de codigo que NAO devem ser repetidos nos projetos bilhon.space. Cada entrada tem o problema, a solucao correta, e evidencia visual quando disponivel.

← Voltar ao Design System
5
Critical
9
Major
4
Minor
18
Total

Compliance por App

AppPrefixoRefs --bl-*ViolacoesStatus
RH.BOS --bl-* 100% 0 COMPLIANT
REPORTS.BOS --bl-* 336 refs 0 (zero rs-*) COMPLIANT
COMERCIAL.BOS --bl-* Parcial AP-018 (inline styles) REMEDIACAO
Bilhon Canvas --bl-* Parcial AP-016, AP-017 REMEDIACAO
HybridOps ho-* (alinhado) Proprio NS 0 ALIGNED

Auditoria automatica — 2026-04-02

AP-001 Hardcoded Credentials com Fallback
Critical
Errado
const SECRET = process.env.SECRET || 'meu-secret-hardcoded'
Correto
const SECRET = process.env.SECRET if (!SECRET) console.warn('[config] SECRET not set') const EFFECTIVE = SECRET || 'dev-only-fallback'

Secret hardcoded com fallback silencioso. Se env var falha, app roda com credencial previsivel. Atacante pode assinar cookies ou bypassar autenticacao.

Session hijack, webhook bypass, acesso nao autorizado a dados de 76k deals.

comercial.bosrh.bos
AP-002 Query sem LIMIT em Tabela Grande
Critical
Errado
const { data } = await sb .from('commercial_deals') .select('value') .eq('status', 'WON') // Busca TODOS os deals — pode ser 10k+
Correto
// Opcao 1: Limitar .select('value').eq('status', 'WON').limit(5000) // Opcao 2: Agregar server-side (melhor) const { data } = await sb.rpc('sum_won_revenue')

Query sem limit busca todos os registros. Com 76k deals, o browser recebe megabytes de JSON, processa no JS, e pode crashar em mobile.

TODA query client-side DEVE ter .limit(). Para agregacoes (sum, count, avg), usar Supabase RPC.

comercial.bos
AP-003 Loading Infinito sem Timeout
Critical
Errado
useEffect(() => { async function load() { try { /* fetch */ } catch { setLoading(false) } } load() }, []) // Se network hang → catch nunca executa → spinner eterno
Correto
useEffect(() => { const timeout = setTimeout(() => { setStats(prev => prev.loading ? { ...prev, loading: false, connected: false } : prev) }, 10000) // 10s timeout async function load() { /* ... */ } load() return () => clearTimeout(timeout) }, [])

Se Supabase/API nao responde (network hang), o catch nao e acionado. O usuario ve "Carregando..." pra sempre. Pensa que a app quebrou.

Todo loading DEVE ter timeout de 10s. Apos timeout, mostrar estado de erro com opcao de retry.

comercial.bosrh.bos
AP-004 Fundo que nao e #09090c
Major
Errado
background: #000000 (preto puro)
Correto
background: #09090c (off-black)

Preto puro (#000) e agressivo demais. O off-black #09090c tem um toque quente que reduz eye strain em uso prolongado.

NUNCA usar #000000 como fundo. Sempre --bl-bg-primary (#09090c).

todos
AP-005 Labels sem Monospace
Major
Errado
PIPELINE STATUS
Correto
PIPELINE STATUS

Labels de UI (botoes, badges, headers de secao, KPIs) usando Inter em vez de IBM Plex Mono. Quebra a identidade visual de "dashboard operacional".

Todo label, badge, botao, tag, header de secao = IBM Plex Mono + 10px + uppercase + tracking 0.08em. Inter so para corpo de texto.

todos
AP-006 Topbar sem Backdrop Blur
Major
Errado
TOPBAR OPACA
Correto
TOPBAR GLASS

Topbar com fundo solido parece pesada. O efeito glass (85% opacity + blur) cria profundidade e deixa o conteudo rolar "por baixo" com elegancia.

Topbar: bg rgba(9,9,12,0.85) + backdrop-blur-xl. NUNCA fundo 100% opaco.

todos
AP-007 Catch Vazio sem Log
Critical
Errado
try { await fetch(url) } catch {} // silencio total
Correto
try { await fetch(url) } catch (err) { console.error('[modulo] operacao falhou:', err) }

Catch vazio esconde erros. Bugs viram fantasmas — o sistema falha mas ninguem ve. Debugging vira impossivel.

Todo catch DEVE ter console.error com [modulo] prefix. Catch {} vazio e proibido.

comercial.bosrh.bos
AP-008 Middleware com Bypass de Rota
Critical
Errado
matcher: ['/((?!_next|favicon|legacy|.*\\.css$).*)'] // /legacy/ bypassa auth completamente
Correto
matcher: ['/((?!_next|favicon|.*\\.css$).*)'] // NENHUMA rota bypassa auth (exceto assets)

Excluir rotas do middleware permite acesso nao autenticado. Se alguem criar /legacy/admin, fica exposto.

Middleware matcher so exclui assets estaticos (_next, images, css, js). NUNCA excluir rotas de pagina.

comercial.bos
AP-009 Cor de Accent Errada por Produto
Major
Errado
COMERCIAL.BOS (verde = cor do RH)
Correto
COMERCIAL.BOS (azul = cor do Comercial)

Usar a mesma cor accent em todos os produtos confunde o usuario. Na aba do browser, todos os favicons ficam iguais. Nao da pra saber qual e qual.

RH = verde #6bc950 | Comercial = azul #3b82f6 | Reports = roxo #a855f7 | Forms = amber #f59e0b. NUNCA repetir.

todos
AP-010 Modal sem Acessibilidade
Major
Errado
<div className="fixed inset-0"> <!-- sem role, sem aria-modal, sem aria-label --> </div>
Correto
<div role="dialog" aria-modal="true" aria-label={title}> <button aria-label="Fechar">X</button> </div>

Modais sem role/aria sao invisiveis para screen readers. O botao de fechar sem aria-label e inacessivel.

Todo modal: role="dialog" + aria-modal="true" + aria-label. Todo botao interativo: aria-label descritivo.

todos
AP-011 Emoji nos Stage Names
Minor
Errado
Stage: 😁 Entrada de lead
Correto
Stage: Entrada de lead

Emojis nos nomes de stage vem do Clint CRM. Em dashboards com IBM Plex Mono, emojis quebram o alinhamento e parecem amadores.

Sempre aplicar stripEmoji() antes de exibir stage names. Funcao ja existe no war-room.

comercial.bos
AP-012 Dropdown sem Fundo Solido
Minor
Errado
Dropdown transparente — texto por baixo vaza
Correto
Dropdown com fundo solido #141418

Dropdowns com fundo transparente deixam o conteudo de baixo vazar. Fica ilegivel, especialmente sobre cards com dados.

Dropdowns e menus flutuantes: fundo --bl-bg-elevated (#0f0f14) ou #141418. NUNCA transparente.

comercial.bos
AP-013 Divisao por Zero sem Safe Guard
Minor
Errado
const closeRate = won / total * 100 // total = 0 → NaN → KPI mostra "NaN%"
Correto
const safeNum = (v) => { const n = Number(v); return isNaN(n) ? 0 : n } const closeRate = total > 0 ? (won / total) * 100 : 0

Divisao por zero produz NaN. NaN se propaga por todo o calculo. KPIs, graficos e leaderboards mostram "NaN" pro usuario.

Toda divisao: checar divisor > 0. Toda conversao Number(): usar safeNum() com fallback 0.

comercial.bosreports.bos
AP-014 Favicon Generico ou Ausente
Major
Errado
🌐 Favicon padrao do Next.js ou ausente
Correto
RH COM SVG 32x32, fundo #09090c, accent por produto

Sem favicon customizado, todas as abas parecem iguais. O usuario com 5+ abas abertas nao sabe qual e qual.

Cada app: favicon.svg no /public/ com fundo #09090c + accent do produto. Layout deve ter icons: { icon: '/favicon.svg' }.

todos
AP-015 as any em Queries Supabase
Minor
Errado
const data = (res.data || []) as any[] data.map(d => d.some_field) // zero type safety
Correto
interface DealRow { id: string; value: number | null stage: string | null } const data = (res.data || []) as DealRow[]

"as any" remove toda seguranca de tipo. Erros de acesso a campo errado so aparecem em runtime, nunca no build.

Zero "as any". Criar interface para cada query Supabase. Build deve ter 0 erros TypeScript.

todos
AP-016 Hardcoded Hex no Layout em vez de Token
Major
Errado
// bilhon-canvas layout.tsx:9 className="bg-[#09090c] text-[#f4f4e8]"
Correto
// Usar tokens do DS className="bg-[var(--bl-bg-2)] text-[var(--bl-text-primary)]" // ou Tailwind semantic className="bg-background text-foreground"

Cores hardcoded no layout root ignoram o token system. Se o DS mudar um valor, o layout nao acompanha. Quebra consistencia cross-app.

NUNCA usar hex literal em className ou style quando existe token --bl-* equivalente. Todos os backgrounds e textos devem referenciar tokens.

bilhon-canvas

Scan automatico 2026-04-02

AP-017 Hardcoded Hex em Topbar Components
Major
Errado
// bilhon-canvas topbar.tsx bg-[#0e0e12] // dropdown bg bg-[#fbbf24] // warning badge text-[#09090c] // badge text
Correto
bg-[var(--bl-bg-3)] // dropdown bg bg-[var(--bl-yellow)] // warning badge text-[var(--bl-bg-primary)] // badge text

Topbar usa 5+ cores hardcoded (#0e0e12, #fbbf24, #09090c) em vez de tokens. Qualquer mudanca no DS nao propaga para a topbar.

Topbar DEVE usar exclusivamente tokens --bl-*. Para cores de status (warning, danger), usar tokens semanticos (--bl-yellow, --bl-red).

bilhon-canvas

Scan automatico 2026-04-02

AP-018 Inline Style para Cores Dinamicas
Major
Errado
// comercial-bos topbar.tsx:238 style={{ borderLeft: `3px solid ${urgencyColor[level]}` }} style={{ color: urgencyColor[level] }} style={{ maxHeight: 420 }}
Correto
// CSS custom property + Tailwind style={{ '--urgency-color': urgencyColor[level] }} className="border-l-[3px] border-[var(--urgency-color)] text-[var(--urgency-color)] max-h-[420px]"

Inline styles para cores dinamicas impedem inspecao via DevTools, nao participam de cascata CSS, e misturam logica de apresentacao no JSX.

Cores dinamicas via CSS custom property no style + consumo via Tailwind arbitrary value. maxHeight e similares: SEMPRE Tailwind (max-h-[Npx]).

comercial-bos

Scan automatico 2026-04-02

LAND BILHON Anti-Patterns v1.1 — Homer (Romulo Henricco) — 2026-04-02
Para adicionar: criar screenshot, salvar em antipattern-img/, adicionar card aqui.