Frontends com Vibecoding Capítulo: Ler a stack de um site grande sem chutar Trechos: 5 pedidos prontos para colar no seu agente Leia o LEIA-ME.txt desta pasta antes de usar. A página do capítulo explica a decisão; estes trechos só executam o que a página já decidiu. O primeiro pedido é o mais importante da lista: ele cria o arquivo de tokens que todos os outros vão importar. Rodar os demais antes dele espalha valor solto pelo projeto, exatamente o que o capítulo pede para evitar. ### O que faz: cria o arquivo único de tokens e os cinco componentes base do seu projeto ### Onde entra: antes de qualquer tela, no primeiro dia do projeto ### Cuidado: rodar isto depois das telas prontas obriga a reescrever cada componente Antes de qualquer tela, crie a fundação do meu design system num único arquivo `design-tokens.css` (ou `tokens.ts`) para um app React + Tailwind v4. Entregue: - Tokens de cor em OKLCH como variáveis CSS em :root: fundo, superfície, texto (contraste >12:1), texto-secundário (AA), cor de marca, borda e um par semântico sucesso/erro com AA sobre o fundo. - Escala tipográfica por tokens com clamp(): título grande, título, subtítulo, corpo (~16px), legenda. - Escala de espaçamento (4/8/12/16/24/32) e raios (8/12/16) como tokens. - Um bloco [data-theme="dark"] reatribuindo as cores com contraste AA mantido. - Cinco componentes base que CONSOMEM só esses tokens: Botão (com :focus-visible), Card, Input, Badge e Callout. Regra: nenhum valor de cor, tamanho ou espaçamento pode ser escrito solto nos componentes; tudo vem dos tokens. Comente que toda tela futura deve importar este arquivo. Esta é a minha estrada pavimentada. ### O que faz: pede a tela que parece viva antes de o dado chegar ### Onde entra: em qualquer lista que dependa de uma consulta ao servidor ### Cuidado: o esqueleto precisa ter a forma exata do conteúdo, ou a página pula quando o dado chega Crie um componente React `PainelPedidos` que busca dados de uma API e exibe uma lista, com a disciplina de latência percebida da Amazon embutida desde o início. Comportamento de carregamento (obrigatório): - Renderize PRIMEIRO um skeleton com a forma exata do conteúdo final (mesmas alturas e larguras dos cards), nunca um spinner solto. - Use streaming/Suspense (ou estado de loading explícito) para que o cabeçalho e o shell apareçam imediatamente, antes dos dados. - Faça prefetch dos dados no hover do link que leva a esta tela, se aplicável. - Trate os três estados de dados: vazio (mensagem útil + ação), erro (retry) e sucesso. Performance: - Nada de layout shift quando o dado chega: o skeleton reserva o espaço (dimensões fixas), CLS zero. - Comente onde está o ganho de latência percebida e por que o skeleton com a forma certa é melhor que um spinner. Meta declarada: a tela deve parecer "viva" em menos de 100ms, mesmo que os dados levem 800ms. Tokens de cor; contraste AA. ### O que faz: cria um componente encapsulado que funciona em qualquer tecnologia ### Onde entra: no design system, quando a peça precisa sobreviver a uma troca de framework ### Cuidado: o encapsulamento só vale se a página de fora ajustar a cor por token, sem alcançar o interior do componente Crie um Web Component nativo encapsulado chamado `` (um botão de call-to-action da minha marca), sem depender de nenhum framework, para eu poder usar a MESMA peça em páginas React, Astro ou HTML puro. Requisitos: - Use a API nativa de Custom Elements (class extends HTMLElement) com Shadow DOM (attachShadow mode 'open') para isolar totalmente o estilo: nenhum CSS global pode vazar para dentro nem de dentro para fora. - Aceite atributos: label, href, variante (primaria/secundaria). Reflita mudanças via observedAttributes. - Estilo interno por CSS custom properties expostas (ex.: --cta-bg, --cta-fg) para que cada página ajuste a cor SEM quebrar o encapsulamento, herdando dos meus design tokens. - :focus-visible sempre presente com anel de contraste AA; estado :hover só sob @media (prefers-reduced-motion: no-preference). - Acessível: papel de botão/link correto, navegável por teclado. Comente por que o Shadow DOM torna este componente imune a conflito de CSS entre frameworks, e por que isso é a forma mais durável de um design system sobreviver a uma troca de stack. Nada de fonte ou asset proprietário; conteúdo genérico meu. ### O que faz: pede duas superfícies do mesmo produto, cada uma com a tecnologia adequada ### Onde entra: no planejamento, quando o produto tem uma página de marca e uma área logada ### Cuidado: as duas precisam importar o mesmo arquivo de tokens, ou a identidade racha entre elas Vou construir duas superfícies do mesmo produto fictício, com naturezas diferentes. Importe o mesmo `design-tokens.css` nas duas para manter a identidade, mas escolha a abordagem técnica certa para cada uma e justifique em uma frase. Superfície 1, landing de marca (objetivo: narrativa + velocidade): - Proponha Astro (ou HTML/CSS com mínimo JS) e explique por que conteúdo estático pede menos JavaScript. - Hero, três seções de storytelling (uma ideia cada), CTA. Aprimoramento progressivo: funciona sem JS; animações de scroll são bônus sob prefers-reduced-motion: no-preference. - Meta de Core Web Vitals: LCP < 2,5s, CLS ~0. Superfície 2, painel transacional autenticado (objetivo: estado + robustez): - Proponha React/Next com estado de cliente e dados de servidor separados. - Foco em estados (vazio/carregando/erro), validação e foco visível. Regra: as duas DEVEM parecer o mesmo produto (mesmos tokens), mas não precisam compartilhar runtime nem cadência. Diga, para cada uma, qual decisão técnica você tomou e por quê. ### O que faz: pede o botão que responde na hora e desfaz sozinho se o servidor recusar ### Onde entra: em ação previsível e reversível, como marcar uma tarefa como concluída ### Cuidado: este padrão não vale para pagamento nem para nada que não dê para voltar atrás Crie um componente React `BotaoConcluir` que marca uma tarefa como concluída, com optimistic update e micro-interação funcional, no estilo do feedback do Duolingo, mas com conteúdo próprio. Comportamento (optimistic UI): - Ao clicar, atualize a UI IMEDIATAMENTE (marca como concluída, incrementa o contador de progresso) antes da resposta do servidor. - Dispare a requisição em segundo plano. Em caso de erro, faça rollback do estado e mostre um aviso discreto de "não foi possível salvar, tente de novo". - Aplique optimismo SÓ porque esta ação é previsível e reversível; comente que eu NÃO devo usar este padrão em pagamento ou operação irreversível. Micro-interação (funcional, não decorativa): - No sucesso visual imediato, uma animação curta de check que CONFIRMA a ação (escala + opacidade, na GPU). - Barra de progresso que cresce suavemente até a nova porcentagem. - Tudo dentro de @media (prefers-reduced-motion: no-preference); sob reduce, o estado muda sem movimento. Acessibilidade: anuncie a conclusão para leitores de tela (aria-live); foco visível. Tokens de cor; contraste AA. A animação tem que ter função: se não comunica nada, remova.