Falar com o estúdioContato
Falar com o estúdio
03/7

Proteção contra incêndio

Home: "quando falhar não é opção"

Site WHK Engenharia

Site institucional recriado do Figma na altura exata do desenho, com painel próprio e as fotos 18× mais leves

Cliente
WHK Engenharia, pela agência CADMO
Categoria
Site institucional + CMS
Período
19–28 ago 2026
Estado
Em validação
whk-163-176-53-20.sslip.io

O problema

A WHK vende engenharia de proteção contra incêndio (projetos, memoriais, laudos, instalação e manutenção) para indústria, onde o comprador julga competência técnica antes de pegar o telefone. O site que ela tinha no ar era WordPress com Visual Composer: o conteúdo morava dentro dos atalhos do construtor, três das quatro páginas de serviço não traziam nada além de uma lista de entregáveis, e uma delas publicava o mesmo item duas vezes. A CADMO redesenhou tudo no Figma e precisava de duas garantias na entrega: prova de que o site é o desenho, e autonomia da WHK para trocar texto sem voltar à agência a cada ajuste.

O que foi construído

Monorepo Next 16 + Payload 3 sobre Postgres, recriado do arquivo do Figma lido pela REST API sempre por node-id, nunca por nome de camada. O nome mente no arquivo: três telas se chamam "Home" e nenhuma delas é a Home. O inventário, os 44 digests por seção e os tokens gerados do arquivo vieram antes da primeira linha de componente, e o CMS sobrepõe o desenho em vez de substituí-lo: campo vazio no painel devolve o conteúdo do Figma, então banco vazio ou fora do ar continua servindo o site inteiro. A responsividade, que o designer não desenhou (só existe o artboard de 1440), virou um segundo canvas em fluxo que consome exatamente as mesmas props do desktop.

0
px
Desvio de altura contra o desenho
13
larguras
Do 4K ao celular, nos 3 navegadores
2,5
MB
Todas as fotos do site (eram 44 MB)
0
Páginas que caem se o painel sair do ar

Decisões de engenharia

01

Dois canvas no DOM, uma única fonte de props

O `.canvas-desktop` é o artboard absoluto de 1440; o `.canvas-fluido` é tablet 820 e celular 402 em fluxo elástico, num DOM só, e o CSS decide qual pinta. As 23 seções recebem as mesmas props nos dois porque a página monta o mapa uma vez e cada função recebe só o nome do canvas. Prop que chega num canvas e não no outro deixa de ser possível por construção, e esse era o defeito mais repetido do projeto anterior. As mídias apontam para as mesmas URLs, então o DOM dobrado não custa download.

apps/web/src/components/layout/DoisCanvas.tsx · apps/web/src/styles/fluido.css (2.456 linhas com a procedência de cada arranjo)

02

15 gates que medem o build, não o olho

medir (≤0,5px por seção), ve (SOBRA 0 nas três engines, Firefox incluído), compara e pesa, mais 15 provas de aceite: 12 em Playwright, e as outras três falando direto com a API do painel, duas delas medindo pixel com sharp. Cada uma nasceu de um defeito que nenhuma outra enxergava: a prova de pintura varre luminância em faixas de 200px contra o render do Figma porque o compara deu +0px durante dias com o herói de Serviço 54% mais escuro. E quando o designer admitiu erro no próprio arquivo, a régua não baixou: as 10 divergências ativas (11 registradas, uma desfeita em 26/08) têm número, autor da decisão e caminho de volta, e o gate confere altura + divergência. Um erro de 59px onde a divergência é 60 continua sendo pego.

ls tools/prova-*.mjs | wc -l → 15 · grep -L playwright tools/prova-*.mjs → 3 · tools/telas.mjs:23 · docs/DIVERGENCIAS-DO-ARQUIVO.md

03

O site volta ao Figma por um plugin próprio

O designer só desenhou 1440, então o mobile é decisão de implementação nossa. Para ele poder mexer, o caminho foi invertido: um extrator lê o canvas fluido no navegador e um plugin escrito à mão remonta as 7 telas, em mobile e tablet, dentro do Figma Desktop, onde a PP Neue Corp instalada na máquina volta a ser usável. O MCP oficial não servia: cota mensal de 20 chamadas no plano Starter, estourada na oitava seção da primeira tela, e o runner dele só enxerga o catálogo do Google. Foi para esse caminho antigo que a fonte substituta saiu de uma medida, não do olho: largura de avanço de 122 frases reais do site contra 43 candidatas, 2,4% de erro médio contra 18,7% da Inter. O plugin tem gate headless que roda o code.js com a API do Figma dublada contra as 14 cenas.

tools/reverso/LEIA.md · tools/reverso/prova-plugin.mjs · tools/reverso/plugin/code.js · tools/reverso/gera.mjs:23-24

04

CMS que sobrepõe o desenho, nunca o substitui

Campo vazio no painel devolve o conteúdo do arquivo do Figma, e nenhuma função de leitura estoura: erro vira null ou lista vazia e o front cai no literal, então banco vazio ou fora do ar continua servindo o site inteiro. O selo âmbar que marca copy de mockup é automático: sobrevive enquanto o texto continuar sendo o do arquivo e cai sozinho quando a WHK escreve o dela. Não há lista para manter, nem risco de conteúdo de demonstração ficar esquecido em produção. O painel foi entregue com manual de 42 páginas feito das capturas reais de cada tela do admin.

apps/web/src/lib/cms.ts (5 catch; os 4 de leitura devolvem null/[]) · tools/prova-painel.mjs · docs/apresentacao/manual-painel/whk_manual_do_painel.pdf

Stack

Front-end
Next.js 16.2.12 + React 19.2.4 (App Router, dois root layouts por route group, 404 pega-tudo)
CMS
Payload 3.88: 6 coleções, 9 globais, seed idempotente e não destrutivo, live preview
Banco
PostgreSQL 17 em Docker (porta 5435), 3 migrações versionadas e lidas antes de rodar
Mídia
3,9 MB em 46 WebP e zero PNG. Disco local em dev, Cloudinary 2.10 em produção, lidos pela url que o Payload devolve
Design tokens
gerador próprio figma-tokens.json → tokens.css (85 variáveis), que recusa emitir entrelinha Auto
Leitura do design
Figma REST API por node-id (44 digests por seção) + plugin próprio de volta ao Figma
Ferramental
Playwright 1.62 em Chromium, WebKit e Firefox. 30 scripts em tools/ (mais 7 em tools/reverso), 15 deles gates de aceite
Infra
Docker Compose na OCI como terceiro inquilino de uma VM, Caddy compartilhado, deploy.sh com portão 7/7
Next.js 16Payload CMSPostgreSQLFigma REST APIplugin do FigmaPlaywrightdesign tokensDocker + OCI

Telas

A faixa full-bleed da home, em obra real
A faixa full-bleed da home, em obra real
Projetos e memoriais
Projetos e memoriais
A WHK
A WHK
A WHK, foto de abertura
A WHK, foto de abertura
Engenharia de sistemas de incêndio
Engenharia de sistemas de incêndio
Portfólio de obras entregues
Portfólio de obras entregues

O papel da CG Mixart

Arquitetura e execução full-stack: front em Next/React, CMS em Payload sobre Postgres, o ferramental de medição e aceite, o deploy na OCI e o material de validação que vai à mesa do cliente. O desenho é da CADMO; a CG Mixart traduziu o arquivo em site e construiu tudo o que prova que ele é o arquivo, incluindo o caminho de volta ao Figma para o designer editar o mobile.

Ressalvas e notas técnicas, verificadas no códigoabrir

Ressalvas, recontadas no repo em 28/08/2026: • Entrega parcial. O desktop está no ar e respondendo (HTTP 200 em 28/08), fechado e na mesa do designer da CADMO; o mobile aguarda o diff que ele devolver. O endereço ainda é o provisório de IP (sslip.io). O domínio final depende do apontamento de DNS da WHK. • A seção Entregáveis nasce desligada em apps/web/src/lib/telas/servico-dados.ts:186. Decisão nossa de 22/08, depois de vê-la no ar: ela não existe no arquivo do Figma e, ligada na página desenhada, tira a tela dos 6592px exatos em que o compara, o prova-pintura e a conferência de altura do ve batem. Não é irreversível: o "Sempre mostrar" do painel a religa (o `for` logo abaixo, linhas 189-191), e o conteúdo já está semeado nas quatro páginas de serviço. • 10 divergências ativas contra o arquivo do Figma, de 11 registradas: a nº 3 foi desfeita em 26/08 a pedido do designer. Todas com número, autor da decisão e caminho de volta. • O portfólio ainda mostra os projetos de mockup do designer (clientes inventados), marcados em âmbar e de propósito FORA do banco: eles caem sozinhos quando a WHK cadastrar os projetos reais pelo painel. • O que "0px" quer dizer, sem inflar: é o desvio da ALTURA da página contra a altura esperada (artboard do Figma mais a divergência já decidida com o designer), medido pelo compara a 1440. A pintura é conferida por outro gate, em faixas de 200px, por diferença de luminância. • Números citados a partir dos documentos do repo, não recontados por comando: os 515 nós de texto do inventário do Figma e as contagens internas de cada gate. Contexto que sustenta a entrega: • O projeto nasceu de um post-mortem escrito. Antes da primeira linha de código, o trabalho anterior da casa (Imah) virou 54 regras numeradas (22 acertos e 32 erros), incorporadas na arquitetura, não penduradas num wiki: o canvas absoluto que custou semanas de reescrita lá virou fluxo elástico desde a primeira seção aqui; o Firefox entrou no harness desde o dia 1 porque lá o site não existia nele por meses; a guarda que só liga push de schema em localhost foi portada antes de existir banco de produção. • Uma vistoria externa levantou 21 achados: 6 verdadeiros (consertados), 8 falsos e 7 decisões, cada um com o número que decidiu. • Duas cicatrizes documentadas em vez de escondidas. Subir este site derrubou o site vizinho na mesma VM (o Compose registra o nome do serviço como alias de DNS em toda rede em que o container entra, e o Caddy do vizinho passou a resolver `web` para o container errado). Está no CLAUDE.md com o diagnóstico e a correção. A outra é a lista E12, que enumera os pontos do código que conhecem a escala: ela existe porque no projeto anterior o breakpoint mudou 4 vezes e desalinhou o site em cada uma. • Para o cliente e o designer saíram dois PDFs gerados do próprio site: a comparação Figma × no ar em 31 folhas e o manual do painel em 42. Cliente por extenso: WHK Engenharia (proteção contra incêndio), contratação via agência CADMO. Desenho de Carlos Augusto.