refactor(skills): cut the workflows to ~100 lines and scale phases by tier

Each workflow was ~300 lines of grep-count "VERIFICAR" steps and ran every
phase for every request. Phases now state their minimum tier, checks are the
quality gate plus real tools, detail moved to references/, and machine-specific
paths and non-public skills are gone. Security references move to OWASP Top
10:2025, ASVS 5.0 and the OWASP LLM Top 10.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
EvandroandClaude Opus 5.5 committed 2026-09-24 21:52:06 -03:00
1 parent c18d3356ae
commit f2db2d69da
20 files changed
+823 -1176

No files matched your search

+67 -286
View File
@@ -1,317 +1,98 @@
---
name: wf-frontend
description: "Use p/ frontend/UI. Fluxo DESIGN→BUILD→REVIEW."
version: 1.0.0
author: Hermes Agent
description: Use para trabalho de frontend e UI - componentes, páginas, layouts, estilos, design system, animação, acessibilidade, redesign de tela existente, e geração de PDF ou documento visual a partir de HTML. Fluxo DESIGN, BUILD, REVIEW com profundidade definida pelo nível do dev-router. Não use para backend ou API (wf-backend), para bug sem mudança visual (wf-bugfix) nem para refactor sem mudança de comportamento (wf-refactor).
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [frontend, ui, ux, design, react, tailwind, workflow]
dev-workflows:
uses: [design-taste-frontend, redesign-existing-projects, lean-code, dev-router]
external: [frontend-design, web-design, vercel-react-best-practices, vercel-composition-patterns, animate, impeccable, avoid-ai-writing]
---
# Workflow Frontend/Design
# Workflow Frontend
Orquestrador obrigatório para TODO trabalho de frontend, UI, UX ou design
(componentes, páginas, landing, apps, re-design, design system). Processo de
3 fases com skills fixas por fase.
A profundidade vem do nível que o `dev-router` definiu. Cada fase diz a partir de qual nível roda.
## When to Use
| Nível | O que roda |
|---|---|
| 0 | só o gate (`--tier 0`) |
| 1 | ajuste de UI: siga o design system que já existe; sem DESIGN.md, sem aprovação; BUILD enxuto + gate `--tier 1` |
| 2 | tela ou componente novo: DESIGN curto, BUILD, REVIEW com `ui-critic` e `reviewer` |
| 3 | fluxo ou design system novo: DESIGN com aprovação do usuário, BUILD por tarefas, REVIEW completo |
Sempre que a tarefa envolver interface do usuário ou GERAÇÃO DE PDF:
- Frontend/UI: criar/editar componentes React/Vue/Svelte, páginas, layouts,
estilos, animações, acessibilidade, qualquer pedido de "design"
- **PDF/DOCUMENTOS VISUAIS: SEMPRE via este workflow** (regra do Evandro,
ago/2026) — NUNCA reportlab platypus raw (estoura bordas em tabelas
longas). Usar HTML+CSS → Playwright headless (`pdf-generator`,
`html-css-print-engineer`, `pdf-render-qa`). Design primeiro, depois
render, depois QA visual (vision_analyze) antes de entregar.
- Vale para apps novos e refactors.
## Skills (carregar só na fase que usa)
## Skills do stack (carregar conforme a fase)
- **Tela nova:** `design-taste-frontend` (~35 mil tokens; só para tela nova, nunca para ajuste) e, se instalada, `frontend-design`.
- **Tela existente:** `redesign-existing-projects` (audita antes de mudar).
- **Auditoria anti "UI de IA":** `impeccable` (`/impeccable audit`, externa).
- **React/Next:** `vercel-react-best-practices` (performance), `vercel-composition-patterns` (composição).
- **Motion:** `animate`. **Microcopy:** `avoid-ai-writing`.
- Sempre: `lean-code`.
- Direção visual / anti-AI-slop: `frontend-design` (Anthropic), `web-design`,
`impeccable` (pbakaus — 23 comandos de design: craft/shape/audit/polish/
animate/live; 59 regras determinísticas anti-slop),
`design-taste-frontend` (taste-skill: gera UI nova com direção inferida do
brief; 3 controles DESIGN_VARIANCE/MOTION_INTENSITY/VISUAL_DENSITY; ~22k
tokens, só para tela nova), `redesign-existing-projects` (taste-skill:
audita UI existente e sobe o nível sem quebrar funcionalidade), e locais
`frontend-award-tier`, `claude-design`, `popular-web-designs`,
`anti-ai-slop`
- React/Next performance + composição: `vercel-react-best-practices`,
`vercel-composition-patterns`
- Motion: `animate` (emilkowalski)
- Bug hunting: `hermaguard` (pre-scan + 3 agentes adversariais; read-only)
- Qualidade de texto/UI copy: `avoid-ai-writing` (remove AI-isms de microcopy,
textos de componente, a11y labels, README de frontend)
- Esboço rápido / docs visuais: `sketch`, `design-md` (locais)
- PDF de qualidade: `pdf-generator` (HTML+CSS LaTeX → Playwright),
`html-css-print-engineer`, `pdf-render-qa` (QA), `professional-pdf-director`,
`pdf-visual-designer` — todo PDF passa por aqui
Externas são opcionais: se não estiverem instaladas, siga as regras desta página. Instalação em `docs/SKILLS.md`.
## Fase 1 — DESIGN (decidir antes de codar)
## Fase 1, DESIGN (nível 2+, tela ou componente novo)
1. Carregar `frontend-design` + `frontend-award-tier` + `anti-ai-slop`.
Tela nova: somar `design-taste-frontend`. Re-design de tela que já
existe: `redesign-existing-projects` (audita antes de mudar).
2. Definir direção visual explícita: paleta, tipografia, espaçamento,
densidade, dark/light — NUNCA gerar "default AI slop".
3. Se for re-design/variação: `claude-design`/`popular-web-designs` para
basear em design systems reais (Stripe/Linear/Vercel) e fugir do genérico.
4. Documentar decisões em `DESIGN.md` (padrão `design-md` se aplicável).
5. Parar e validar a direção com o usuário ANTES de implementar.
6. VERIFICAR: rodar `avoid-ai-writing` em detect no DESIGN.md (0 AI-isms) e
confirmar que a direção está registrada (paleta + tipografia + density)
antes de codar.
7. VERIFICAR (gate visual): se for PDF/artefato visual, renderizar um
rascunho e inspecionar com `vision_analyze` ANTES de avançar — validar
que a direção visual de fato foi aplicada e nada está fora de margem.
8. CHECKPOINT: gravar decisões (paleta final, fonte, density) num
`DESIGN.md` com versionamento, para as fases seguintes referenciarem.
9. VERIFICAR (comandos de direção): conferir que `DESIGN.md` existe e tem
conteúdo — `wc -l DESIGN.md` > 5; e que as cores/fontes estão anotadas
(`grep -c "paleta\|fonte\|spacing" DESIGN.md` >= 3).
10. VERIFICAR (anti-slop real): rodar o `anti-ai-slop` no direção proposta
antes de mostrar ao usuário — detectar gradiente/glassmorphism
prematuramente economiza retrabalho.
11. VERIFICAR (comandos de design): validar a direção também contra a
ferramenta de design usada — `npx`/CLI do design system (ex:
`pnpm tailwindcss` se Tailwind) confirmando tokens aplicáveis; e
checar com `grep -rn "palette\|tokens\|--color" DESIGN.md` que os
tokens ficaram declarados.
Nível 1 pula esta fase e usa os tokens, componentes e padrões que o projeto já tem.
**Checklist da fase 1 (validar todos antes de seguir):**
- [ ] Direção visual definida e DOCUMENTADA (paleta, tipografia, spacing).
- [ ] Anti-slop: nenhum padrão "default IA" (gradiente, glassmorphism, ícones genéricos).
- [ ] `DESIGN.md` existe e está aprovado pelo usuário.
- [ ] `avoid-ai-writing` detect = 0 no DESIGN.md.
1. `explorer` mapeia o design system existente: tokens (cor, tipografia, espaçamento), componentes reutilizáveis, biblioteca de UI. Reaproveitar vem antes de criar.
2. Defina a direção: paleta, tipografia, densidade, claro/escuro. Tela nova usa `design-taste-frontend`; redesign usa `redesign-existing-projects`.
3. Registre as decisões em `DESIGN.md` (curto: tokens e o porquê).
4. Nível 3, ou decisão que é do usuário (identidade visual, troca de stack): pare e peça aprovação antes de codar. Nível 2 segue sem parar se a direção vem do design system existente.
**Anti-padrões desta fase:**
- NUNCA pular a definição de direção visual "só para ver como fica".
- NUNCA aprovar design sem a confirmação explícita do usuário.
- NÃO misturar 2 design systems na mesma tela; se for variação, basear em um só.
Evite: gradiente roxo genérico, glassmorphism sem motivo, cards idênticos em grade, ícone decorativo sem função, dois design systems na mesma tela.
## Fase 2 — BUILD (implementar com padrões de produção)
## Fase 2, BUILD (nível 1+)
1. Carregar `vercel-react-best-practices` + `vercel-composition-patterns`
(React) — aplicar regras de performance (waterfalls, bundle, re-renders)
e composição (compound components, sem boolean-prop explosion).
2. Componentes acessíveis por padrão (WCAG): semântica HTML, foco,
contraste — sem depender de ARIA desnecessário.
3. Animações só quando agregam: `animate` — propósito, duração, easing,
reduzir motion para prefers-reduced-motion.
4. Responsivo mobile-first; estados vazios/loading/erro em todo fluxo.
5. VERIFICAR: rodar build + lint incrementalmente a cada componente
(npm/pnpm build) e `vercel-react-best-practices` como checklist de perf
durante o build — não deixar para o fim.
6. VERIFICAR (a11y atômica): para cada componente novo, conferir semântica
HTML, gerenciamento de foco e contraste ANTES de considerar pronto —
acessibilidade é parte do build, não polimento final.
7. VERIFICAR (perf real): medir com DevTools/Lighthouse por tela-chave
(LCP, INP, CLS) e registrar os números no relatório de perf.
8. VERIFICAR (composição limpa): `grep -rn "is[A-Z]\|show[A-Z]" src/components`
para caçar boolean-prop explosion (deve ser 0 ou poucos intencionais);
se houver, refatorar para compound components.
9. VERIFICAR (animações justificadas): para cada `animate`/motion adicionada,
conferir com `grep -rn "animate\|transition\|motion" src/` que há propósito
(hover/estado/entrada) — animação decorativa sem função = cortar.
10. VERIFICAR (limpeza): `git status` e `git diff --stat` antes de fechar —
nada de arquivo órfão/debug commitado.
11. VERIFICAR (critério de aceite do componente): cada componente novo
confirma o critério definido na Fase 1 (estado correto, a11y ok, perf
ok) antes de passar para o próximo — validar item a item do checklist.
12. VERIFICAR (comandos de estado): conferir que loading/erro/vazio são
tratados em cada fluxo — `grep -rn "loading\|isLoading\|error\|empty" src/`
para provar a presença nos componentes que interagem com dados.
13. VERIFICAR (anti-padrão visual final): percorrer os componentes com
`anti-ai-slop` de novo ao fechar a fase — sombra/glassmorphism que
"escapou" no scroll é regressão de qualidade.
14. VERIFICAR (critério de aceite): validar que cada item do checklist da
fase está marcado (sem checkbox em branco) antes de declarar BUILD
concluído.
1. `implementer` (ou você, em mudança pequena) implementa com `lean-code`: componente e hook existentes antes de novos; CSS e HTML nativos antes de JS.
2. **Estados em todo fluxo com dados:** carregando, vazio, erro, sucesso.
3. **Acessibilidade por padrão:** HTML semântico, foco visível e em ordem, rótulos, contraste de texto >= 4.5:1. ARIA só quando o HTML não resolve.
4. **Responsivo mobile-first**, testado em 375 px e 1280 px.
5. **Composição:** compound components em vez de explosão de props booleanas (`isX`, `showY`).
6. **Motion com propósito** (estado, entrada, feedback) e `prefers-reduced-motion` respeitado.
7. React/Next: sem waterfall de dados, sem re-render em cascata, imagem com dimensões, código dividido por rota.
8. TypeScript sem `any` nem cast forçado para "passar".
9. Rode o gate a cada componente relevante, não só no fim.
**Checklist da fase 2 (validar antes da REVIEW):**
- [ ] Build e lint verdes (`npm run build` / `npx tsc --noEmit`).
- [ ] Componentes acessíveis (semântica HTML, foco, contraste) — auditar com
`frontend-design`/a11y antes de considerar pronto.
- [ ] Estados vazios/loading/erro presentes em todo fluxo.
- [ ] Animações com propósito + `prefers-reduced-motion` respeitado.
Entrada de usuário renderizada como HTML, `dangerouslySetInnerHTML`, `eval`, `postMessage` ou mudança de CSP disparam `security-auditor` (XSS/CSP).
**Anti-padrões desta fase:**
- NUNCA usar `any`/forçar cast em TS para "fazer passar".
- NUNCA animar sem propósito — animação decorativa gratuita é anti-padrão.
- NÃO implementar responsivo só no final; mobile-first desde o início.
- NÃO duplicar lógica de estado em vários componentes (compor, não copiar).
## Fase 3, REVIEW (nível 2+)
## Fase 3 — REVIEW (verificar antes de entregar)
1. `ui-critic`: screenshot em 375 e 1280, estados, a11y, padrões genéricos. Se `impeccable` estiver instalada, `/impeccable audit`.
2. `reviewer`: correção e simplicidade do diff.
3. `avoid-ai-writing` nos textos entregues ao usuário (labels, vazios, erros), se instalada.
4. Corrija o que for `bloqueante` ou `importante` e rode os dois de novo só no que mudou.
1. `anti-ai-slop` sobre o resultado (gradientes-texto, glassmorphism,
sombras genéricas, layout previsível).
2. `avoid-ai-writing` sobre textos entregues ao usuário: microcopy, labels,
empty states, mensagens de erro, README/descrições — remover AI-isms
(em-dash em excesso, "robust", "seamless", "let's dive in", etc).
3. `hermaguard` no diff de frontend (JS/TS/TSX/CSS): caça bugs adiversariais
no código produzido (lógica de estado, efeitos, a11y que quebra).
4. `vercel-react-best-practices` como checklist de perf (LCP/INP/CLS,
bundle, imagem, Suspense).
5. Rodar build + lint + testes do projeto; corrigir o que quebrar.
6. Relatório curto: o que foi decidido na Fase 1, entregue na 2, verificado
na 3.
7. VERIFICAR (regressão visual): se houver, comparar screenshots do antes
vs depois (ou `vision_analyze` no render) para garantir que nada quebrou
de layout.
8. VERIFICAR (não-regressão QA): rodar `test_quality.py` (gate do workflow)
e conferir que o score do stack não caiu.
9. VERIFICAR (hermaguard re-audit): se o REVIEW mudou >3 arquivos, rodar
`hermaguard` no novo diff antes de fechar.
10. VERIFICAR (bundle/perf real): rodar `npm run build` e conferir tamanho
dos chunks (`ls -lh dist/static/*.js`), anotar LCP/INP/CLS se houver
Lighthouse.
11. VERIFICAR (html válido): para PDF/páginas, validar o HTML antes do
render — `python3 -c "from html.parser import HTMLParser; ...
"` (ou parser disponível) e `grep -c "</t" arquivo.html` = 0 (sem tag
truncada).
12. VERIFICAR (comandos de acessibilidade): rodar auditoria de a11y no
render final — `npx @axe-core/cli http://localhost:PORT` (se houver
dev server) ou `pa11y`/equivalente; anotar violações sérias.
13. VERIFICAR (contraste verificado): para paleta dark/light, conferir
contraste com ferramenta (ex: `npx contrast-checker` ou manual) —
textos principais >= 4.5:1.
**Checklist da fase 3 (gate de entrega):**
- [ ] `anti-ai-slop` aplicado e sem ressalvas no resultado final.
- [ ] `avoid-ai-writing` detect = 0 em microcopy/labels/errors/README.
- [ ] `hermaguard` rodado no diff (0 findings CRITICAL/HIGH pendentes).
- [ ] `vercel-react-best-practices` auditado (LCP/INP/CLS, bundle, imagem).
- [ ] Build + lint + testes verdes com contagem real.
- [ ] Para PDF: renderização via Playwright + `vision_analyze` sem corte.
**Anti-padrões desta fase:**
- NUNCA dar como entregue com build vermelho.
- NUNCA ignorar finding CRITICAL/HIGH do hermaguard "para depois".
- NÃO pular o QA visual de PDF (conteúdo cortado nas bordas = entrega quebrada).
- NÃO entregar relatório sem os itens do checklist marcados.
## Comandos de Verificação (executáveis)
Gate de qualidade do stack (rodar SEMPRE antes de entregar):
## Gate
```bash
# 1) Não-regressão: valida que os workflows continuam íntegros
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py
# 2) Testes-dos-testes: prova que o harness detecta regressão
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py
"${CLAUDE_PLUGIN_ROOT}/scripts/quality-gate" --tier N
```
QA visual de PDF — renderizar páginas e inspecionar bordas (nada cortado):
Lint, typecheck, testes, segredos e build rodam sozinhos. O que depende do app de pé (Lighthouse,
axe, bundle, regressão visual) entra como `[[check]]` no `.dev-workflows.toml` do projeto: modelos em
[references/checks.md](references/checks.md). Lista completa de checagens:
`skills/dev-router/references/quality-gate.md`.
```bash
cd ~/.hermes/skills/productivity/pdf/scripts
python pdf_page_image.py /caminho/do.pdf --pages 1-3 --dpi 150 --out-dir /tmp/qa
# depoiss: vision_analyze em cada PNG — margens ok, sem truncamento
```
Metas de referência (nível 2+): LCP <= 2,5 s, INP <= 200 ms (TBT como proxy em laboratório),
CLS <= 0,1; axe sem violação `serious` ou `critical`; bundle dentro do limite do `size-limit`.
Qualidade de texto (microcopy, labels, README) — auditoria de AI-isms:
O `verifier` roda o gate e devolve a evidência. Ferramenta ausente aparece como "não verificado":
diga isso ao usuário, nunca chame de testado.
```bash
# detect (só lista) — passa 2 arquivos para comparar original vs limpo
node ~/.hermes/skills/avoid-ai-writing/detector/validate.js ui-copy.md ui-copy-limp.md
## PDF e documento visual
# ou debaixo do wf: pedir "roda o avoid-ai no README" (modo detect/rewrite)
```
Sempre HTML + CSS renderizado pelo Playwright (`page.pdf()`), depois cada página convertida em PNG e
inspecionada com Read: nada cortado na margem, tabela longa quebrando entre páginas. Nunca
reportlab platypus direto para tabelas longas. Método completo: [references/pdf.md](references/pdf.md).
Bug hunt adversarial no diff (comandos da skill hermaguard):
## Aceite
```bash
# gatilho: "hermaguard this" / "adversarial review" / "bug hunt this"
# gera relatório em /tmp/hermaguard/hermaguard-<ts>.md + .json
```
Performance React/Next — checklist durante o build:
```bash
npm run build # ou pnpm build — verificar warnings de bundle chunk
npx tsc --noEmit # typecheck limpo
npm run lint # sem erros
```
Resumo do fluxo (mapa de navegação do workflow):
```text
[Fase 1 DESIGN] -> frontend-design + anti-ai-slop -> DESIGN.md aprovado
[Fase 2 BUILD] -> vercel patterns + animate -> build/lint verdes
[Fase 3 REVIEW] -> avoid-ai + hermaguard + perf -> QA visual (PDF)
[Gate final] -> test_quality.py exit 0
```
## Critérios de Aceite (checklist não-regressivo)
- [ ] DESIGN.md com direção visual aprovada (Fase 1 validada pelo usuário).
- [ ] BUILD com perf/a11y; build e lint verdes a cada componente.
- [ ] REVIEW: anti-ai-slop + avoid-ai-writing + hermaguard + perf checklist.
- [ ] Para PDF: renderização via Playwright e QA visual (vision_analyze)
sem conteúdo cortado nas bordas.
- [ ] Nenhuma skill do stack removida do arquivo.
- [ ] Rodar `python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py`
→ exit 0 (sem regressão).
## Exemplos de execução por fase (comandos reais)
Fase 1 — direção visual documentada:
```bash
cat > DESIGN.md <<'EOF'
# Direção visual
Paleta: fundo #ffffff, acento #1e40af, texto #1a1a1a
Tipografia: serif corpo (Noto Serif/Georgia), mono p/ código
Density: padrão; dark/light: light first
EOF
```
Fase 2 — build e perf:
```bash
npm run build # ou pnpm build
npx tsc --noEmit # typecheck
npm run lint # sem erros
# "audite a perf" (vercel-react-best-practices)
```
Fase 3 — review/QA:
```bash
# "rode o anti-ai-slop" / "rode o avoid-ai nos textos"
# "hermaguard this" (bug hunt no diff de frontend)
```
Para PDF (regra do Evandro — SEMPRE este caminho):
```bash
# HTML+CSS -> Playwright headless
~/.hermes/venvs/latebra/bin/python /tmp/gen-pdf.py # ver pdf-generator
cd ~/.hermes/skills/productivity/pdf/scripts
python pdf_page_image.py saida.pdf --pages 1-N --dpi 150 --out-dir /tmp/qa
# depois vision_analyze em cada PNG: NENHUM conteúdo cortado nas bordas
# QA de perfil visual (se tiver origem de design)
node ~/.hermes/skills/avoid-ai-writing/detector/validate.js ui-copy.md ui-limp.md
```
Verificação de integridade do workflow (gate anti-regressão):
```bash
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py # não-regressão
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py # teste dos testes
# "hermaguard this" -> bug hunt adversarial se o diff >3 arquivos
# "rode o anti-ai-slop" -> antes de entregar
```
## Regras duras
- NUNCA pular a Fase 1 (consulta de design) direto para código.
- NUNCA entregar UI sem passar pelo `anti-ai-slop` + `avoid-ai-writing` +
`hermaguard` + build verde.
- Dúvida de stack (Vite vs Next, Tailwind vs CSS) → decidir na Fase 1 com
aprovação do usuário, não no meio do build.
- [ ] Nível declarado; fases puladas coerentes com ele.
- [ ] Nível 2+: direção registrada em `DESIGN.md` (aprovada pelo usuário no nível 3).
- [ ] Estados carregando, vazio, erro e sucesso em todo fluxo com dados.
- [ ] Acessível: semântica, foco, rótulos, contraste >= 4.5:1; axe sem `serious`/`critical` se configurado.
- [ ] Responsivo em 375 px e 1280 px, sem corte ou sobreposição.
- [ ] `prefers-reduced-motion` respeitado; animação só com propósito.
- [ ] Sem explosão de props booleanas; composição com compound components.
- [ ] Gate `pass`, ou falhas explicadas; "não verificado" listado ao usuário.
- [ ] PDF: páginas renderizadas e inspecionadas, nada cortado.
+91
View File
@@ -0,0 +1,91 @@
# Checagens de frontend para o `.dev-workflows.toml`
Estas checagens precisam do app de pé ou de configuração do projeto, por isso entram como
`[[check]]`. O gate só roda as do nível pedido ou abaixo.
```toml
[[check]]
name = "lighthouse"
cmd = "npx lhci autorun"
tier = 2
[[check]]
name = "a11y"
cmd = "npx playwright test e2e/a11y.spec.ts"
tier = 2
[[check]]
name = "bundle"
cmd = "npx size-limit"
tier = 2
[[check]]
name = "visual"
cmd = "npx playwright test e2e/visual.spec.ts"
tier = 3
```
## Lighthouse CI com orçamento (`lighthouserc.json`)
```json
{
"ci": {
"collect": { "startServerCommand": "npm run start", "url": ["http://localhost:3000/"], "numberOfRuns": 3 },
"assert": {
"assertions": {
"largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"total-blocking-time": ["error", { "maxNumericValue": 200 }],
"cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"categories:accessibility": ["error", { "minScore": 0.9 }]
}
}
}
}
```
INP só existe com usuário real; em laboratório, TBT é o proxy.
## Acessibilidade com Playwright + axe (`e2e/a11y.spec.ts`)
```ts
import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
for (const path of ["/", "/login"]) {
test(`a11y ${path}`, async ({ page }) => {
await page.goto(path);
const { violations } = await new AxeBuilder({ page }).analyze();
const graves = violations.filter(v => v.impact === "serious" || v.impact === "critical");
expect(graves).toEqual([]);
});
}
```
## Regressão visual (`e2e/visual.spec.ts`)
```ts
import { test, expect } from "@playwright/test";
for (const width of [375, 1280]) {
test(`home ${width}px`, async ({ page }) => {
await page.setViewportSize({ width, height: 900 });
await page.goto("/");
await expect(page).toHaveScreenshot(`home-${width}.png`, { fullPage: true });
});
}
```
A primeira execução grava a referência (`--update-snapshots`); as seguintes comparam.
## Bundle (`size-limit` no `package.json`)
```json
"size-limit": [{ "path": "dist/**/*.js", "limit": "200 KB" }]
```
## Screenshot rápida para o `ui-critic`
```bash
npx playwright screenshot --viewport-size=375,812 http://localhost:3000 /tmp/ui-375.png
npx playwright screenshot --viewport-size=1280,800 http://localhost:3000 /tmp/ui-1280.png
```
+49
View File
@@ -0,0 +1,49 @@
# PDF e documento visual: HTML + CSS + Playwright
Todo PDF passa por aqui: design primeiro, depois render, depois inspeção visual das páginas.
## Por que não reportlab direto
`platypus` com tabela longa estoura margem e corta linhas entre páginas. HTML + CSS de impressão
resolve quebra de página, cabeçalho repetido e margens com regras declarativas.
## 1. HTML com CSS de impressão
```css
@page { size: A4; margin: 18mm 16mm; }
table { width: 100%; border-collapse: collapse; }
thead { display: table-header-group; } /* repete o cabeçalho em cada página */
tr, img, figure { break-inside: avoid; }
h1, h2 { break-after: avoid; }
td { overflow-wrap: anywhere; } /* texto longo não empurra a margem */
```
## 2. Render com Playwright
```python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
page = p.chromium.launch().new_page()
page.goto("file:///caminho/relatorio.html")
page.pdf(path="relatorio.pdf", format="A4", print_background=True, prefer_css_page_size=True)
```
## 3. Inspeção visual obrigatória
Converta cada página em PNG e abra com Read:
```bash
pdftoppm -png -r 110 relatorio.pdf /tmp/qa/pagina
ls /tmp/qa/pagina-*.png
```
Em cada imagem, confira:
- nada cortado nas bordas (texto, tabela, imagem);
- tabela longa quebra entre páginas com o cabeçalho repetido;
- nenhuma linha órfã de título no pé da página;
- fontes carregadas (sem fallback inesperado).
Achou problema: ajuste o CSS, renderize de novo e inspecione de novo. Só entregue depois de todas as
páginas passarem.