O que CSS/JS faz?
Este skill converte um layout de landing page do Figma em HTML, CSS e JS estáticos. O trabalho é feito bloco por bloco: após cada bloco, o agente para e aguarda a confirmação do usuário.
As regras de codificação (estrutura, BEM, unidades, imagens, hover, etc.) estão em templates/AGENTS.md deste skill. Na etapa 3, este arquivo é copiado para a raiz do projeto e passa a valer sempre.
Requisitos
- Figma MCP conectado (
get_metadata,get_design_context,get_screenshot, se disponível —get_variable_defs). Se não estiver, informar o usuário e parar. - O usuário forneceu um link no formato
https://www.figma.com/design/:fileKey/:fileName?node-id=1-2. - Para servidor, screenshots e WebP, é necessário Node.js. Os comandos
npxna primeira execução baixam pacotes da rede — o Codex pode solicitar permissão; isso é normal.
Ordem de trabalho
Execute as etapas em ordem, sem pular nenhuma.
Etapa 1. Analisar o link
fileKey— a parte após/design/. Se o link contiver/branch/:branchKey/, usebranchKey.nodeId— o valor denode-id, substitua o hífen por dois-pontos (1-2→1:2).- O link pode levar ao documento inteiro, a uma página, a um frame desktop ou a um frame mobile. O tipo será determinado na etapa 2.
Etapa 2. Mapa do layout
- Chame
get_metadatapara o nó do link (para o documento inteiro, semnode-idou com a página raiz). - Encontre os frames de versão da landing page: desktop, mobile, às vezes tablet. As larguras devem ser determinadas a partir do layout, não use valores padrão. Encontre também frames separados de modais (popups) e menu mobile aberto, se existirem na página.
- Dentro de cada frame, identifique as seções de nível superior (cabeçalho, hero, vantagens, depoimentos, rodapé, etc.).
- Mapeie as seções entre as versões: "seção desktop ↔ seção mobile" (pelo nome da camada, ordem e conteúdo).
- Mostre ao usuário o mapa e aguarde a confirmação:
Larguras: desktop 1440, mobile 375
1. header — 12:30 ↔ 40:2
2. hero — 12:45 ↔ 40:18
3. advantages — 13:10 ↔ 41:5
...
Modais / menu:
- mobile-menu — 45:12
- popup-order — 46:01
Se não houver versão mobile, informe e pergunte como proceder.
Etapa 3. Estrutura do projeto e UI base
- Se
AGENTS.mdnão existir na raiz do projeto, copietemplates/AGENTS.mdda pasta do skill. Preencha a seção "Esta landing page" (larguras, container, fontes) com os dados da etapa 2. Mantenha os breakpoints padrão; altere-os somente se o layout quebrar em outras larguras — e então registre os novos. - Crie a estrutura:
index.html,style.css,script.js,assets/icons/. index.html:<!doctype html>,lang="pt",charset,viewport,<title>e<meta name="description">de acordo com o propósito da landing page. Não adicione favicon. Incluascript.jscomdefer.- Fontes: obtenha de
get_design_context/get_variable_defs, conecte via Google Fonts apenas os estilos necessários, comdisplay=swap. Se a fonte não estiver no Google Fonts, solicite ao usuário os arquivos e conecte via@font-facedeassets/fonts/. style.css: reset de estilos (vejaAGENTS.md), depois:rootcom variáveis de cores, fontes, espaçamentos, largura do container. Use valores deget_variable_defs, se houver variáveis no layout; caso contrário, extraia do layout e arredonde.- Componentes base: identifique elementos transversais do layout (botões, títulos de seção, campos de entrada) e crie classes reutilizáveis (
.btn,.section-title,.input,.container). Se o layout não tiver um kit de UI com estados (hover,focus,active), pergunte uma vez ao usuário as regras de hover para botões e links típicos de todo o projeto. Registre a resposta na linha "Estados de UI" da seção "Esta landing page" emAGENTS.md. - Ferramentas (uma vez):
- Inicie um servidor local em segundo plano a partir da raiz do projeto:
npx -y serve -l 3000(alternativa:python3 -m http.server 3000). Todos os screenshots devem ser tirados dehttp://localhost:3000, não defile://; - Verifique como tirar screenshots: Playwright MCP, se conectado; caso contrário, o script
scripts/shot.cjs(veja "Autoverificação"); - Verifique o conversor de imagens (veja "Imagens") e memorize o resultado.
- Inicie um servidor local em segundo plano a partir da raiz do projeto:
- Informe ao usuário que a estrutura está pronta e vá para o primeiro bloco.
Etapa 4. Blocos um por um
Para cada seção do mapa, estritamente em ordem de cima para baixo (incluindo seções com formulários):
- Dados.
get_design_contexteget_screenshotpara a seção desktop e sua contraparte mobile.- Se a resposta for truncada ou muito grande — use
get_metadatana seção e obtenha os nós filhos individualmente. - O código na resposta (geralmente React + Tailwind) é apenas uma referência de tamanhos, cores e estrutura. Não copie seu estilo.
- Se a resposta for truncada ou muito grande — use
- Imagens. Baixe e processe os assets do bloco (veja "Imagens").
- Codificação. HTML do bloco em
index.html, estilos emstyle.cssem seção separada com comentário/* ===== hero ===== */, JS (se necessário) emscript.js. Use as classes base da etapa 3.6, sem duplicar código de botões e títulos. Primeiro desktop, depois responsivo até mobile usandoclamp()e media queries.- Para
headerna largura mobile, codifique imediatamente o menu hambúrguer (com base no frame do mapa ou perguntando ao usuário o tipo). - Se o bloco contiver um formulário, codifique-o com atributos de validação básicos do navegador (
required,type="email",type="tel",pattern), mas sem lógica JS de envio.
- Para
- Autoverificação. Tire apenas a seção atual nas larguras desktop, mobile e intermediárias (1024, 768). Compare com os screenshots do Figma: espaçamentos, tamanhos, fontes, cores, quebras de linha. Corrija as diferenças e tire novamente.
- Com Playwright MCP — screenshot do elemento da seção em cada largura.
- Sem MCP — script da pasta do skill:
O script salva# uma vez mkdir -p .screens && cp <pasta-do-skill>/scripts/shot.cjs .screens/ npm i playwright --prefix .screens && npx -y playwright install chromium # após cada bloco node .screens/shot.cjs http://localhost:3000 .hero 1440,1024,768,375.screens/<seção>-<largura>.pnge imprime⚠ rolagem horizontalse a página ultrapassar a largura da tela. Qualquer aviso desse tipo — corrija a causa (não esconda comoverflow: hiddennobody). - Remova os screenshots das seções após a confirmação do bloco; mantenha o script e
node_modulesem.screens/até a etapa 6.
- Relatório e pausa. Escreva resumidamente ao usuário: o que foi feito, onde houve desvios do layout e por quê, quais interações únicas do bloco precisam de esclarecimento (hover não padrão de cartões, parâmetros de slider). Aguarde a confirmação. Incorpore as correções do usuário neste mesmo bloco e aguarde novamente.
- Somente após o "ok" — vá para o próximo bloco.
Etapa 5. Modais e lógica de formulários
Após codificar todas as seções principais:
- Codifique os modais ocultos (popups), se encontrados na etapa 2, e conecte os gatilhos de abertura/fechamento (botões,
Esc, clique no overlay). Comportamento conforme a seção "JavaScript" emAGENTS.md. - Cada modal como um bloco separado: autoverificação com screenshots no estado aberto, relatório e espera por confirmação.
- Verifique o funcionamento de todos os formulários na página. Não implemente envio de dados (
fetch/AJAX) a lugar nenhum, a menos que o usuário solicite explicitamente e forneça um endpoint ou especificação.
Etapa 6. Final
Após a confirmação da última etapa: verifique a página inteira em todas as larguras, remova arquivos e pastas temporários (assets/_raw/, .screens/ inteiro), pare o servidor local em segundo plano, remova estilos e imagens não utilizados. Escreva um breve resumo.
Imagens
- Obtenha os assets do bloco da resposta do Figma MCP (links para imagens em
get_design_context). Se for fornecido um endereçolocalhost, baixe diretamente. Não use placeholders ou conjuntos de ícones de terceiros. - Baixe para a pasta temporária
assets/_raw/<bloco>/, imagens rasterizadas com o dobro do tamanho (2x) em que aparecem no layout. - Gráficos responsivos: se a versão mobile do bloco usar uma imagem cortada (proporções diferentes) ou semanticamente diferente, baixe ambas as versões (
hero-bg-desktop.webpehero-bg-mobile.webp) e conecte via<picture>. - Classificação:
- Ícones pequenos dentro de elementos interativos (botões, links) que devem mudar de cor (
fill/stroke) ao passar o mouse → inline<svg>no HTML comfill="currentColor"(ou via CSSmask-image); - Ícones estáticos, logotipos, gráficos simples → SVG em
assets/icons/via<img>(ou na pasta do bloco, se for um gráfico grande). Se o ícone for rasterizado, informe o usuário; - Fotos e imagens complexas → WebP em
assets/<bloco>/.
- Ícones pequenos dentro de elementos interativos (botões, links) que devem mudar de cor (
- Converta para WebP, qualidade 80. Ordem de tentativas:
npx -y sharp-cli -i in.png -o out.webp -f webp -q 80(requer Node.js);cwebp -q 80 in.png -o out.webp;- se nenhum estiver disponível — mantenha o formato original e informe uma vez ao usuário o que instalar (Node.js ou
cwebp), sem interromper o trabalho.
- Se o WebP ficar mais pesado que o original — mantenha o original.
- Nomes de arquivo: latim, minúsculas, hífen, descritivos (
hero-photo.webp,arrow-right.svg). - Após confirmar o bloco, remova
assets/_raw/<bloco>/.
Hover, animações, sliders
- Hover: para botões e links básicos — regras da linha "Estados de UI" em
AGENTS.md. Se o bloco contiver cartões/elementos interativos únicos sem estados no layout — não invente; pergunte ao usuário no relatório do bloco. - Animações de scroll e animações personalizadas — somente se o usuário solicitar. Primeiro, esclareça exatamente o que deve acontecer. Para algo simples (aparecer ao scroll) —
IntersectionObserver; para algo pesado (vinculado à roda, seções pegajosas, parallax) — GSAP via CDN, apenas após consentimento do usuário. Sempre respeiteprefers-reduced-motion. - Slider: simples (setas, pontos, deslizar) — próprio em CSS
scroll-snap+ um pouco de JS. Complexo (infinito, reprodução automática, efeitos, sliders vinculados) — Swiper via CDN.
Problemas comuns
- Resposta do Figma truncada →
get_metadatana seção, depoisget_design_contextnos nós filhos. - Par mobile da seção ou frame do menu mobile não visível → pergunte ao usuário, não invente.
- Fonte não corresponde à largura do layout → verifique o peso e
letter-spacing, não ajuste o tamanho da fonte. - Imagens não baixam → verifique se o Figma MCP está em execução; use os links sem modificações.
- Screenshot com fontes ou ícones quebrados → verifique se o servidor em
localhost:3000está rodando e se o screenshot é tirado dele, não defile://. - Script imprime "rolagem horizontal" → encontre o elemento mais largo que a tela (largura fixa,
gapgrande, decoração fora da borda) e corrija; para elementos decorativos fora da borda — useoverflow-x: clipna seção. - Desvio do layout por questões de acessibilidade ou limitações técnicas → é aceitável, mas mencione no relatório do bloco.