Purpose: Complete guide to Metarr's React frontend - architecture, components, styling, and development guidelines.
For: Developers (human and AI) building or maintaining the Metarr frontend.
New to the codebase? Start here:
- Architecture Overview - Understand the tech stack
- Component Guidelines - Learn when/how to create components
- Styling System - Master the design system
Need to find something?
- "Where do I put this component?" → Component Guidelines
- "Does a component exist for X?" → Component Reference
- "How do I style this?" → Styling Guide
- "How do I fetch data?" → State Management
| Document | Purpose | When to Read |
|---|---|---|
| Component Guidelines | When to create components, file organization, composition patterns | Before creating ANY component |
| Component Reference | Complete inventory of all custom components | Before creating a new component (avoid duplication) |
| Styling Guide | Design tokens, shadcn integration, utility classes | Before writing any styles |
| Architecture | Tech stack, build system, data flow | Understanding the big picture |
| Document | Purpose | When to Read |
|---|---|---|
| State Management | TanStack Query, WebSocket, caching | Working with server state |
| API Layer | API client, request handling, error management | Adding API calls |
| Error Handling | Error boundaries, user feedback, recovery | Implementing error states |
Core:
- React 18 - Functional components with hooks
- TypeScript 5 - Strict typing, no
any - Vite 5 - Fast dev server and optimized builds
Styling:
- Tailwind CSS v4 - Utility-first styling
- shadcn/ui - Pre-built component primitives
- Custom Components - Domain-specific reusable components
State Management:
- TanStack Query - Server state (API data, caching)
- React Hooks - Local UI state (useState, useReducer)
- WebSocket - Real-time updates
Key Principles:
- Component-Based - Reusable components when patterns appear 2+ times
- Type-Safe - Full TypeScript coverage, strict mode
- DRY - Single source of truth for styles, logic, and data
- Industry Standards - Follow React, TypeScript, and Tailwind best practices
See Architecture for complete details.
shadcn/ui primitives (Button, Card, Input)
↓
Custom UI components (PageContainer, SettingCard, EmptyState)
↓
Domain components (MovieCard, ProviderCard, LibraryCard)
↓
Pages (Dashboard, Movies, Settings)
Create a new component when:
- Pattern appears 2+ times - Eliminate duplication
- Component exceeds 200 lines - Break into smaller pieces
- Logic is reusable - Extract for use elsewhere
DO NOT create a component when:
- Used only once - Keep inline unless complex
- Tightly coupled to parent - Keep as local implementation
- Already exists - Check Component Reference first!
Checklist:
- Search Component Reference - does it already exist?
- Check if existing component can be extended/modified
- Verify pattern appears 2+ times (or is complex enough to warrant extraction)
- Read Component Guidelines for structure
See Component Guidelines for complete rules.
Three Layers:
- Design Tokens - CSS variables (
--color-primary-500,--spacing-card) - Utility Classes - Semantic classes (
.section-header-title,.text-muted) - Components - Reusable components (PageContainer, SettingCard)
Key Concepts:
- shadcn Semantics - Use
text-muted-foreground,bg-cardfor theme-aware colors - Explicit Colors - Use
bg-neutral-800,border-neutral-700for structural elements - No Inline Tailwind - Use utility classes and components (DRY principle)
Text Colors:
- Primary text:
text-foreground - Secondary text:
text-muted-foreground - Explicit gray:
text-neutral-400(when semantic doesn't fit)
Surfaces:
- Page background:
bg-background - Card background:
bg-cardorbg-neutral-800 - Elevated surface:
bg-neutral-800/50
Spacing:
- Section spacing:
section-stack(space-y-6) - Compact spacing:
section-stack-compact(space-y-3) - Page padding:
page-container(pt-16 pb-24)
See Styling Guide for complete patterns.
- Check routing - Ensure route exists in
App.tsx - Use PageContainer - Wrap page with
<PageContainer title="..." subtitle="..."> - Follow patterns - Use SectionStack, SettingCard, DataCard as appropriate
- Apply utility classes - Use semantic colors, spacing utilities
Example:
import { PageContainer } from '@/components/ui/PageContainer';
import { SectionStack } from '@/components/ui/SectionStack';
export const MyPage = () => (
<PageContainer title="My Page" subtitle="Page description">
<SectionStack>
{/* Page content */}
</SectionStack>
</PageContainer>
);- Plan component structure - Identify reusable vs. feature-specific components
- Check existing components - Review Component Reference
- Create types first - Define TypeScript interfaces
- Implement incrementally - Build, test, refine
- Update documentation - Add to Component Reference if reusable
- Use existing components - Check if PageContainer, SettingCard, etc. fit
- Apply utility classes - Use
section-header-title,text-muted-foreground, etc. - Use shadcn semantics - Prefer semantic colors over explicit
- Create utility if 2+ uses - Add to
globals.css@layer components - Create component if 2+ uses - Extract to
components/ui/
- Read relevant docs - Review Component/Styling guides
- Check existing patterns - Avoid reinventing the wheel
- Follow file organization - Place files in correct directories
- Type everything - No
anytypes - Test incrementally - Verify TypeScript and build after changes
- TypeScript compiles (
npm run typecheck) - ESLint passes (
npm run lint) - Frontend builds (
npm run build:frontend) - No new code duplication (DRY)
- Consistent with styling guide
- Documentation updated if needed
For AI assistants working on this codebase:
- ALWAYS read Component Reference first
- Check if component exists - Search for similar patterns
- Consider extending existing - Can we modify an existing component?
- Follow 2+ rule - Only create if pattern appears twice or is very complex
- Read Component Guidelines - File structure, naming
- Create directory -
components/[domain]/[ComponentName]/ - Create files -
index.tsx,ComponentName.tsx,types.ts - Update reference - Add to Component Reference
- Read Styling Guide first
- Use shadcn semantics -
text-muted-foreground,bg-card, etc. - Use existing utilities - Check globals.css @layer components
- Create utility if 2+ uses - Add to globals.css with clear comment
When to update:
- New component created → Update Component Reference
- Styling pattern changed → Update Styling Guide
- Architecture changed → Update Architecture doc
- New guideline established → Update relevant doc
Decision Tree:
- Is it reusable across domains? →
components/ui/ - Is it domain-specific? →
components/[domain]/ - Is it page-specific and not reusable? → Keep inline in page
Decision Tree:
- Does a component exist? → Use it (Component Reference)
- Is there a utility class? → Use it (check globals.css)
- Do I need this 2+ times? → Create utility or component
- One-time use? → Use Tailwind utilities inline
Checklist:
- Run
npm run typecheck- Fix TypeScript errors - Run
npm run lint- Fix ESLint errors - Check imports - Ensure all imports resolve correctly
- Check component structure - Verify barrel exports (index.tsx)
- DRY Principle - Link to other docs, don't duplicate
- Guidelines, Not Examples - Explain rules, not implementations
- Clear Navigation - Use tables, links, decision trees
- AI-Friendly - Write for both humans and AI agents
- Check if doc exists - Avoid duplication
- Update README - Add to relevant table
- Follow structure - Purpose, Quick Reference, Content, Related Docs
- Link bidirectionally - Update related docs to link back
- Project Root README - Project overview
- Development Workflow - Git, commits, testing
- Backend Architecture - Server-side documentation