Claude-skill-registry frontend-flow

Ensures frontend code quality by enforcing Design System (9 ESLint rules), Storybook coverage, and 5-step verification pipeline. Use when creating/modifying React components in frontend/src/, especially shared/ where quality gates are mandatory. Triggers on "create component", "verify frontend", "storybook coverage", "перевір фронтенд", "frontend flow". Goal - all verification passes before task completion, knowledge captured in vault.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/frontend-flow" ~/.claude/skills/majiayu000-claude-skill-registry-frontend-flow && rm -rf "$T"
manifest: skills/data/frontend-flow/SKILL.md
source content

Frontend Flow

Quality-first frontend development workflow for Pulse Radar.

Overview

┌─────────────────────────────────────────────────────────────┐
│  QUALITY-FOCUSED FRONTEND WORKFLOW                          │
│                                                              │
│  1. SESSION    2. DISCOVERY   3. IMPLEMENT   4. STORYBOOK   │
│  ────────────  ────────────   ────────────   ────────────   │
│  Journal       Storybook MCP  Tokens         Stories        │
│  Beads         Vault Search   Patterns       Screenshots    │
│  Context       AGENTS.md      Design System  Interaction    │
│                                                              │
│  5. VERIFICATION (CRITICAL)   6. KNOWLEDGE                  │
│  ────────────────────────────  ────────────                 │
│  TypeScript → ESLint → Tests   Journal done                 │
│  Story check → Accessibility   Capture                      │
│  ALL MUST PASS                 Beads update                 │
└─────────────────────────────────────────────────────────────┘

Principle: Quality over speed. Verification must pass before task completion.

Phase 1: Session & Context

Trigger: Starting frontend work

Actions:

  1. Start journal session:
    /obsidian:journal session "Task title"
  2. Get issue context:
    bd show {issue}
  3. Read previous handoff if exists

Goal: Establish context and enable progress tracking.

Phase 2: Discovery (CRITICAL!)

Trigger: BEFORE creating or modifying any component

Required checks:

# 1. Check existing components in Storybook
storybook_list_components

# 2. Get props API for similar components
storybook_get_component_props componentId="..."

# 3. Search knowledge vault
/obsidian:search "relevant pattern"

# 4. Read Design System rules
frontend/AGENTS.md

Checkpoint: "Existing component found? → USE IT instead of creating new!"

Anti-pattern: Creating new component without Storybook check = quality violation.

→ See @references/discovery.md for detailed checklist.

Phase 3: Implementation (Design System)

Trigger: During code writing

Required rules:

RuleUseDon't Use
Colors
@shared/tokens/*
bg-red-500
,
text-green-600
Patterns
@shared/patterns/*
Manual composition
Icons
lucide-react
heroicons, Radix icons
Touch
h-11 w-11
(44px)
h-9 w-9
(36px)
Spacing
gap-2
,
gap-4
,
p-4
gap-3
,
p-5
(off-grid)
Icon buttons
aria-label="..."
No label
StatusIcon + TextColor only

Related skills:

/frontend
,
/design-tokens

Phase 3.5: Component Portability (NEW!)

Trigger: When creating/modifying components in

shared/

Principle: Components in shared/ must be PORTABLE — work without API, store, router.

┌─────────────────────────────────────────────────────────────┐
│  PORTABLE COMPONENT = Pure Function                         │
│                                                             │
│  Props → Component → UI                                     │
│                                                             │
│  ✅ No useQuery/useMutation inside                          │
│  ✅ No apiClient/fetch calls inside                         │
│  ✅ No useNavigate/useParams/useLocation                    │
│  ✅ No useStore (Zustand) directly                          │
│  ✅ All data via props                                      │
│  ✅ Works in Storybook WITHOUT providers                    │
└─────────────────────────────────────────────────────────────┘

Anti-pattern (FORBIDDEN):

// ❌ NON-PORTABLE — violates CDD principles
import { useQuery } from '@tanstack/react-query'
import { apiClient } from '@/shared/lib/api'

export function ActivityHeatmap() {
  const { data } = useQuery({ queryFn: () => apiClient.get('/activity') })
  return <Heatmap data={data} />
}

Correct pattern (Presenter + Hook):

// ✅ PORTABLE PRESENTER — shared/components/
interface ActivityHeatmapProps {
  data: ActivityDataPoint[]
  isLoading?: boolean
  className?: string
}

export function ActivityHeatmap({ data, isLoading, className }: ActivityHeatmapProps) {
  if (isLoading) return <ActivityHeatmapSkeleton />
  return <HeatmapRenderer data={data} className={className} />
}

// Data hook — features/activity/hooks/ or page level
export function useActivityData(timeRange: TimeRange) {
  return useQuery({
    queryKey: ['activity', timeRange],
    queryFn: () => activityService.getActivity(timeRange)
  })
}

// Page usage — composition
function DashboardPage() {
  const { data, isLoading } = useActivityData('week')
  return <ActivityHeatmap data={data ?? []} isLoading={isLoading} />
}

Portability Checklist:

  • No useQuery/useMutation in shared/components
  • No apiClient/fetch imports in shared/components
  • No useNavigate/useParams in shared/components
  • All data passed via typed props interface
  • Optional className prop for customization
  • Works in Storybook without QueryClient/Router mocks

Verification command:

# Should return 0 violations
grep -rE "useQuery|apiClient" src/shared/components --include="*.tsx" | grep -v test

Phase 3.6: Component Integration Decision (NEW!)

Trigger: When needing a new UI element

Decision Tree:

NEED NEW UI ELEMENT?
         │
         ▼
┌─────────────────────────────┐
│ 1. Check shared/ui/         │ → EXISTS → USE IT
└─────────────────────────────┘
         │ NOT FOUND
         ▼
┌─────────────────────────────┐
│ 2. Check shared/components/ │ → EXISTS → USE IT
└─────────────────────────────┘
         │ NOT FOUND
         ▼
┌─────────────────────────────┐
│ 3. Check shared/patterns/   │ → EXISTS → USE IT
└─────────────────────────────┘
         │ NOT FOUND
         ▼
┌─────────────────────────────┐
│ 4. Check shadcn registry    │
│    ui.shadcn.com/docs       │
└─────────────────────────────┘
         │
    FOUND ┴ NOT FOUND
      │        │
      ▼        ▼
  EVALUATE   BUILD in shared/components
      │
 Fits 80%? ┬ YES → npx shadcn add → shared/ui
           │
           └ NO → WRAP in shared/components

Where to put new component:

TypeLocationExample
shadcn primitive
shared/ui/
Button, Dialog, Select
shadcn + customize
shared/ui/
(modify)
Badge with new variant
Composition
shared/patterns/
CardWithStatus, FormField
Business reusable
shared/components/
SearchBar, TopicSelector
Feature-specific
features/X/components/
AtomCard, ProviderList
Page-specific
pages/X/components/
DashboardStats

Adding shadcn component example:

# 1. Check if exists
grep -r "DatePicker\|Calendar" src/shared/

# 2. Add from shadcn
npx shadcn@latest add calendar

# 3. Create composition wrapper if needed
# src/shared/components/DatePicker/index.tsx

Checkpoint: "Component location decided? Portability requirements clear?"

Phase 4: Storybook (Component Library)

Trigger: After creating/modifying component

Mandatory coverage:

LocationStory Required?Min Stories
shared/ui/
Always4-6
shared/patterns/
Always5-8
shared/components/
Always4-6
features/*/
If >50 LOC or reused2-4

Actions:

  1. Create
    .stories.tsx
    with
    tags: ['autodocs']
  2. Cover all variants, states, sizes
  3. Add interaction tests for clickable elements
  4. Capture screenshot:
    storybook_capture_screenshot storyId="..."

Checkpoint: "Story created with full coverage?"

Related skill:

/storybook

Phase 5: Verification Pipeline (MOST IMPORTANT!)

Trigger: After code written, BEFORE considering task complete

Required pipeline (ALL steps!):

cd frontend

# 1. TypeScript — type safety
npx tsc --noEmit

# 2. ESLint — Design System compliance (9 rules)
npm run lint

# 3. Unit tests — logic correctness
npm run test:run

# 4. Story coverage — documentation
npm run story:check

# 5. Accessibility (for shared/ components)
npm run test:a11y

ESLint Design System Rules (all 9 — ERROR level):

#RuleEnsures
1
no-raw-tailwind-colors
Semantic tokens only
2
no-odd-spacing
4px grid system
3
no-heroicons
lucide-react only
4
no-raw-zindex
Named z-index tokens
5
no-direct-fonts
Font tokens only
6
no-raw-page-wrapper
PageWrapper required
7
no-direct-api-imports
Service classes
8
no-hardcoded-api-paths
API_ENDPOINTS config
9
stories-require-autodocs
Autodocs tag

If any step fails: Fix → Re-run pipeline → Don't proceed until ALL pass.

→ See @references/verification.md for troubleshooting.

Phase 6: Knowledge Capture

Trigger: After successful verification

Actions:

  1. Close journal session:
    /obsidian:journal done
  2. Add findings as wikilinks:
    [[знання/паттерни/pattern-name]]
  3. Capture learnings:
    /obsidian:capture auto
  4. Update Beads:
    bd comments add {issue} "Progress: ..."
  5. Generate handoff for next session

Learning categories:

  • знання/паттерни/
    — reusable approaches
  • знання/рішення/
    — architectural decisions
  • знання/помилки/
    — mistakes to avoid

→ See @references/documentation.md for templates.

Quality Gates

GateCriterionBlocking?
DiscoveryStorybook checked BEFORE codingYes
Design SystemTokens instead of raw colorsYes (ESLint blocks)
StorybookStory for shared/ componentsYes
TypeScript
tsc --noEmit
passes
Yes
ESLint9 Design System rules passYes
TestsUnit tests passYes
Story Coverage
story:check
passes
Yes
Accessibility
test:a11y
for shared/
Recommended
KnowledgeLearnings captured in vaultRecommended

Principle: If verification fails → task NOT complete.

Quick Reference

Commands:

ActionCommand
Start Storybook
just storybook
TypeScript check
npx tsc --noEmit
ESLint
npm run lint
ESLint fix
npm run lint:fix
Unit tests
npm run test:run
Story coverage
npm run story:check
A11y tests
npm run test:a11y

Related skills:

SkillWhen to use
/frontend
Architecture, state management
/storybook
Story templates, interaction tests
/design-tokens
Token API reference
/testing
Vitest, Playwright patterns

Example

User: "Create TopicCard component"

Claude follows frontend-flow:

1. [Session] /obsidian:journal session "TopicCard component"

2. [Discovery] BEFORE coding!
   → storybook_list_components → check existing cards
   → Found CardWithStatus — base structure exists!
   → /obsidian:search "card pattern" → found prior decisions

3. [Implementation]
   → Using @shared/tokens for colors
   → Using @shared/patterns/CardWithStatus as base
   → All icon buttons with aria-label
   → 44px touch targets

4. [Storybook]
   → TopicCard.stories.tsx with tags: ['autodocs']
   → 5 stories: Default, Empty, Loading, Error, WithBadge
   → storybook_capture_screenshot

5. [Verification] ALL must pass!
   → npx tsc --noEmit ✅
   → npm run lint ✅ (9 ESLint rules pass)
   → npm run test:run ✅
   → npm run story:check ✅
   → npm run test:a11y ✅

6. [Knowledge]
   → /obsidian:journal done
   → Findings: [[знання/паттерни/topic-card-composition]]
   → /obsidian:capture auto

Key: Verification runs COMPLETELY before task is considered done.