React Feature Architecture
Organizes React features around cohesive components, hooks, and domain specific modules.
Scenario
You have a growing React application organized by business feature rather than by technical file type.
The application contains features such as:
- users;
- billing;
- projects;
- notifications.
Each feature owns its components, hooks, API functions, and types.
The team wants coding agents to extend existing feature boundaries instead of gradually turning the application into global components, hooks, and services directories.
Repository Structure
web-app/
├── src/
│ ├── features/
│ │ ├── users/
│ │ │ ├── api/
│ │ │ ├── components/
│ │ │ ├── hooks/
│ │ │ └── types.ts
│ │ ├── billing/
│ │ └── projects/
│ ├── shared/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── utils/
│ └── app.tsx
├── tests/
└── AGENTS.md
AGENTS.md
# Project Instructions
## Feature Architecture
- Keep feature-specific code under `src/features/<feature>`.
- Add new code to an existing feature when that feature owns the behavior.
- Do not create new top-level source directories when an existing feature or shared area is appropriate.
## Feature Ownership
- Keep feature-specific components, hooks, API functions, and types inside the owning feature.
- Do not import another feature's internal modules directly.
- Use its public exports when cross-feature access is required.
## Shared Code
- Use `src/shared` only for code genuinely reused across multiple features.
- Do not move code into `shared` solely to avoid a feature dependency.
- Keep product-specific business rules inside their owning feature.
## React
- Follow existing component and hook patterns within the feature being modified.
- Prefer composition over duplicating similar components across features.
## Validation
- Run tests relevant to affected features.
- Run `pnpm lint` and `pnpm typecheck` before completing source changes.
What This Does
This tells the agent that the primary organizational unit is a business feature.
Instead of organizing everything globally:
components/
hooks/
services/
types/
the repository groups related behavior:
features/
├── users/
├── billing/
└── projects/
If a new billing hook is needed, the natural location is:
src/features/billing/hooks/
not a global hooks directory.
What This Does NOT Do
This does not prohibit shared code.
For example, a generic button used throughout the application can reasonably live under:
src/shared/components/
The important question is whether the code is truly application-wide.
A component such as:
BillingPlanSelector
should not automatically move to shared merely because two billing screens use it.
It still belongs to the billing domain.
The instructions also do not prescribe an identical internal structure for every feature.
A simple feature may not need:
api/
components/
hooks/
types/
all at once.
Why These Instructions Matter
Feature architectures can slowly deteriorate when developers solve each task locally.
Suppose a developer needs a hook for project permissions.
Creating:
src/hooks/use-project-permissions.ts
works.
Later another developer creates:
src/services/project-service.ts
Eventually, project behavior is scattered across the repository.
The instruction:
- Keep feature-specific code under `src/features/<feature>`.
gives the agent a default ownership model.
Another common problem is overusing shared.
If every potentially reusable function moves there, the directory becomes a collection of unrelated code with unclear ownership.
That is why the file says:
- Use `src/shared` only for code genuinely reused across multiple features.
Key Decisions
Organize around ownership
Ask:
Which feature owns this behavior?
before asking:
What type of file is this?
This keeps related code closer together.
Shared is not a staging area
Code should not move to shared simply because its future ownership is uncertain.
Keep it close to its current owner until genuine reuse exists.
Preserve feature boundaries
Direct imports from another feature's internals create hidden coupling.
Public exports provide a deliberate integration point.
Follow local patterns
If the users feature already has an established organization, an agent should inspect and extend that pattern before introducing a new one.
When to Use This Pattern
Use this pattern when:
- a React application has several business domains;
- features contain more than a few files;
- global technical directories are becoming difficult to navigate;
- ownership boundaries matter;
- multiple developers or agents work on different areas.
For very small applications, this structure may be unnecessary. Introduce feature architecture when the complexity justifies it.