← Back to list

react-project-structure
by SlavaMelanko
React SPA with a solid, well-designed architecture for a smooth user experience
⭐ 0🍴 0📅 Jan 25, 2026
SKILL.md
name: react-project-structure description: File and folder organization conventions for React + Vite + shadcn/ui projects. Use when creating new components, organizing files, deciding folder structure, naming files/folders, or reviewing project organization. Covers folder-per-component vs flat structure, naming conventions, barrel exports, internal elements, and form patterns.
React Project Structure Guidelines
Core Conventions
| Convention | Rule |
|---|---|
| Folder naming | lowercase = grouping folder, PascalCase = component folder |
| Exports | Named exports only (except ui/) |
| Export style | Inline export const for components; bottom exports for index.js and ui/ |
| Functions | Arrow functions (except ui/) |
| Imports | Use index.js barrel files |
| File naming | ComponentName.jsx (not just index.jsx) |
| Suffixes | Keep descriptive suffixes (LoginPrompt, ConfirmDialog) |
Folder vs Flat Decision
| Condition | Structure | Example |
|---|---|---|
Single .jsx file only | Flat in grouping folder OR standalone folder | prompts/LoginPrompt.jsx or Header/ |
| 2+ related files | Folder-per-component | DataTable/ with hooks, sub-components |
| Tests | __tests__/ in component or grouping folder | Header/__tests__/ or prompts/__tests__/ |
| Stories (single) | PascalCase matching component name | Header/Header.stories.jsx |
| Stories (group) | lowercase matching folder name | prompts/prompts.stories.jsx |
Internal Folder Naming
| Location | Internal folder | Purpose |
|---|---|---|
src/components/*/ | elements/ | Small atomic primitives (Label, Error) |
src/components/*/ | assets/ or domain | Static resources (flags/, icons/) |
src/pages/*/ | components/ | Shared pieces used by 2+ sibling pages |
src/pages/*/ | containers/ | Shared layout utilities for sibling pages |
Important: Only create components/ or containers/ folders in pages when
helpers are shared by multiple sibling pages. For single-page helpers, keep
files flat in the page folder.
Directory Structure
src/
├── components/ # Shared/reusable components
│ ├── Header/ # Standalone component (PascalCase at top level OK)
│ │ ├── index.js
│ │ ├── Header.jsx
│ │ ├── elements/
│ │ └── __tests__/ # Tests can live in component folder
│ ├── prompts/ # Grouping folder (flat structure)
│ │ ├── index.js
│ │ ├── LoginPrompt.jsx
│ │ ├── SignupPrompt.jsx
│ │ ├── elements/ # Internal primitives
│ │ └── __tests__/ # Or in grouping folder for multiple components
│ ├── dialogs/
│ │ ├── PricingSliderDialog/ # Complex → folder-per-component
│ │ │ ├── index.js
│ │ │ ├── PricingSliderDialog.jsx
│ │ │ ├── hooks/
│ │ │ └── elements/
│ │ └── ConfirmDialog.jsx # Simple → flat
│ ├── pricing/ # Mixed: flat files + nested folders OK
│ │ ├── index.js
│ │ ├── CustomPricingCard.jsx
│ │ ├── StandardPricingCard.jsx
│ │ ├── PricingSlider/ # Complex component gets folder
│ │ └── elements/
│ ├── LanguageDropdown/
│ │ ├── index.js
│ │ ├── LanguageDropdown.jsx
│ │ ├── flags/ # Domain-specific assets folder
│ │ └── elements/
│ ├── form/ # Form utilities pattern
│ │ ├── index.js
│ │ ├── FormController.jsx
│ │ ├── FormField.jsx
│ │ ├── elements/ # Shared primitives
│ │ └── containers/ # Layout utilities (not layouts/)
│ └── ui/ # shadcn/ui primitives ONLY
├── layouts/
├── pages/
│ ├── admin/Users/
│ │ ├── index.js
│ │ ├── UsersPage.jsx
│ │ └── Toolbar/ # Single-page helper → flat in page folder
│ ├── errors/ # Multiple pages sharing helpers
│ │ ├── General/
│ │ ├── Network/
│ │ ├── NotFound/
│ │ ├── components/ # Shared by all error pages
│ │ └── containers/ # Shared layout utilities
│ └── public/Pricing/
│ ├── index.js
│ ├── PricingPage.jsx
│ ├── EnterpriseTab.jsx # Single-page helpers → flat
│ └── StandardCards.jsx
└── hooks/ # Shared hooks
File Patterns
Export Style
| File type | Style | Example |
|---|---|---|
Component .jsx | Inline export | export const Button = () => { ... } |
Barrel index.js | Bottom re-export | export { Button } from './Button' |
ui/ components | Bottom default | export default function Button() { ... } |
index.js (barrel)
export { ComponentName } from './ComponentName'
ComponentName.jsx
export const ComponentName = ({ ...props }) => {
return (/* ... */)
}
When to Extract vs Inline
| Condition | Action |
|---|---|
| Few lines, single-file usage | Inline in same file |
| Used by 2+ sibling files | Extract to elements/ |
| Complex logic | Extract to elements/ |
Inline Helpers Example
// ProfileDialog.jsx
const Row = ({ children }) => (
<div className='flex items-center gap-2'>{children}</div>
)
export const ProfileDialog = ({ profile }) => {
/* ... */
}
Form Utilities Pattern
form/
├── index.js # Exports: FormController, FormField, FormRoot, FormFields
├── FormController.jsx # Wrapper for controlled inputs (Select, Switch)
├── FormField.jsx # Wrapper for native inputs (Input, Textarea)
├── elements/ # Shared primitives (Error, Label, FieldWrapper)
└── containers/ # Layout utilities (FormRoot, FormFields)
Use containers/ (not layouts/) to avoid confusion with page layouts.
src/components/ui/ Rules
- Reserved for shadcn/ui primitives only
- Install via
npx shadcn@latest add <component> - Uses regular functions + default exports (shadcn convention)
- Custom wrappers go in
src/components/, notui/
Import Examples
import { LoginPrompt, SignupPrompt } from '@/components/prompts'
import { PricingSliderDialog } from '@/components/dialogs'
import { Button, Card } from '@/components/ui'
import { FormController, FormRoot } from '@/components/form'
Score
Total Score
55/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon

