Communitygithub.com

deputychinh/frontend

Verwenden Sie dieses Skill, wenn Sie in einer Vue 3- oder React-Web-App etwas hinzufügen oder ändern, das ein Benutzer sieht oder anklickt – einen Bildschirm, eine Komponente, ein Composable oder Hook, einen Store, ein Formular, eine Route oder einen Datenabruf – selbst für eine kleine Anpassung oder wenn die Anforderung nur „UI“, „Seite“, „Formular“, „Frontend“ oder „der Button tut nichts“ heißt.

Was ist frontend?

Der Skill „frontend“ ist darauf spezialisiert, konsistente, barrierefreie und testbare Benutzeroberflächen in Vue-3- und React-Web-Apps zu erstellen oder zu ändern. Er stellt sicher, dass jeder Zustand (Laden, Leer, Fehler, Erfolg) korrekt behandelt wird und der Code wartbar und wiederverwendbar bleibt. Das Vorgehen ist streng geregelt: Zuerst werden die Konventionen des Repositorys geladen (CLAUDE.md, docs/conventions.md, design-system.md), dann wird vor dem Schreiben des Codes eine Zustandstabelle erstellt. Unit-Tests werden vor der Implementierung geschrieben (Test-First), Komponenten werden Feature-basiert in `src/features/<name>/` organisiert, und alle sichtbaren Zeichenketten stammen aus Lokalisierungsdateien. Der Skill umfasst eine vollständige Checkliste mit Best Practices und Anti-Patterns für beide Frameworks, eine Zugänglichkeits- und Tastaturprüfung sowie eine abschließende End-to-End-Verifizierung mit Playwright. Er ist als Ergänzung zu den vorhandenen Repository-Richtlinien gedacht und überschreibt diese nicht.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

frontend – Bildschirme, die für jeden Benutzer, in jedem Zustand funktionieren und leicht änderbar bleiben

Beachten Sie zuerst die CLAUDE.md, docs/conventions.md und docs/design-system.md des Repositorys; dieses Skill füllt Lücken und überschreibt sie nie. Visuelle Arbeit (Tokens, Layout, Farbe, CSS) gehört zu css-design; das Ausführen der App wie der Benutzer und das endgültige Urteil gehören zu verify-app.

Wählen Sie den Stack. Vue 3 und React sind gleichberechtigt und folgen denselben Regeln. Verwenden Sie das Framework, das das Repository bereits hat; für eine neue App verwenden Sie das Frontend-Standard aus dem Lieferprofil (siehe README des Repositorys), sonst fragen Sie einmal im Triage. Vue: TypeScript + Vite (npm create vue@latest -- --ts --router --pinia --vitest --playwright --eslint --prettier) mit references/vue-patterns.md. React: TypeScript + Vite (oder das Meta-Framework des Repositorys) mit references/react-patterns.md. Mischen Sie niemals Frameworks in einer App. Benötigen Sie SSR oder SSG für SEO? Dokumentieren Sie Nuxt oder Next.js in einem ADR (architect); dieses Skill deckt in beiden Fällen die Client-seitigen Teile ab.

Arbeitsablauf

  1. Laden Sie die Konventionen und die Bestandsaufnahme des Repositorys. Lesen Sie CLAUDE.md, docs/conventions.md, docs/design-system.md; listen Sie wiederverwendbare Teile auf (ls src/components src/features src/composables src/hooks src/stores). Erkennen Sie die Daten-(Layer), Router-, Formular- und i18n-Bibliotheken (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). Fügen Sie niemals eine zweite Daten-(Layer), Router-, Store-, Formular- oder i18n-Bibliothek hinzu. Nachweis: Die Notizen der Story listen die wiederverwendeten Komponenten und Composables/Hooks sowie alle neuen auf, mit Begründung.
  2. Schreiben Sie die Zustandstabelle vor dem Code. Für jede Ansicht: jedes Datenelement und wo es lebt – Server (Query), URL (Route-Parameter / Suche), gemeinsam genutzter Client (Pinia-Store, oder React-Kontext oder der Store des Repositorys), lokal (ref / useState), abgeleitet (computed / eine Konstante im Render), extern (ein Composable oder useSyncExternalStore, das die Browser-API umschließt). Listen Sie dann die vier Zustände auf (Laden, Leer, Fehler, Erfolg) und die Kopier-Schlüssel für jeden. Nachweis: Die Tabelle in der Story.
  3. Schreiben Sie zuerst die fehlschlagenden Tests. Vitest + @testing-library/vue oder @testing-library/react, userEvent.setup(), Abfragen nach Rolle und zugänglichem Namen, ein Verhalten pro Test, Netzwerk an der Service-Grenze simuliert (MSW oder der Fake-Client des Repositorys in src/test-utils). Decken Sie jeden Zustand, den Tastaturpfad und einen negativen Fall ab. Nachweis: Der Lauf zeigt aus dem richtigen Grund Rot.
  4. Bauen Sie innerhalb des Feature-Ordners. src/features/<name>/services (typisierte API-Aufrufe, kein Framework) → composables / hooks (useX, das useQuery/useMutation und eine Key-Factory umschließt) → components (Name.vue mit <script setup lang="ts">, oder Name.tsx) → die Routen-Ansicht, die sie zusammensetzt. Props und Events typisiert, kein any, kein Non-Null !, @/-Imports. Nachweis: git diff --stat bleibt innerhalb des Features plus bewusste gemeinsame Änderungen.
  5. Kopieren und Formatieren. Jede sichtbare Zeichenkette stammt aus den Lokalisierungsdateien (vue-i18n useI18n(), oder der i18n-Bibliothek oder dem Copy-Modul des React-Repositorys) mit denselben Schlüsseln in jedem Gebietsschema; ein Test erzwingt Parität. Zahlen und Daten über den i18n-Formatierer oder Intl. Nachweis: Paritätstest grün; keine hartcodierten Kopien, erzwungen durch Lint (@intlify/vue-i18n/no-raw-text; React: react/jsx-no-literals oder die Regel des i18n-Plugins) – zitieren Sie den Lint-Exit-Code.
  6. Gestalten Sie es mit css-design. Nur Tokens, BEM-Block = Komponentenname, jeder Zustand gestaltet; .vue-Styles durch postcss-html gelintet. Nachweis: Stylelint grün.
  7. Stories (Komponentenbibliotheken). Eine Geschichte pro Zustand, beide Themes; Storybook axe besteht. Nachweis: Die Stories-Tests und der axe-Lauf.
  8. Gates, verkettet durch Exit-Code. npm run lint && npm run type-check && npm run test:unit -- --run (Vue: vue-tsc --build; React: tsc -b), oder make ci; nie von | tail aus beurteilen. Nachweis: Exit-Code 0 und Abdeckung auf oder über dem Schwellenwert des Repositorys.
  9. Journey in einem echten Browser gegen den Production-Build. npm run build und servieren Sie die Ausgabe (vite preview, oder der statische Server, den das Repository verwendet). Fügen Sie eine Playwright-Spezifikation für den Hauptpfad mit @axe-core/playwright hinzu oder erweitern Sie sie (Tags wcag2a wcag2aa wcag21aa wcag22aa, schwerwiegend und kritisch = 0). Erfassen Sie docs/delivery/<slug>/evidence/<view>-390.png und -1280.png, plus Dark-Theme, falls die App eines hat. Öffnen Sie jeden Screenshot, bevor Sie ihn zitieren. Nachweis: Spezifikation grün, PNGs.
  10. Tastatur- und Screenreader-Prüfung. Tabben Sie durch die neue Ansicht: Reihenfolge, sichtbarer Fokus, Escape schließt Overlays und der Fokus kehrt zum Auslöser zurück; nach der Navigation landet der Fokus auf der neuen Überschrift und der Titel hat sich geändert. Überprüfen Sie stichprobenartig Namen und Ansagen mit einem Screenreader (VoiceOver Cmd+F5, oder NVDA). Nachweis: Ein dreizeiliger Hinweis im QA-Abschnitt der Story.
  11. Übergabe. Führen Sie verify-app für den End-to-End-Anspruch aus; innerhalb von deliver-loop bewertet die unabhängige Überprüfung das Element. Wiederholen Sie deren Schritte hier nicht.

Kern-Checkliste

  1. Nichts speichern, was abgeleitet werden kann: computed verwenden (React: eine Konstante im Render); kein Watcher oder Effekt, dessen einzige Aufgabe es ist, anderen Zustand zu setzen.
  2. Watcher und Effekte synchronisieren nur mit der Außenwelt (DOM-APIs, Abonnements, Timer, Drittanbieter- Widgets) und räumen auf (onWatcherCleanup/onUnmounted; React: die Rückgabe des Effekts). Arbeit, die durch eine Benutzeraktion verursacht wird, wird im Event-Handler ausgeführt.
  3. Serverdaten werden niemals in den lokalen Zustand oder einen Store kopiert; Query-Keys enthalten jede Eingabe, die der Fetch verwendet (in Vue als Refs oder Getter, sodass eine Änderung erneut abruft).
  4. Auswahl, Filter, Tabs und Paginierung, die ein Benutzer teilen oder neu laden würde, leben in der URL-Query.
  5. Jede Datenansicht rendert Laden, Leer, Fehler (mit Wiederholung) und Erfolg; Tests decken alle vier ab.
  6. Jede Eingabe hat ein sichtbares <label for> (IDs von useId() in beiden Frameworks); Fehler sind Text, der mit aria-describedby verbunden ist, die Eingabe bleibt erhalten, der Fokus bewegt sich beim Absenden zum ersten ungültigen Feld.
  7. Native Elemente zuerst (button, a href/Router-Link, dialog, details, input type); kein div @click / div onClick.
  8. Benutzerdefinierte Widgets folgen dem entsprechenden WAI-ARIA APG-Muster, inklusive Tastatur.
  9. Asynchrone Ergebnisse, die den Fokus nicht verschieben, werden über einen role="status"/role="alert"-Bereich angekündigt, der einmal gerendert und leer ist (Vue: teleportiert zu body; React: ein Portal, falls es die Ansicht überleben muss).
  10. Routenwechsel: document.title aktualisiert und der Fokus auf die Seite h1 oder main verschoben (Vue: ein router.afterEach + Template-Ref; React: das Äquivalent des Routers).
  11. Fehler werden pro Route und pro riskantem Widget abgefangen (Vue: eine onErrorCaptured-Boundary-Komponente; React: eine Error-Boundary) und zeigen einen Wiederholungsversuch, niemals eine leere Seite.
  12. Keine hartcodierten Anzeigezeichenfolgen; jedes Gebietsschema hat dieselben Schlüssel.
  13. Tests fragen nach Rolle/Label/Text ab, interagieren mit user-event und bestätigen niemals Klassennamen, Komponenten-Interna (wrapper.vm, Zustandswerte) oder Composable/Hook-Aufrufe.
  14. Kein v-html / dangerouslySetInnerHTML, es sei denn, es wird unmittelbar vor der Verwendung mit DOMPurify bereinigt; URLs aus Daten sind auf https:/mailto:/relativ zugelassen.
  15. shallowRef/markRaw/v-memo/KeepAlive (React: memo/useMemo/useCallback) nur mit einer Profiler-Messung oder einem dokumentierten Bedarf.
  16. Diagramme und Datenvisualisierungen haben einen zugänglichen Namen und eine Zusammenfassung, eine Daten-Tabellen- (oder Text-)Alternative, eine farbenblind-sichere Palette, bei der Serien auch durch Beschriftung, Form oder Muster unterschieden werden, und Tastaturzugriff auf jede Interaktion – unabhängig von der verwendeten Diagrammbibliothek.

Anti-Patterns

Vue:

  • watch(items, v => { filtered.value = v.filter(...) }) – computed verwenden.
  • const { count } = reactive(state) oder const { name } = store – Reaktivität verloren; toRefs / storeToRefs verwenden oder ref bevorzugen.
  • watch(props.id, ...) oder ein destrukturiertes Prop an ein Composable übergeben – einen Getter () => id übergeben.
  • Ein Prop oder useQuery-Daten mutieren; Query-Daten direkt an v-model binden – in ein Formular kopieren.
  • v-if und v-for auf demselben Element; :key="index" bei einer neu anordenbaren Liste.
  • await vor onWatcherCleanup oder vor dem Registrieren von Lifecycle-Hooks in einem Composable.
  • defineAsyncComponent für eine Routenkomponente (Routen verwenden () => import(...) direkt).
  • next() in einem Navigation-Guard – false, einen Ort oder nichts zurückgeben.
  • Tests, die in wrapper.vm greifen oder setData aufrufen.

React:

  • useEffect(() => setFiltered(items.filter(...)), [items]) – im Rendern berechnen.
  • Ein Formular in einem Effekt zurücksetzen, wenn sich eine ID ändert – key={id} übergeben.
  • Hooks, die innerhalb von Bedingungen oder Schleifen aufgerufen werden; Zustand an Ort und Stelle mutiert, anstatt ersetzt zu werden.
  • key={index} bei einer neu anordenbaren Liste; ein neues Objekt oder eine neue Funktion als Prop bei jedem Rendern an ein memoisiertes Kind übergeben, das aus einem gemessenen Grund memoisiert wurde.

Beide:

  • Fetching beim Mount ohne Abbruch, Cache, Wiederholung oder Fehlerzweig – die Daten-Layer verwenden.
  • Spinner ohne leeren oder Fehlerzweig; Fehler in console.log verschluckt.
  • staleTime auf 0 belassen für Daten, die sich täglich ändern, sodass jeder Fokus erneut abruft.
  • Optimistisches Update ohne Snapshot, Rollback und Invalidate bei Abschluss.
  • Platzhalter als Label verwendet; Farbe allein markiert einen Fehler; role="button" ohne Tasten.
  • getByTestId überall; ganze Seiten-Snapshots; Testen von Implementierungsdetails.
  • Eine Feature-Barrel-Datei, die alles in den ersten Routen-Chunk zieht.
  • :href="user.url" / href={user.url} ohne Überprüfung des Schemas.

Nachweise vor „Erledigt“

  • Fehlschlagende, dann bestehende Unit-Tests für jeden Zustand und den Tastaturpfad.
  • Lint, vue-tsc oder tsc, Tests verkettet, Exit 0; Abdeckung auf oder über dem Schwellenwert.
  • Playwright-Journey gegen den Production-Build, axe schwerwiegend/kritisch = 0.
  • Screenshots bei 390 und 1280 px (und Dark-Theme) in docs/delivery/<slug>/evidence/, jedes geöffnet.
  • Tastatur- und Screenreader-Hinweis im QA-Abschnitt der Story.
  • Dann verify-app.

Referenzen

  • references/vue-patterns.md – Die Vue-Checkliste: SFC und Component API, Reaktivitätsfallen, computed vs. watch, Composables, Pinia, TanStack Query für Vue, Vue Router (URL-Zustand, Guards, Fokus), Formulare, i18n, A11y-Spezifikationen, Leistung, Sicherheit, Tooling; jedes Element mit Quellenangabe.
  • references/react-patterns.md – Die React-Checkliste: dieselben Themen, plus eine Variante für statischen Export (Next.js / Nuxt generieren).
  • references/a11y-and-testing.md – WCAG 2.2 AA-Items für UI-Code, ARIA/APG, Tastatur und Live- Regionen, Diagramme, Testing Library für Vue und React, MSW, Playwright + axe, was nicht getestet werden soll.

Verwandte Skills