--- name: component-organization description: Maintain consistent file structure - components/ui for base shadcn, components/shared for composed components, pages for routes, always use barrel exports --- # Component Organization Guide This guide establishes the file structure and naming conventions for maintaining a consistent, scalable React TypeScript codebase. ## Directory Structure ``` src/ ├── assets/ # Static assets (images, icons, fonts) │ ├── icons/ │ └── images/ ├── components/ # Reusable components │ ├── ui/ # Base shadcn components (CLI-generated) │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── badge.tsx │ │ └── index.ts # Barrel export │ ├── shared/ # Composed app-specific components │ │ ├── UserProfileCard.tsx │ │ ├── DataTable.tsx │ │ └── index.ts # Barrel export │ └── index.ts # Root barrel export ├── pages/ # Top-level route components │ ├── Home.tsx │ ├── About.tsx │ ├── NotFound.tsx │ └── index.ts # Barrel export ├── layouts/ # Layout wrappers │ ├── MainLayout.tsx │ ├── DashboardLayout.tsx │ └── index.ts # Barrel export ├── features/ # Feature-based organization (optional) │ ├── authentication/ │ │ ├── components/ │ │ ├── hooks/ │ │ └── index.ts │ └── dashboard/ │ ├── components/ │ ├── hooks/ │ └── index.ts ├── hooks/ # Custom React hooks │ ├── useLocalStorage.ts │ └── index.ts # Barrel export ├── lib/ # Utilities and helpers │ └── utils.ts # cn() helper for Tailwind ├── services/ # API and external services │ ├── api.service.ts │ └── index.ts # Barrel export ├── constants/ # App-wide constants │ └── index.ts # APP_NAME, ROUTES, etc. ├── types/ # TypeScript type definitions │ ├── api.types.ts │ ├── common.types.ts │ └── index.ts # Barrel export └── utils/ # Pure utility functions └── index.ts ``` ## Directory Purposes ### `components/ui/` **Purpose**: Base shadcn/ui components generated via CLI - **DO**: Add new components using `npx shadcn@latest add [component]` - **DO**: Keep these components pure and unopinionated - **DON'T**: Modify these files directly (regenerate if needed) - **DON'T**: Add business logic here **Example**: ```tsx // components/ui/button.tsx (generated by shadcn CLI) import * as React from "react" import { cn } from "@/lib/utils" const Button = React.forwardRef( ({ className, variant, size, ...props }, ref) => { return ( ); } ``` ### Domain Logic: App-Specific Behavior When adding business logic, API calls, or state management, extract to a component. ```tsx // components/shared/ProductList.tsx - Contains domain logic import { useEffect, useState } from 'react'; import { fetchProducts } from '@/services/api.service'; import { Card } from '@/components/ui/card'; export function ProductList() { const [products, setProducts] = useState([]); useEffect(() => { fetchProducts().then(setProducts); }, []); return (
{products.map(product => ( {/* Product display */} ))}
); } ``` ## Real-World Examples from This Project ### Example 1: UI Component Barrel Export ```ts // src/components/ui/index.ts export { Button } from './button'; export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent, } from './card'; export { Badge } from './badge'; export { Separator } from './separator'; ``` ### Example 2: Page Component with Feature Imports ```tsx // src/pages/Home.tsx import { Card, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { APP_NAME } from '@/constants'; export function Home() { // Page orchestrates UI components return (

{APP_NAME}

{/* Feature showcase using composed components */}
); } ``` ### Example 3: Layout with Router Integration ```tsx // src/layouts/MainLayout.tsx import { Link, Outlet, useLocation } from 'react-router-dom'; export function MainLayout() { const location = useLocation(); return (
{/* Pages render here */}
); } ``` ### Example 4: Constants with Type Safety ```ts // src/constants/index.ts export const APP_NAME = 'Vite React TypeScript Boilerplate'; export const ROUTES = { HOME: '/', ABOUT: '/about', NOT_FOUND: '*', } as const; // Usage in pages import { ROUTES } from '@/constants'; Home ``` ## Quick Reference Checklist - [ ] Created barrel export `index.ts` for new directory? - [ ] Used PascalCase for component files and exports? - [ ] Used kebab-case for directory names? - [ ] Added shadcn components via CLI to `components/ui/`? - [ ] Placed composed components in `components/shared/`? - [ ] Put route components in `pages/` directory? - [ ] Exported layouts from `layouts/` directory? - [ ] Used SCREAMING_SNAKE_CASE for constants? - [ ] Added TypeScript types for component props? - [ ] Verified component is reused 2+ times before creating? - [ ] Extracted complex logic (>50 lines) to separate component? - [ ] Used `@/` path alias for imports? ## Anti-Patterns to Avoid **DON'T modify shadcn UI components directly**: ```tsx // ❌ Bad: Editing ui/button.tsx manually // If you need customization, create a wrapper in shared/ ``` **DON'T skip barrel exports**: ```tsx // ❌ Bad: Direct imports without barrel import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; // ✅ Good: Use barrel exports import { Button, Card } from '@/components/ui'; ``` **DON'T create one-off components in shared/**: ```tsx // ❌ Bad: Single-use component in shared/ // components/shared/HomepageHeroSection.tsx (only used once) // ✅ Good: Keep in the page or feature // pages/Home.tsx (inline) or features/homepage/components/ ``` **DON'T mix concerns in constants**: ```tsx // ❌ Bad: Mixing types and runtime values export const ENDPOINTS = { users: '/api/users', auth: '/api/auth', }; export type User = { id: string; name: string }; // ✅ Good: Separate constants and types // constants/index.ts - runtime values // types/index.ts - type definitions ``` --- **Remember**: Good organization makes scaling easy. When in doubt, follow the principle: "Start simple, extract when you repeat."