Sitemap
Nimmikrishnab

Nimmikrishnab

React Folder Structure & Clean Architecture

2 min readMar 11, 2026

--

As your React applications grow from simple counter buttons to full-scale platforms, the “everything in one folder” approach quickly becomes a nightmare. Implementing a Clean Architecture ensures your project remains searchable, scalable, and easy for new developers to join.

While React doesn’t enforce a specific structure, the industry has converged on a few “gold standard” patterns.

The Standard “Feature-Based” Structure

The most popular modern approach is to group files by feature (e.g., Auth, Profile, Cart) rather than by file type (e.g., all CSS in one folder, all JS in another).

A typical src directory looks like this:

  • assets/: Static files like images, fonts, and global SVGs.
  • components/: Shared, "dumb" UI components used across the whole app (Buttons, Inputs, Modals).
  • features/: The heart of the app. Each sub-folder (e.g., features/todo-list) contains its own logic, components, and styles.
  • hooks/: Global, reusable custom hooks (e.g., useAuth, useLocalStorage).
  • services/: API calls and external SDK configurations (Axios instances, Firebase config).
  • utils/: Pure helper functions (date formatting, currency conversion).
  • store/: Global state management files (Redux slices, Zustand stores, or Context providers).

Feature Folder

To keep a feature truly modular, treat the folder like a mini-application. This makes it easy to move or delete the entire feature later.

features/auth/
├── components/ # UI specific only to Auth (e.g., LoginForm)
├── hooks/ # Hooks specific to Auth (e.g., useLogin)
├── services/ # Auth API calls
├── types/ # TypeScript interfaces for Auth data
├── utils/ # Auth-specific logic
└── index.js # The "Public API" (exports only what the rest of the app needs)

Clean Architecture aims to separate Business Logic from UI Logic.

  • The Domain Layer (Entities): Pure logic and data structures. It doesn’t know React exists.
  • The Application Layer (Hooks/Services): This acts as the bridge. Hooks like useGetProducts handle the orchestration of data fetching.
  • The Presentation Layer (Components): These components just “consume” data and render UI. They shouldn’t contain complex math or API logic.

Why Use an index.js (Barrels)?

Using “Barrel files” allows you to import from a folder rather than a specific file. This keeps your import statements at the top of your files clean.

Get Nimmikrishnab’s stories in your inbox

Join Medium for free to get updates from this writer.

Without Barrels: import { Button } from '../../components/ui/Button/Button';

With Barrels: import { Button } from '@/components';

Absolute Imports and Aliases

Stop using “dot-dot-slash hell” (../../../). Configure your project (via jsconfig.json or tsconfig.json) to use Aliases.

{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

Now, you can simply write: import { UserProfile } from '@/features/user'; from anywhere in your app.

Summary

  • Keep it flat until it hurts; don’t over-engineer a small 3-page site.
  • Move to features once you have multiple distinct parts of the app.
  • Keep components small. If a component is over 100 lines, it’s probably doing too much.
  • Extract logic into hooks. If your component has 5 useState calls and 3 useEffect calls, move them to a custom hook.

--

--