Awesome-omni-skill React Frontend Architecture
Comprehensive guidelines and standards for building scalable React applications, including project structure, component design, state management, and styling.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/react-frontend-architecture" ~/.claude/skills/diegosouzapw-awesome-omni-skill-react-frontend-architecture && rm -rf "$T"
manifest:
skills/development/react-frontend-architecture/SKILL.mdsource content
React Frontend Architecture Guide
This skill provides the architectural foundation for React applications in this project. It is designed to ensure maintainability, scalability, and strict separation of concerns.
1. Project Structure
Organize the
src directory as follows. We strictly follow a Features-First (Domain-Driven) organization approach.
src/ ├── app/ # Next.js App Router pages (if using App Router) ├── assets/ # Static assets (images, fonts, global styles) ├── components/ # Shared "Dumb" UI components (Buttons, Inputs, Modals) │ ├── ui/ # Atomic UI elements │ └── layout/ # Structural components (Header, Footer, Sidebar) ├── features/ # Business Logic & Complex Features │ └── [feature]/ # e.g., 'auth', 'dashboard', 'user-profile' │ ├── components/ # Components specific to this feature │ ├── hooks/ # Hooks specific to this feature │ ├── api/ # API calls/services specific to this feature │ └── types/ # Types specific to this feature ├── hooks/ # Global/Shared custom hooks (useDebounce, useOnClickOutside) ├── lib/ # Third-party library configurations (Axios instance, queryClient) ├── services/ # Global API definitions (if not using feature-based) ├── store/ # Global State Store (Zustand/Redux) ├── utils/ # Pure helper functions (formatDate, currency helpers) └── types/ # Global TypeScript definitions
2. Component Architecture: The MVC Pattern
We adhere to a strict Separation of Concerns using a ViewModel-like pattern. Rule: UI Components should contain zero business logic.
2.1 File Structure
Each component is a directory. The structure is non-negotiable for "Smart" (Logic-heavy) components.
MyComponent/ ├── MyComponent.tsx # View (Template) ├── MyComponent.hook.ts # Logic (ViewModel) ├── MyComponent.type.ts # Type Definitions ├── MyComponent.css # Styles (CSS Modules preferred) ├── index.ts # Export Interface └── components/ # (Optional) Internal sub-components
2.2 Roles & Responsibilities
[Name].tsx
- The View
[Name].tsx- Role: Pure Function of Props/State.
- Responsibility: Rendering JSX, binding events to handlers.
- Constraints:
- No
allowed (unless purely UI related like animations).useEffect - No complex calculations.
- Must call
hook to get its state/handlers.use[Name]
- No
[Name].hook.ts
- The Logic (ViewModel)
[Name].hook.ts- Role: The Brain.
- Responsibility:
- Manage local state (
,useState
).useReducer - Handle side effects (
).useEffect - Fetch data (consume
or services).useQuery - Process Logic: Formatting dates, calculating derived values, mapping data structures.
- Return a neat interface (
) for the View.interface Use[Name]Result
- Manage local state (
- Goal: The
file should be reduced to a purely declarative template. If you find yourself writing a.tsx
,map
, orfilter
in thenew Date()
file, consider if it belongs in the hook..tsx
[Name].type.ts
- The Type Definitions
[Name].type.ts- Role: Type Safety & Contract.
- Responsibility:
- Define all TypeScript interfaces/types specific to this component.
- Separate API response types, component props, and internal state types.
- Export types for external consumers (via
).index.ts
- Why Separate:
- Keeps hook and view files focused on logic and rendering.
- Makes types easier to import and reuse across features.
- Improves testability by isolating type definitions.
- Naming: Use descriptive names with component prefix (e.g.,
,MyComponentProps
).MyComponentState
api/*.ts
- The Service Layer
api/*.ts- Role: Data Access.
- Responsibility:
- Knows HTTP implementation details (GET/POST endpoints).
- Returns Promises of typed data.
- Never contains UI state logic.
2.3 Implementation Example
MyComponent.type.ts
// Component Props export interface MyComponentProps { initialCount?: number; } // State Shape export interface MyComponentState { count: number; isSubmitting: boolean; } // Action Handlers export interface MyComponentActions { increment: () => void; submit: () => Promise<void>; } // Hook Return Interface export interface UseMyComponentResult { state: MyComponentState; actions: MyComponentActions; } // API Request/Response Types export interface SubmitDataRequest { count: number; } export interface SubmitDataResponse { success: boolean; timestamp: string; }
MyComponent.hook.ts
import { useState, useCallback } from 'react'; import { useSubmitData } from './api/useSubmitData'; import type { MyComponentProps, MyComponentState, MyComponentActions, UseMyComponentResult, SubmitDataRequest } from './MyComponent.type'; export const useMyComponent = ({ initialCount = 0 }: MyComponentProps): UseMyComponentResult => { const [count, setCount] = useState(initialCount); const mutation = useSubmitData(); const increment = useCallback(() => setCount(c => c + 1), []); const submit = async () => { const request: SubmitDataRequest = { count }; try { await mutation.mutateAsync(request); } catch (error) { console.error(error); } }; return { state: { count, isSubmitting: mutation.isLoading }, actions: { increment, submit } }; };
MyComponent.tsx
import React from 'react'; import styles from './MyComponent.module.css'; import { useMyComponent } from './MyComponent.hook'; import type { MyComponentProps } from './MyComponent.type'; export const MyComponent: React.FC<MyComponentProps> = (props) => { const { state, actions } = useMyComponent(props); return ( <div className={styles.container}> <h1>Count: {state.count}</h1> <button onClick={actions.increment} disabled={state.isSubmitting}> Increment </button> <button onClick={actions.submit}> {state.isSubmitting ? 'Saving...' : 'Save'} </button> </div> ); };
3. Naming Conventions (Strict)
Consistency is key to preventing code rot.
- Directories:
- Components/Pages:
(e.g.,PascalCase
,UserProfile
).EditButton - Utilities/Hooks/Libs:
(e.g.,camelCase
,utils
).hooks
- Components/Pages:
- Files:
- React Components:
(e.g.,PascalCase.tsx
).UserProfile.tsx - Hooks:
prefix +use
(e.g.,camelCase.ts
).useUserProfile.ts - Logic Files:
.[Component].hook.ts - Type Files:
.[Component].type.ts - Utilities:
(e.g.,camelCase.ts
).formatDate.ts - Styles:
(preferred for scoping).[Component].module.css
- React Components:
- Variables/Functions:
- Boolean props/vars:
,is
,has
prefix (e.g.,should
,isLoading
).hasError - Handlers:
prefix (e.g.,handle
,handleSubmit
).handleInputChange - Props passing handlers:
prefix (e.g.,on
,onClick
).onSubmit
- Boolean props/vars:
4. Next.js Specific Guidelines
- Client vs Server Components:
- The
pattern is specifically for Client Components (*.hook.ts
).'use client' - Server Components (RSC) should be used for initial data fetching where appropriate to reduce client JS bundles.
- Boundary: Keep RSC at the "Page" level and pass data down to "Smart" Client components.
- The
5. CSS & Styling Architecture
- Avoid Global CSS: Only use
for resets and root variables.globals.css - Z-Index Management: Define z-indices in a global variable map or strictly in CSS variables to avoid stacking context wars.
- Design System: Reusable values (colors, spacing) MUST come from CSS variables or Tailwind utility classes. Do not use magic hex codes in component files.