Back to list
djimontyp

frontend-flow

by djimontyp

0🍴 0📅 Jan 11, 2026

SKILL.md


name: frontend-flow description: 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.

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
Iconslucide-reactheroicons, Radix icons
Touchh-11 w-11 (44px)h-9 w-9 (36px)
Spacinggap-2, gap-4, p-4gap-3, p-5 (off-grid)
Icon buttonsaria-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 primitiveshared/ui/Button, Dialog, Select
shadcn + customizeshared/ui/ (modify)Badge with new variant
Compositionshared/patterns/CardWithStatus, FormField
Business reusableshared/components/SearchBar, TopicSelector
Feature-specificfeatures/X/components/AtomCard, ProviderList
Page-specificpages/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
1no-raw-tailwind-colorsSemantic tokens only
2no-odd-spacing4px grid system
3no-heroiconslucide-react only
4no-raw-zindexNamed z-index tokens
5no-direct-fontsFont tokens only
6no-raw-page-wrapperPageWrapper required
7no-direct-api-importsService classes
8no-hardcoded-api-pathsAPI_ENDPOINTS config
9stories-require-autodocsAutodocs 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
TypeScripttsc --noEmit passesYes
ESLint9 Design System rules passYes
TestsUnit tests passYes
Story Coveragestory:check passesYes
Accessibilitytest:a11y for shared/Recommended
KnowledgeLearnings captured in vaultRecommended

Principle: If verification fails → task NOT complete.

Quick Reference

Commands:

ActionCommand
Start Storybookjust storybook
TypeScript checknpx tsc --noEmit
ESLintnpm run lint
ESLint fixnpm run lint:fix
Unit testsnpm run test:run
Story coveragenpm run story:check
A11y testsnpm run test:a11y

Related skills:

SkillWhen to use
/frontendArchitecture, state management
/storybookStory templates, interaction tests
/design-tokensToken API reference
/testingVitest, 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.

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon