Pular para conteúdo

0010 — UI unificada para apps server-render

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-15 · Decidido em: 2026-07-15

Contexto

A constituição regia documentação e engenharia, mas não tinha convenção de UI. Resultado (loop §6, feedback de app): cada app que renderiza HTML no servidor — telas de admin/auditoria/dev, mesmo internas e protegidas pelo gate de auth do Coolify — reinventava o visual. O integrador já tinha layout.html + custom-theme.css + logo + Bootstrap padronizados; o tradutor ecom nasceu com <table border="1"> cru até ser retrofitado à mão. Divergência que só se pega no olho, nunca no gate.

Pior: o custom-theme.css do integrador usava #0066CC/#6B7280 (chute "azul vibrante ou similar"), não a paleta canônica do logo (royal #064490, prata #939495) — o mesmo drift de cor que a reconciliação do xadm.css (2026-07-01) já tinha corrigido no lado docs. Templatizar copiando teria propagado a cor errada.

Decisão

Todo app com views renderizadas no servidor segue o layout padrão X-Adm — piso na constituição §5 (UI dos apps), detalhe operável em Java/Micronaut §UI.

  • Fragment base único (head/navbar/scripts), Bootstrap 5, header escuro com logo + nome do cliente, e os idiomas visuais da casa (table-striped, badge bg-*, alert-*). O app só escreve o conteúdo de cada tela; o esqueleto vem do template.
  • Paleta única: o custom-theme.css dos apps deriva dos mesmos tokens do xadm.css do portal — uma fonte, dois consumidores (MkDocs Material no portal, Bootstrap nos apps). Sem CSS próprio por app além do necessário.
  • Kit rastreado, opcional no manifesto: layout.html, custom-theme.css, logo.png e favicon.ico são templates rastreados (sha256, sincronizados pela /xadm-docs) mas opcionais — app headless/Flutter não tem view, então não é defasagem; app com views mantém em sincronia. Adoção fora-do-padrão vira item de conformidade do /xadm-docs §3b (app tem views server-render e não usa o layout → não-conformidade).
  • Escopo = server-render. A casa só server-renderiza em Micronaut/Thymeleaf; Flutter é nativo e tem identidade própria (Flutter), fora deste raio.

Alternativas consideradas

  • Só documentar a convenção (sem template rastreado): o drift continua só no olho — o problema exato reportado. Preterido: o valor está no gate, não na prosa.
  • Xerocar o kit do integrador: propagaria a cor errada (#0066CC) e o navbar inconsistente (dois estilos, <style> inline + CSS). Preterido em favor de re-derivar limpo na paleta canônica.
  • Binários fora do manifesto (referenciar o logo publicado): app server-render precisa servir asset local (offline/gate), e o sync por /xadm-docs já cobre binário por sha256. Preterido: kit completo (imagens inclusas) rastreado é consistente com o resto.

Consequências

  • Tela nova nasce no padrão sem esforço: puxa os três fragments, escreve o miolo.
  • Zero drift de CSS por app; operador que abre integrador e tradutor vê a mesma casa.
  • Favicon é default substituível (gerado do wordmark); a variação quadrada do logo segue design pendente (backlog item 27) — quando existir, gera-se um favicon melhor.
  • Sem guarda offline: conformidade de UI é auditoria de código (/xadm-docs §3b) + revisão de PR, não o valida-frontmatter — o layout não tem shape validável por script.