|
| 1 | +--- |
| 2 | +name: "Frontend Component Structure Guidelines" |
| 3 | +description: "Use when creating, moving, or refactoring React components, Storybook stories, or frontend tests in frontend/src/. Covers the preferred elements/layout/ui/providers/app _components directory structure and colocated naming conventions." |
| 4 | +applyTo: |
| 5 | + - "frontend/src/**/*.ts" |
| 6 | + - "frontend/src/**/*.tsx" |
| 7 | +--- |
| 8 | + |
| 9 | +# Frontend Component Structure Guidelines |
| 10 | + |
| 11 | +- Avoid growing a flat `frontend/src/components/` directory. |
| 12 | +- Put app-owned presentational or interactive components that combine shadcn primitives with project-specific functionality in `frontend/src/components/elements/`. |
| 13 | +- Put shared structural components in `frontend/src/components/layout/`. |
| 14 | +- Keep `frontend/src/components/ui/` for shadcn components installed directly by `npx shadcn@latest add <component>`. |
| 15 | +- Put provider-style wrappers and context composition in `frontend/src/providers/`. |
| 16 | +- Put route-local components in `frontend/src/app/**/_components/` when they are only used by a single route. |
| 17 | +- Put route page tests beside the page or route-local component they cover within the same `frontend/src/app/**` directory. |
| 18 | +- For app-owned folders under `frontend/src/components/elements/`, `frontend/src/components/layout/`, `frontend/src/providers/`, and `frontend/src/app/**/_components/`, let the folder name carry the component or provider name and use `index.tsx`, `index.test.tsx`, and `index.stories.tsx` for colocated files. |
| 19 | +- Do not add barrel `index.ts` files inside those component or provider folders unless a task explicitly needs a separate module boundary. |
| 20 | +- Preserve shadcn's generated file naming and structure inside `frontend/src/components/ui/`; do not wrap those generated components in extra folders just to match the app-owned component pattern. |
| 21 | +- For new Storybook stories that use `tags: ["autodocs"]`, set `parameters.docs` to the shared compact docs helper in `frontend/src/lib/storybook-docs.tsx` so the Docs tab omits the default `Stories` block and uses the reduced primary canvas height. |
| 22 | + |
| 23 | +## Preferred Shapes |
| 24 | + |
| 25 | +Shared reusable component: |
| 26 | + |
| 27 | +```text |
| 28 | +frontend/src/components/elements/StatusBadge/ |
| 29 | + index.tsx |
| 30 | + index.stories.tsx |
| 31 | + index.test.tsx |
| 32 | +``` |
| 33 | + |
| 34 | +Shadcn-installed primitive: |
| 35 | + |
| 36 | +```text |
| 37 | +frontend/src/components/ui/button.tsx |
| 38 | +``` |
| 39 | + |
| 40 | +Shared provider: |
| 41 | + |
| 42 | +```text |
| 43 | +frontend/src/providers/ThemeProvider/ |
| 44 | + index.tsx |
| 45 | + index.test.tsx |
| 46 | +``` |
| 47 | + |
| 48 | +Route-local component: |
| 49 | + |
| 50 | +```text |
| 51 | +frontend/src/app/projects/[id]/_components/MemberInviteCard/ |
| 52 | + index.tsx |
| 53 | + index.stories.tsx |
| 54 | + index.test.tsx |
| 55 | +``` |
| 56 | + |
| 57 | +Route page with colocated test: |
| 58 | + |
| 59 | +```text |
| 60 | +frontend/src/app/admin/sources/ |
| 61 | + page.tsx |
| 62 | + page.test.tsx |
| 63 | +``` |
| 64 | + |
| 65 | +## Placement Heuristics |
| 66 | + |
| 67 | +- If the component is a shadcn primitive created by the CLI, keep it under `components/ui/` with the generated naming. |
| 68 | +- If the component is app-owned and composes shadcn primitives with project-specific behavior or presentation, place it under `components/elements/`. |
| 69 | +- If the component primarily arranges shared navigation or page chrome, place it under `components/layout/`. |
| 70 | +- If the module primarily provides context or wraps app trees with provider logic, place it under `providers/`. |
| 71 | +- If the component is only consumed by one route segment, keep it under that route's `_components/` folder instead of promoting it to `components/`. |
| 72 | +- Prefer folder-level naming over duplicate file naming. For example, prefer `OriginalContentIdeaCard/index.tsx` over `OriginalContentIdeaCard/OriginalContentIdeaCard.tsx`. |
| 73 | +- When extracting from a large page, prefer moving the smallest reusable visual leaves first, then larger feature sections, while keeping the page as the orchestration layer. |
| 74 | +- Prefer `*.test.tsx` files beside the owning page or component over `__tests__/` directories for new frontend tests. |
| 75 | + |
| 76 | +## Notes |
| 77 | + |
| 78 | +- Preserve the existing backend contract and keep frontend payloads in `snake_case`. |
| 79 | +- Follow the repo's colocated story convention for Storybook. |
| 80 | +- Reuse `frontend/src/lib/storybook-docs.tsx` for compact Docs tabs in new stories instead of re-declaring the same docs page JSX in each file. |
| 81 | +- Do not move files only to satisfy the structure guideline unless the current task already touches that area. |
0 commit comments