Use when refactoring frontend sections with 20+ files, deciding where new components belong, or organizing React codebases - provides file structure standards based on complexity tiers (flat, tab-based, hook-based, feature-module patterns) matching metrics/vulnerabilities gold standards
Standardized file and directory organization patterns for React frontend sections. Prevents the "where does this file go?" problem by providing clear structure based on section complexity (file count and feature depth).
Core Principle: Structure should match complexity. Simple features stay flat. Complex features get organized hierarchies. Let file count and feature independence drive organization decisions.
Standards for organizing code within files (complements directory organization above). Ensures consistency in import order, file length, and component internal structure.
For detailed code structure patterns, see Code Structure Standards:
Quick Reference:
| Aspect | Standard | Example |
|---|---|---|
| Import groups | 4 groups with blank lines | React → UI → Utils → Types |
| Component limit | 300 lines (hard) | Extract hooks at 200 lines |
| Function limit | 30 lines (hard) | Break into subfunctions |
| Hook limit | 50 lines (hard) | Split by concern |
| Hook order | Specific sequence | Global → API → Local → Computed → Effects |
Use when:
Symptoms this addresses:
Don't use when:
🚨 MANDATORY: You MUST use TodoWrite before starting to track all refactoring steps and organizational decisions. This skill has 17 sections with multiple decision points - mental tracking will cause missed steps.
Structure:
section/
├── index.tsx
├── ComponentA.tsx
├── ComponentB.tsx
├── hooks.ts
├── types.ts
└── utils.ts
When: Simple features, minimal state, few components Example: Small utility sections, simple dashboards
Structure:
section/
├── index.tsx (orchestration)
├── tabs/
│ ├── Tab1.tsx
│ ├── Tab2.tsx
│ └── Tab3.tsx
├── components/
│ ├── primitives/ # Shared UI building blocks
│ ├── forms/ # Form components (3+ threshold)
│ ├── modals/ # Modal dialogs (3+ threshold)
│ └── index.ts
├── hooks/
│ └── index.ts
├── types.ts
└── constants.ts
When: Features with clear tab/mode separation Example: Settings section (after refactoring) Key Pattern: Organize components by purpose when hitting thresholds
Structure:
section/
├── index.tsx (< 300 lines via hook extraction)
├── types/
│ ├── domain1.types.ts
│ ├── domain2.types.ts
│ └── index.ts
├── config/
│ ├── columns.ts
│ ├── filters.ts
│ └── index.ts
├── hooks/
│ ├── useMainFeature.ts
│ ├── actions/ # Specialized hooks
│ │ └── useActions.ts
│ └── index.ts
├── utils/
│ ├── domain1.util.ts
│ └── index.ts
└── components/
├── cells/ # Table cells (5+ threshold)
├── modals/ # Modals (3+ threshold)
├── actions/ # Toolbars (2+ threshold)
└── index.ts
When: Data-intensive features with complex business logic Example: Vulnerabilities section Key Pattern: Extract business logic to hooks, organize components by UI pattern
Structure:
section/
├── index.tsx (lightweight orchestration)
├── types/, config/, constants/, hooks/, utils/ # Foundation
├── components/
│ ├── shared/ # Section-wide components
│ └── modals/
└── features/ # Self-contained feature modules
├── feature1/
│ ├── index.tsx
│ ├── components/
│ ├── hooks/
│ ├── types.ts
│ └── constants.ts
├── feature2/
└── index.ts
When: Multiple independent sub-features, high complexity Example: Metrics section (widgets are features) Key Pattern: Each feature is self-contained module with own organization
How many files in /components/?
├─ < 5 files → Keep flat ✅
├─ 5-10 files → Watch for growth ⚠️
└─ 10+ files → Organize by type ❌
Which component type has 3+ files?
├─ 3+ modals → Create /modals/
├─ 3+ forms → Create /forms/
├─ 3+ cards → Create /cards/
├─ 5+ cells → Create /cells/
└─ All types < threshold → Keep flat
✅ components/ # Plural, lowercase
✅ types/ # Plural, lowercase
✅ subscription/ # Singular feature, lowercase
❌ component/ # Not plural
❌ Components/ # Not lowercase
✅ StatusCell.tsx # PascalCase
✅ useVulnerabilityFilters.ts # camelCase + use prefix
✅ vulnerability.types.ts # camelCase + .types suffix
✅ ScanSettingsTab.tsx # Tab suffix
❌ status-cell.tsx # Not kebab-case
❌ types.ts # Too generic
❌ ScanSettings.tsx # Missing Tab suffix
| Suffix | Usage |
|---|---|
Tab | Tab components |
Cell | Table cells |
Modal | Modal dialogs |
Form | Forms |
Card | Card components |
When to create component subdirectories:
| Subdirectory | Threshold | Purpose |
|---|---|---|
tabs/ | 3+ tab components | Tab panel components |
cells/ | 5+ cell renderers | Table cell components |
modals/ | 3+ modals | Modal dialogs |
forms/ | 3+ forms | Form components |
cards/ | 4+ cards | Card components |
primitives/ | 5+ reusable primitives | Base building blocks |
Feature subdirectory threshold: 5+ related files AND logically independent
Trigger: Section grows to 20+ files OR adds 3+ tabs
Actions:
/tabs/ directory/components/ if not existsTrigger: Main index.tsx > 300 lines OR complex business logic
Actions:
/hooks/ directory/types/ directory for domain-specific typesTrigger: Section has 80+ files OR 3+ independent features
Actions:
/features/ or domain-specific directoriesLevel 1: Section-Scoped
sections/[name]/components/Level 2: Multi-Section Shared
sections/components/Level 3: Design System
@praetorian-chariot/uiNever mix levels in same directory.
Co-locate tests with code:
components/
├── ComponentA.tsx
└── __tests__/
└── ComponentA.test.tsx
hooks/
├── useFeature.ts
└── __tests__/
└── useFeature.test.tsx
Section-level tests:
section/
└── __tests__/
├── integration.test.tsx
├── fixtures/
└── mocks/
Current (Poor Organization):
settings/
├── components/ (21 mixed files) ❌
└── 10 orphaned root files ❌
Target (Tier 2 Organized):
settings/
├── tabs/
├── components/
│ ├── primitives/
│ ├── cards/
│ ├── forms/
│ ├── modals/
│ ├── sections/
│ └── integrations/
├── subscription/ (feature)
├── constants.ts
└── types.ts
Creating /modals/ with only 1-2 modals. Wait for threshold (3+).
types.ts instead of vulnerability.types.ts. Use domain prefixes.
Organizing 15-file section with Tier 4 feature modules. Use simplest tier that fits.
Section-specific and multi-section shared in same directory. Separate by reusability level.
Going 5+ levels deep. Stop at 3-4 levels maximum.
metrics/ (Tier 4: Feature Module)
├── index.tsx (162 lines - lightweight)
├── types/, config/, constants/, hooks/, utils/
├── components/
│ └── modals/
└── widgets/ (features)
├── assets/, remediation/, vulnerabilities/
Why it works:
Apply this pattern when your section reaches 80+ files with independent features.
Maximum depth: 3-4 levels
✅ GOOD (3 levels):
section/components/modals/[files]
⚠️ ACCEPTABLE (4 levels):
section/features/feature1/components/[files]
❌ TOO DEEP (5+ levels):
section/features/feature1/components/cards/[files]
When hitting max depth: Extract feature to root or flatten hierarchy.
| Directory | Warning | Action |
|---|---|---|
| Section root | 15+ files | Create subdirectories |
components/ root | 10+ files | Organize by type |
hooks/ root | 15+ files | Create specialized subdirs |
| Any subdirectory | 20+ files | Split by domain or extract feature |
All sections should have:
Consistency enables:
Structure follows complexity. Start simple (Tier 1), evolve as needed (Tier 2→3→4). Use file count thresholds to trigger organization improvements. Follow metrics/vulnerabilities patterns for complex sections.
Gold Standards: