Communitygithub.com

frontend — pantallas que funcionan para cada usuario, cada esta…

Úsalo al agregar o modificar cualquier elemento que el usuario vea o en el que haga clic en una app web Vue 3 o React — una pantalla, componente, composable o hook, store, formulario, ruta o fetch de datos — incluso para un ajuste pequeño o cuando la solicitud solo dice 'UI', 'página', 'formulario', 'frontend' o 'el botón no hace nada'.

¿Qué es frontend — pantallas que funcionan para cada usuario, cada esta…?

Esta skill guía el desarrollo frontend en aplicaciones Vue 3 o React, enfocándose en pantallas accesibles, con manejo completo de estados (carga, vacío, error y éxito) y código fácil de mantener. Sigue las convenciones del repositorio (`CLAUDE.md`, `docs/conventions.md`, `docs/design-system.md`) y no las anula, delegando el trabajo visual a la skill `css-design` y la verificación final a `verify-app`. El flujo incluye cargar las convenciones, escribir una tabla de estados antes del código, crear pruebas fallidas primero (con Vitest y Testing Library), construir dentro de la carpeta de feature, usar archivos de locale para todo texto visible, estilizar con tokens, crear stories para bibliotecas de componentes, ejecutar gates de lint, tipos y pruebas, realizar un recorrido en navegador real contra el build de producción (con Playwright y axe-core), verificar teclado y lector de pantalla, y finalmente pasar a `verify-app`. Soporta tanto Vue (TypeScript + Vite) como React (TypeScript + Vite o meta-framework), sin mezclar frameworks en una misma app.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

frontend — pantallas que funcionan para cada usuario, cada estado y se mantienen fáciles de cambiar

Sigue primero el CLAUDE.md, docs/conventions.md y docs/design-system.md del repositorio; esta skill rellena vacíos y nunca los anula. El trabajo visual (tokens, layout, color, CSS) pertenece a css-design; ejecutar la app como lo hará el usuario y el veredicto final pertenecen a verify-app.

Elige el stack. Vue 3 y React son ambos de primera clase y siguen las mismas reglas. Usa el framework que ya tenga el repositorio; para una app nueva usa el frontend por defecto del perfil de entrega (ver el README del repo), si no, pregunta una vez en el triage. Vue: TypeScript + Vite (npm create vue@latest -- --ts --router --pinia --vitest --playwright --eslint --prettier) con references/vue-patterns.md. React: TypeScript + Vite (o el meta-framework del repo) con references/react-patterns.md. Nunca mezcles frameworks en una misma app. ¿Necesitas SSR o SSG para SEO? Registra Nuxt o Next.js en un ADR (architect); esta skill cubre las partes del lado del cliente de todas formas.

Flujo de trabajo

  1. Carga las convenciones e inventario del repositorio. Lee CLAUDE.md, docs/conventions.md, docs/design-system.md; lista las partes reutilizables (ls src/components src/features src/composables src/hooks src/stores). Detecta la capa de datos, router, formulario y bibliotecas de 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 agregues una segunda capa de datos, router, store, formulario o biblioteca de i18n. Evidencia: las notas de la historia listan los componentes y composables/hooks reutilizados y cualquier nuevo, con la razón.
  2. Escribe la tabla de estados antes del código. Para cada vista: cada pieza de datos y dónde vive — servidor (query), URL (parámetros de ruta / búsqueda), cliente compartido (store de Pinia, o contexto de React o el store del repo), local (ref / useState), derivado (computed / una constante en render), externo (un composable o useSyncExternalStore que envuelve la API del navegador). Luego lista los cuatro estados (cargando, vacío, error, éxito) y las claves de copia para cada uno. Evidencia: la tabla en la historia.
  3. Escribe las pruebas fallidas primero. Vitest + @testing-library/vue o @testing-library/react, userEvent.setup(), consultas por rol y nombre accesible, un comportamiento por prueba, red falsificada en el límite del servicio (MSW o el cliente falso del repositorio en src/test-utils). Cubre cada estado, la ruta de teclado y un caso negativo. Evidencia: la ejecución muestra rojo por la razón correcta.
  4. Construye dentro de la carpeta de feature. src/features/<nombre>/services (llamadas API tipadas, sin framework) → composables / hooks (useX envolviendo useQuery/useMutation y una fábrica de claves) → components (Name.vue con <script setup lang="ts">, o Name.tsx) → la vista de ruta que los compone. Props y eventos tipados, sin any, sin ! no nulo, imports con @/. Evidencia: git diff --stat se mantiene dentro de la feature más cambios compartidos deliberados.
  5. Copia y formato. Cada cadena visible proviene de los archivos de locale (vue-i18n useI18n(), o la biblioteca i18n del repositorio React o módulo de copia) con las mismas claves en cada locale; una prueba verifica paridad. Números y fechas a través del formateador i18n o Intl. Evidencia: prueba de paridad verde; sin copia hardcodeada, forzado por lint (@intlify/vue-i18n/no-raw-text; React: react/jsx-no-literals o la regla del plugin i18n) — cita el código de salida del lint.
  6. Estiliza con css-design. Solo tokens, BEM bloque = nombre del componente, cada estado estilizado; estilos .vue lintados a través de postcss-html. Evidencia: Stylelint verde.
  7. Stories (bibliotecas de componentes). Una story por estado, ambos temas; Storybook axe pasa. Evidencia: la prueba de stories y la ejecución de axe.
  8. Gates, encadenados por código de salida. npm run lint && npm run type-check && npm run test:unit -- --run (Vue: vue-tsc --build; React: tsc -b), o make ci; nunca juzgues desde | tail. Evidencia: código de salida 0 y cobertura en o por encima del umbral del repositorio.
  9. Recorrido en un navegador real contra el build de producción. npm run build y sirve la salida (vite preview, o el servidor estático que use el repositorio). Agrega o extiende una especificación de Playwright para la ruta principal con @axe-core/playwright (etiquetas wcag2a wcag2aa wcag21aa wcag22aa, serios y críticos = 0). Captura docs/delivery/<slug>/evidence/<vista>-390.png y -1280.png, más el tema oscuro si la app lo tiene. Abre cada captura de pantalla antes de citarla. Evidencia: especificación verde, PNGs.
  10. Prueba de teclado y lector de pantalla. Tabula a través de la nueva vista: orden, foco visible, Escape cierra superposiciones y el foco vuelve al disparador; después de la navegación, el foco aterriza en el nuevo encabezado y el título cambió. Verifica nombres y anuncios puntualmente con un lector de pantalla (VoiceOver Cmd+F5, o NVDA). Evidencia: una nota de tres líneas en la sección de QA de la historia.
  11. Entrega. Ejecuta verify-app para la afirmación de extremo a extremo; dentro de deliver-loop la revisión independiente califica el ítem. No repitas sus pasos aquí.

Lista de verificación central

  1. Nada almacenado que se pueda derivar: usa computed (React: una constante en render); ningún watcher o efecto cuyo único trabajo sea establecer otro estado.
  2. Watchers y efectos solo sincronizan con el exterior (APIs del DOM, suscripciones, temporizadores, widgets de terceros) y limpian (onWatcherCleanup/onUnmounted; React: el retorno del efecto). El trabajo causado por una acción del usuario se ejecuta en el manejador de eventos.
  3. Los datos del servidor nunca se copian en estado local o un store; las claves de query contienen cada entrada que el fetch utiliza (en Vue como refs o getters, para que un cambio refetchee).
  4. Selección, filtros, pestañas y paginación que un usuario compartiría o recargaría viven en la URL query.
  5. Cada vista de datos renderiza estados de carga, vacío, error (con reintento) y éxito; las pruebas cubren los cuatro.
  6. Cada entrada tiene un <label for> visible (ids de useId() en ambos frameworks); los errores son texto vinculado con aria-describedby, la entrada se conserva, el foco se mueve al primer campo inválido al enviar.
  7. Elementos nativos primero (button, a href/router link, dialog, details, input type); sin div @click / div onClick.
  8. Widgets personalizados siguen el patrón WAI-ARIA APG correspondiente, teclado incluido.
  9. Resultados asíncronos que no mueven el foco se anuncian mediante una región role="status"/role="alert" renderizada una vez y vacía (Vue: teletransportada a body; React: un portal, si debe sobrevivir a la vista).
  10. Cambio de ruta: document.title actualizado y foco movido al h1 o main de la página (Vue: un router.afterEach + ref de plantilla; React: el equivalente del router).
  11. Los errores se capturan por ruta y por widget riesgoso (Vue: un componente de límite onErrorCaptured; React: un límite de error) y muestran un reintento, nunca una página en blanco.
  12. Sin cadenas de visualización hardcodeadas; cada locale tiene las mismas claves.
  13. Las pruebas consultan por rol/label/texto, interactúan con user-event, y nunca afirman sobre nombres de clase, internos de componentes (wrapper.vm, valores de estado), o llamadas a composables/hooks.
  14. Sin v-html / dangerouslySetInnerHTML a menos que se haya sanitizado con DOMPurify justo antes de usar; URLs de datos están en lista blanca para https:/mailto:/relativas.
  15. shallowRef/markRaw/v-memo/KeepAlive (React: memo/useMemo/useCallback) solo con una medición de perfilador o una necesidad documentada.
  16. Gráficos y visualizaciones de datos tienen un nombre accesible y resumen, una alternativa en tabla de datos (o texto), una paleta segura para daltonismo con series también diferenciadas por etiqueta, forma o patrón, y acceso por teclado a cualquier interacción — sea cual sea la biblioteca de gráficos que use el repositorio.

Anti-patrones

Vue:

  • watch(items, v => { filtered.value = v.filter(...) }) — usa computed.
  • const { count } = reactive(state) o const { name } = store — reactividad perdida; usa toRefs / storeToRefs, o prefiere ref.
  • watch(props.id, ...) o pasar una prop desestructurada a un composable — pasa un getter () => id.
  • Mutar una prop o datos de useQuery; vincular datos de query directamente a v-model — copia a un formulario.
  • v-if y v-for en el mismo elemento; :key="index" en una lista reordenable.
  • await antes de onWatcherCleanup o antes de registrar hooks de ciclo de vida en un composable.
  • defineAsyncComponent para un componente de ruta (las rutas toman () => import(...) directamente).
  • next() en un guardia de navegación — devuelve false, una ubicación, o nada.
  • Pruebas que acceden a wrapper.vm o llaman a setData.

React:

  • useEffect(() => setFiltered(items.filter(...)), [items]) — calcula en render.
  • Resetear un formulario en un efecto cuando un id cambia — pasa key={id}.
  • Hooks llamados dentro de condiciones o bucles; estado mutado en lugar de reemplazado.
  • key={index} en una lista reordenable; un nuevo objeto o función prop en cada render pasado a un hijo memoizado que fue memoizado por una razón medida.

Ambos:

  • Fetch al montar sin cancelación, caché, reintento o rama de error — usa la capa de datos.
  • Spinner sin rama vacía o de error; error tragado en console.log.
  • staleTime dejado en 0 para datos que cambian diariamente, por lo que cada focus refetchea.
  • Actualización optimista sin snapshot, rollback e invalidación al settled.
  • Placeholder usado como label; solo color marcando un error; role="button" sin teclas.
  • getByTestId por todas partes; snapshots de página completa; probar detalles de implementación.
  • Un archivo barrel de feature que empuja todo al primer chunk de ruta.
  • :href="user.url" / href={user.url} sin verificar el esquema.

Evidencia antes de "hecho"

  • Pruebas unitarias que fallan y luego pasan para cada estado y la ruta de teclado.
  • Lint, vue-tsc o tsc, pruebas encadenadas, salida 0; cobertura en o por encima del umbral.
  • Recorrido de Playwright contra el build de producción, axe serios/críticos = 0.
  • Capturas de pantalla a 390 y 1280 px (y tema oscuro) en docs/delivery/<slug>/evidence/, cada una abierta.
  • Nota de teclado y lector de pantalla en la sección de QA de la historia.
  • Luego verify-app.

Referencias

  • references/vue-patterns.md — la lista de verificación de Vue: SFC y API de componentes, trampas de reactividad, computed vs watch, composables, Pinia, TanStack Query para Vue, Vue Router (estado de URL, guardias, foco), formularios, i18n, accesibilidad específica, rendimiento, seguridad, herramientas; cada ítem con fuente.
  • references/react-patterns.md — la lista de verificación de React: los mismos temas, más una variante de exportación estática (Next.js / Nuxt generate).
  • references/a11y-and-testing.md — ítems WCAG 2.2 AA para código de UI, ARIA/APG, teclado y regiones vivas, gráficos, Testing Library para Vue y React, MSW, Playwright + axe, qué no probar.

Skills relacionados