10 KiB
Project Development Guidelines
Version: 1.0
Last Updated: July 1, 2025
1. Introduction
This document provides the official guidelines for developing this application. Its purpose is to ensure a consistent, maintainable, and high-quality codebase. Adhering to these standards is mandatory for all contributors.
2. Project Structure
We use a feature-based structure to ensure modularity and scalability.
/
├── src/
│ ├── assets/
│ ├── components/ # Only for shared components (e.g., App Layout, Button)
│ ├── config/
│ ├── contexts/
│ ├── features/ # Main directory for all application features
│ │ ├── authentication/
│ │ │ ├── api/
│ │ │ │ └── authAPI.ts
│ │ │ ├── components/
│ │ │ │ └── LoginForm.tsx
│ │ │ ├── hooks/
│ │ │ │ └── useAuth.ts
│ │ │ ├── routes/
│ │ │ │ └── LoginPage.tsx # The main entry point for this feature's route
│ │ │ └── types.ts
│ │ │
│ │ └── products/
│ │ ├── api/
│ │ │ └── productsAPI.ts
│ │ ├── components/
│ │ │ ├── ProductCard.tsx
│ │ │ └── ProductGrid.tsx
│ │ ├── routes/
│ │ │ └── ProductListPage.tsx
│ │ └── index.ts
│ │
│ ├── hooks/ # Only for global hooks
│ ├── lib/ # For external library configurations (e.g., axios instance)
│ ├── providers/ # A single place for all context providers
│ ├── routes/ # Central route configuration
│ │ └── index.tsx
│ ├── types/ # Only for global types
│ ├── App.tsx
│ └── main.tsx
│
src/features/: All code related to a specific business feature (e.g.,authentication,products,user-profile) resides within its own folder here. Each feature folder should contain its owncomponents,hooks,api,types, androutes.src/components/: This directory is only for truly generic, shared UI components that are used across multiple features (e.g.,Button,Layout,Logo).src/lib/: For configuring and exporting instances of third-party libraries (e.g., anaxiosclient).src/providers/: A single location to compose all React Context providers (AuthProvider,ThemeProvider, etc.).src/routes/: The central routing configuration, which lazy-loads page components from thefeaturesdirectory.src/theme/: Contains the MUI theme definition and global styles.
3. Naming Conventions
Consistent naming is critical for readability.
-
Files:
- Components:
PascalCase.tsx(e.g.,ProductCard.tsx) - Hooks:
useCamelCase.ts(e.g.,useDebounce.ts) - All other
.tsfiles:camelCase.ts(e.g.,authService.ts)
- Components:
-
Components:
PascalCase. The component function name must match the filename.// src/components/SubmitButton.tsx function SubmitButton() { // ... } -
Variables and Functions:
camelCase.const userCount = 10; function getUserProfile() { /* ... */ } -
Constants:
UPPER_SNAKE_CASE. For constant values that are hardcoded and reused.const MAX_LOGIN_ATTEMPTS = 5; -
Types and Interfaces:
PascalCase.interface UserProfile { userId: string; displayName: string; }
4. Coding Best Practices
-
Functional Components: All components must be functional components using React Hooks. Class components are not permitted.
-
TypeScript: Use TypeScript's features to your advantage. Avoid
anywhenever possible. Define clear types and interfaces for props, API responses, and complex objects. -
Props: Always define props with a
typeorinterface. Use destructuring in the component signature for clarity.interface UserCardProps { name: string; avatarUrl: string; } function UserCard({ name, avatarUrl }: UserCardProps) { // ... } -
Imports: Use absolute paths with the
@/alias for cleaner imports. -
DRY (Don't Repeat Yourself): If you use a piece of logic more than twice, abstract it into a custom hook. If you use a piece of JSX more than twice, create a reusable component.
5. State Management
- Local State:
useStateanduseReducerare the default choices for component-level state. - Shared State: For state that needs to be shared across the application (e.g., user authentication, theme), use the React Context API.
6. Styling
Styling is handled by Material-UI (MUI).
- For creating new, reusable, styled components, use the
styled()utility from MUI. - For one-off style adjustments or layout overrides, use the
sxprop.
7. Component Documentation (Storybook)
All shared UI components in the src/components directory must be documented using Storybook. This creates a living style guide, allows for isolated component development, and makes it easy for all developers to discover and use existing components.
Each component folder should contain a *.stories.tsx file.
8. Code Comments
-
Comment the Why, Not the What: Your code should be self-documenting. Use comments to explain why a complex or non-obvious piece of code exists.
// Bad comment // Increment the counter counter++; // Good comment // We need to pre-increment the counter to account for the zero-based index of the array. ++preemptiveCounter; -
JSDoc: Use JSDoc blocks for all exported functions and custom hooks to enable better editor IntelliSense.
/** * Fetches a user profile from the API. * @param userId - The ID of the user to fetch. * @returns The user profile object or null if not found. */
9. Git Workflow
We use a simplified GitFlow model.
- Create a Branch: All work must be done on a feature branch, named descriptively (e.g.,
feat/login-page,fix/header-bug). - Commit Often: Make small, logical commits. Commit messages must follow the Conventional Commits specification (e.g.,
feat:,fix:,docs:,chore:). - Create a Pull Request (PR): When the feature is complete, create a PR against the
mainbranch. - Code Review: At least one other team member must review and approve the PR.
- Merge: Once approved and all checks pass, the PR can be merged.
10. Pre-Commit Checklist
Before creating a Pull Request, ensure you have:
- ✅ Formatted the entire codebase:
npm run format - ✅ Passed all linter checks:
npm run lint - ✅ Documented any new shared components in Storybook.
11. Design Patterns
Design patterns are reusable solutions to common problems within a given context. Here are the key patterns we will use in this React project.
Component Design Patterns
-
Container/Presentational Pattern (Smart/Dumb Components)
- Concept: Separate the "how things work" from the "how things look."
- Container (Smart) Component: Manages state, fetches data, and contains business logic. It doesn't have many styles.
- Presentational (Dumb) Component: Receives data via props and simply renders UI. It contains no business logic.
- Example: A
UserProfilePage(container) fetches user data and passes it to aUserProfileCard(presentational) to display.
-
Composition Pattern
- Concept: Build complex components by combining simpler, more generic ones. This is React's core philosophy.
- Example: Using the
childrenprop to create a genericCardcomponent that can wrap any content:
<Card> <h2>Title</h2> <p>Content</p> </Card>
State Management Patterns
- Provider Pattern
- Concept: Make data available to a deep tree of components without having to pass props down manually at every level.
- How we use it: This is the pattern that powers the React Context API. Our
AuthProvider,ThemeProvider, andCustomThemeProviderall use this pattern to provide authentication status and theme information to any component that needs it.
Reusable Logic Patterns
- Custom Hooks
- Concept: The modern, standard way to share stateful logic between components.
- How we use it: By extracting logic into a function whose name starts with
use(e.g.,useAuth,useTheme), we can reuse that logic in any component without repeating code. This is the preferred replacement for older patterns like HOCs and Render Props.
Memoization Pattern
-
Concept: A performance optimization technique to prevent unnecessary re-renders and expensive re-calculations by caching results. React provides three main tools for this.
-
Best For: Improving the performance of applications with complex components, large lists, or frequent state updates.
-
The Tools:
React.memo: A higher-order component that prevents a component from re-rendering if its props haven't changed.useMemo: A hook that caches the result of an expensive calculation. It only re-computes the value when its dependencies change.useCallback: A hook that caches a function definition. This is useful for preventing child components from re-rendering when you pass functions down as props.
Custom Data Fetching Hook
-
Concept: A custom hook that abstracts all the logic for fetching data from an API. It typically manages the loading, error, and data states internally.
-
Best For: Simplifying data fetching in your components, eliminating repetitive
useEffectlogic, and creating a consistent way to handle API requests across your app. -
How it looks: Components become much cleaner and focused on displaying the data.
function UserProfile({ userId }) { const { data: user, isLoading, error } = useFetch(`/api/users/${userId}`); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error fetching data!</div>; return <div>{user.name}</div>; }