Communitygithub.com

deputychinh/frontend

Use ao adicionar ou alterar qualquer coisa que o usuário veja ou clique em uma aplicação web Vue 3 ou React — uma tela, componente, composable ou hook, store, formulário, rota ou busca de dados — mesmo para um pequeno ajuste ou quando a solicitação disser apenas "UI", "página", "formulário", "frontend" ou "o botão não faz nada".

O que é frontend?

Este skill define um processo rigoroso e completo para desenvolvimento frontend em Vue 3 ou React, garantindo telas que funcionam para todos os usuários, em todos os estados e que permanecem fáceis de modificar. Ele abrange desde a leitura das convenções do repositório e definição da stack (Vue ou React com TypeScript e Vite) até a entrega final verificada pelo skill `verify-app`. O fluxo de trabalho detalha 11 etapas que incluem: carregar convenções, escrever uma tabela de estados antes do código, criar testes que falham primeiro, construir componentes dentro de pastas de features, usar i18n para todas as strings, estilizar com tokens de design, criar histórias para bibliotecas de componentes, executar gates de qualidade (lint, type-check, testes unitários), testar a jornada completa em um navegador real contra o build de produção (com Playwright e axe-core para acessibilidade), verificar navegação por teclado e leitor de tela, e finalmente passar o bastão para `verify-app`. O skill também inclui uma checklist principal com 16 itens que cobrem boas práticas como evitar estado derivado, sincronizar apenas com APIs externas, nunca copiar dados do servidor para estado local, usar query params para filtros e paginação, tratar todos os estados (carregando, vazio, erro, sucesso), garantir acessibilidade com labels e ARIA, usar elementos nativos, e capturar erros. Além disso, lista anti-padrões específicos para Vue e React, como watchers desnecessários, mutação de props, perda de reatividade, e testes que acessam detalhes de implementação. O skill é compatível com Claude Code, Cursor e Codex, e requer as referências `vue-patterns.md`, `react-patterns.md` e `a11y-and-testing.md` para detalhes adicionais.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/deputychinh/Skills/tree/HEAD/skills/frontend

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

frontend — telas que funcionam para todos os usuários, em todos os estados e que permanecem fáceis de alterar

Siga primeiro o CLAUDE.md, docs/conventions.md e docs/design-system.md do repositório; este skill preenche lacunas e nunca os substitui. O trabalho visual (tokens, layout, cor, CSS) pertence ao css-design; executar o aplicativo como o usuário fará e o veredito final pertencem ao verify-app.

Escolha a stack. Vue 3 e React são ambos cidadãos de primeira classe e seguem as mesmas regras. Use o framework que o repositório já possui; para um novo aplicativo, use o padrão frontend do perfil de entrega (veja o README do repositório), caso contrário, pergunte uma vez na triagem. Vue: TypeScript + Vite (npm create vue@latest -- --ts --router --pinia --vitest --playwright --eslint --prettier) com references/vue-patterns.md. React: TypeScript + Vite (ou o meta-framework do repositório) com references/react-patterns.md. Nunca misture frameworks em um único aplicativo. Precisa de SSR ou SSG para SEO? Registre Nuxt ou Next.js em um ADR (architect); este skill cobre as partes do lado do cliente de qualquer forma.

Fluxo de trabalho

  1. Carregue as convenções e o inventário do repositório. Leia CLAUDE.md, docs/conventions.md, docs/design-system.md; liste as partes reutilizáveis (ls src/components src/features src/composables src/hooks src/stores). Detecte a camada de dados, roteador, bibliotecas de formulário e i18n (Vue: grep -E '"(@tanstack/vue-query|pinia|vue-router|vee-validate|vue-i18n)"' package.json; React: grep -E '"(@tanstack/react-query|@tanstack/react-router|react-router|react-hook-form|i18next|react-intl)"' package.json). Nunca adicione uma segunda camada de dados, roteador, store, formulário ou biblioteca i18n. Evidência: as notas da história listam os componentes e composables/hooks reutilizados e qualquer novo, com o motivo.
  2. Escreva a tabela de estados antes do código. Para cada visão: cada dado e onde ele vive — servidor (query), URL (parâmetros de rota / search), cliente compartilhado (store Pinia, ou React context ou a store do repositório), local (ref / useState), derivado (computed / uma const em render), externo (um composable ou useSyncExternalStore envolvendo a API do navegador). Em seguida, liste os quatro estados (carregando, vazio, erro, sucesso) e as chaves de cópia para cada um. Evidência: a tabela na história.
  3. Escreva os testes que falham primeiro. Vitest + @testing-library/vue ou @testing-library/react, userEvent.setup(), consultas por papel e nome acessível, um comportamento por teste, rede simulada no limite do serviço (MSW ou o cliente falso do repositório em src/test-utils). Cubra cada estado, o caminho do teclado e um caso negativo. Evidência: a execução mostra vermelho pelo motivo certo.
  4. Construa dentro da pasta de feature. src/features/<nome>/services (chamadas de API tipadas, sem framework) → composables / hooks (useX envolvendo useQuery/useMutation e uma fábrica de chaves) → components (Nome.vue com <script setup lang="ts">, ou Nome.tsx) → a visão da rota que os compõe. Props e eventos tipados, sem any, sem non-null !, imports com @/. Evidência: git diff --stat permanece dentro da feature mais alterações deliberadas compartilhadas.
  5. Cópia e formatação. Cada string visível vem dos arquivos de localidade (vue-i18n useI18n(), ou a biblioteca i18n do repositório React ou módulo de cópia) com as mesmas chaves em cada localidade; um teste garante paridade. Números e datas através do formatador i18n ou Intl. Evidência: teste de paridade verde; sem cópia hard-coded, garantido por lint (@intlify/vue-i18n/no-raw-text; React: react/jsx-no-literals ou a regra do plugin i18n) — cite o código de saída do lint.
  6. Estilize com css-design. Apenas tokens, BEM block = nome do componente, todos os estados estilizados; estilos .vue com lint através de postcss-html. Evidência: Stylelint verde.
  7. Histórias (bibliotecas de componentes). Uma história por estado, ambos os temas; Storybook axe passa. Evidência: os testes de história e a execução do axe.
  8. Gates, encadeados por código de saída. npm run lint && npm run type-check && npm run test:unit -- --run (Vue: vue-tsc --build; React: tsc -b), ou make ci; nunca julgue a partir de | tail. Evidência: código de saída 0 e cobertura igual ou acima do limite do repositório.
  9. Jornada em um navegador real contra o build de produção. npm run build e sirva a saída (vite preview, ou o servidor estático que o repositório usa). Adicione ou estenda uma especificação Playwright para o caminho principal com @axe-core/playwright (tags wcag2a wcag2aa wcag21aa wcag22aa, serious e critical = 0). Capture docs/delivery/<slug>/evidence/<view>-390.png e -1280.png, mais tema escuro se o aplicativo tiver um. Abra cada captura de tela antes de citá-la. Evidência: spec verde, PNGs.
  10. Verificação de teclado e leitor de tela. Navegue pela nova visão com Tab: ordem, foco visível, Escape fecha sobreposições e o foco retorna ao gatilho; após navegação, o foco pousa no novo título e o título mudou. Verifique nomes e anúncios com um leitor de tela (VoiceOver Cmd+F5, ou NVDA). Evidência: uma nota de três linhas na seção de QA da história.
  11. Passe o bastão. Execute verify-app para a afirmação de ponta a ponta; dentro do deliver-loop a revisão independente avalia o item. Não repita os passos deles aqui.

Checklist principal

  1. Nada armazenado que possa ser derivado: use computed (React: uma const em render); nenhum watcher ou effect cuja única função seja definir outro estado.
  2. Watchers e effects síncronizam apenas com o externo (APIs do DOM, subscriptions, timers, widgets de terceiros) e fazem a limpeza (onWatcherCleanup/onUnmounted; React: o retorno do effect). Trabalho causado por uma ação do usuário executa no event handler.
  3. Dados do servidor nunca são copiados para estado local ou store; as chaves de query contêm toda entrada que a busca usa (em Vue como refs ou getters, de modo que uma alteração refetch).
  4. Seleção, filtros, abas e paginação que um usuário compartilharia ou recarregaria vivem na query da URL.
  5. Toda visão de dados renderiza carregando, vazio, erro (com retry) e sucesso; testes cobrem todos os quatro.
  6. Toda entrada tem um <label for> visível (ids de useId() em ambos os frameworks); erros são texto vinculados com aria-describedby, a entrada é mantida, o foco move-se para o primeiro campo inválido ao enviar.
  7. Elementos nativos primeiro (button, a href/link do roteador, dialog, details, input type); nenhum div @click / div onClick.
  8. Widgets personalizados seguem o padrão WAI-ARIA APG correspondente, incluindo teclado.
  9. Resultados assíncronos que não movem o foco são anunciados através de uma região com role="status"/role="alert" renderizada uma vez e vazia (Vue: teleportada para body; React: um portal, se precisar sobreviver à visão).
  10. Mudança de rota: document.title atualizado e foco movido para o h1 ou main da página (Vue: um router.afterEach + template ref; React: o equivalente do roteador).
  11. Erros são capturados por rota e por widget arriscado (Vue: um componente de boundary onErrorCaptured; React: um error boundary) e mostram um retry, nunca uma página em branco.
  12. Sem strings de exibição hard-coded; toda localidade tem as mesmas chaves.
  13. Testes consultam por papel/label/texto, interagem com user-event, e nunca afirmam nomes de classe, internos de componente (wrapper.vm, valores de estado), ou chamadas de composable/hook.
  14. Sem v-html / dangerouslySetInnerHTML a menos que sanitizado com DOMPurify imediatamente antes do uso; URLs de dados são permitidos apenas para https:/mailto:/relativos.
  15. shallowRef/markRaw/v-memo/KeepAlive (React: memo/useMemo/useCallback) apenas com uma medição de profiler ou uma necessidade documentada.
  16. Gráficos e visualizações de dados têm um nome e resumo acessíveis, uma alternativa de tabela de dados (ou texto), uma paleta segura para daltonismo com séries também distinguidas por rótulo, forma ou padrão, e acesso por teclado a qualquer interação — independentemente da biblioteca de gráficos que o repositório usa.

Anti-padrões

Vue:

  • watch(items, v => { filtered.value = v.filter(...) }) — use computed.
  • const { count } = reactive(state) ou const { name } = store — reatividade perdida; use toRefs / storeToRefs, ou prefira ref.
  • watch(props.id, ...) ou passar uma prop desestruturada para um composable — passe um getter () => id.
  • Mutar uma prop ou dados de useQuery; ligar dados de query diretamente ao v-model — copie para um formulário.
  • v-if e v-for no mesmo elemento; :key="index" em uma lista reordenável.
  • await antes de onWatcherCleanup ou antes de registrar lifecycle hooks em um composable.
  • defineAsyncComponent para um componente de rota (rotas aceitam () => import(...) diretamente).
  • next() em um navigation guard — retorne false, uma localização, ou nada.
  • Testes que acessam wrapper.vm ou chamam setData.

React:

  • useEffect(() => setFiltered(items.filter(...)), [items]) — compute em render.
  • Resetar um formulário em um effect quando um id muda — passe key={id}.
  • Hooks chamados dentro de condições ou loops; estado mutado no lugar em vez de substituído.
  • key={index} em uma lista reordenável; um novo objeto ou função prop em cada render passado para um filho memoizado que foi memoizado por um motivo medido.

Ambos:

  • Buscar no mount sem cancelamento, cache, retry ou branch de erro — use a camada de dados.
  • Spinner sem branch vazio ou de erro; erro engolido em console.log.
  • staleTime deixado em 0 para dados que mudam diariamente, então cada focus refetch.
  • Atualização otimista sem snapshot, rollback e invalidate no settle.
  • Placeholder usado como o label; cor sozinha marcando um erro; role="button" sem teclas.
  • getByTestId em toda parte; snapshots de página inteira; testar detalhes de implementação.
  • Um barrel file de feature puxando tudo para o primeiro chunk de rota.
  • :href="user.url" / href={user.url} sem verificar o esquema.

Evidência antes de "pronto"

  • Testes unitários que falham e depois passam para cada estado e o caminho do teclado.
  • Lint, vue-tsc ou tsc, testes encadeados, exit 0; cobertura igual ou acima do limite.
  • Jornada Playwright contra o build de produção, axe serious/critical = 0.
  • Capturas de tela em 390 e 1280 px (e tema escuro) em docs/delivery/<slug>/evidence/, cada uma aberta.
  • Nota de teclado e leitor de tela na seção de QA da história.
  • Então verify-app.

Referências

  • references/vue-patterns.md — a checklist Vue: SFC e API de componente, armadilhas de reatividade, computed vs watch, composables, Pinia, TanStack Query para Vue, Vue Router (estado de URL, guards, foco), formulários, i18n, especificidades de a11y, desempenho, segurança, ferramentas; cada item com fonte.
  • references/react-patterns.md — a checklist React: os mesmos tópicos, mais uma variante de exportação estática (Next.js / Nuxt generate).
  • references/a11y-and-testing.md — itens WCAG 2.2 AA para código de UI, ARIA/APG, teclado e regiões vivas, gráficos, Testing Library para Vue e React, MSW, Playwright + axe, o que não testar.

Habilidades Relacionadas