Whether you are building a single-page app with Vite, server-rendering with Next.js 15, or shipping mobile experiences through Expo, the way you organize files inside your React project will shape how fast your team moves six months from now. This article walks through react folder structure best practices that scale from a weekend MVP to an enterprise-grade platform, covering core principles, concrete folder layouts, and migration strategies drawn from real client work at TVL IT Solutions.
React does not enforce a strict folder structure. That freedom is a double-edged sword. Small prototypes feel effortless, but once a codebase crosses thirty or forty components, a missing organizational strategy turns every pull request into an archaeology expedition.
The pain is real. In a 2023 ecommerce engagement, TVL IT Solutions inherited a react project with over two hundred components stuffed inside a flat /components directory, no feature boundaries, and hooks scattered across a dozen unrelated folders. Onboarding a new developer took nearly a week just to understand where things lived.
Modern ecosystems compound the challenge. Next.js 15 introduces enhanced server components and app directories, Vite encourages rapid iteration, and Expo apps must work across platforms. A scalable folder structure aids maintainability and developer collaboration regardless of which tool you choose.
The src folder contains all React application code, yet how you subdivide it determines whether your project grows gracefully or collapses under its own weight. Two ideas recur throughout this post: organize around feature folders grouped by domain, and enforce clear boundaries between shared, app, and feature code.
Before choosing folder names, internalize the principles that make any project structure work over time.
Feature-based structure promotes higher code cohesion. Instead of scattering a feature’s UI, hooks, services, and types across top level folders like /components, /hooks, and /services, group them together. The two common approaches are grouping by file type and grouping by feature-for medium-to-large react apps, grouping by feature keeps related code localized and easier to reason about.
Keep cognitive load low. A new developer should understand the layout in under ten minutes. Avoid nesting component folders more than two levels deep. A flat structure is generally easier to maintain than a deeply nested one.
Enforce one-way dependencies. Code flows from shared utilities into features and from features into pages. Features should not import from each other to maintain independence. This prevents circular coupling and makes deletion or replacement of any feature safe.
Developers should start with a simple layout and evolve as their application grows. Premature abstractions create coupling that slows you down later. Keep files as close as possible to where they are used, and extract to shared only when reuse is proven.
At TVL IT Solutions, these principles guide every scalable architecture engagement-from SaaS platforms to AI dashboards and B2B products.
Most modern react applications converge on a similar top-level shape regardless of framework. Here is a concrete base layout:
my-project/
public/
src/
app/
features/
shared/
config/
styles/
types/
tests/ (optional)
A public folder holds static files like index.html and images that are served as-is. The app folder is the application shell: routing, providers, and root layouts. The features directory contains all domain-specific code, each feature in its own subfolder. The shared directory houses reusable components, hooks, and utilities that are feature-agnostic.
Other folders round out the picture. Config stores environment settings and API endpoints. Styles holds global CSS, theme variables, and resets. Types contains app-wide TypeScript interfaces. Tests is optional because many teams prefer colocating test files next to the code they verify.
This structure works for both greenfield projects and refactors. As the project grows, it can evolve into a monorepo with apps/ and packages/ directories. Folder names may shift slightly by framework-Next.js uses app/ for file-based routing while Vite projects typically use src/app.tsx-but the main concepts remain identical.
The app folder is the shell of your React application. Routing definitions, global providers, and root layouts live here-nothing else. This makes sense because it keeps bootstrap logic separate from domain logic.
A typical layout:
src/app/
App.tsx
main.tsx
routes/
providers/
layouts/
Components should be separated from pages to maintain clarity in routing. The routes directory holds route definitions-React Router configs, route guards, or lazy-loaded page wrappers-while feature UI stays inside features/. This prevents App.tsx from becoming a thousand-line monolith.
The providers directory composes global context: ThemeProvider, React Query client, i18n, auth context. By isolating providers, tests can mount a trimmed-down provider tree without pulling in the entire application.
Framework differences matter. In Vite or CRA, main.tsx renders the root App component wrapped in BrowserRouter. In Next.js 15, the framework provides layout.tsx and page.tsx inside its own app directory, but the app layer still orchestrates features and shared logic at a higher level. In React Native via Expo, the app folder corresponds to navigation setup-stacks, tabs, and root providers.
In a 2024 logistics dashboard, TVL IT Solutions moved provider wiring out of a bloated App.tsx into a dedicated providers directory. Onboarding time dropped by roughly two days, and tests became far simpler.
A feature folder groups everything related to a single user-facing capability-billing, productCatalog, userProfile-rather than scattering code by technical type. Each feature folder can contain components, hooks, and services, all scoped to that domain.
Example layout using singular names for feature folders to maintain clarity:
src/features/productCatalog/
views/
hooks/
services/
store/
utils/
types/
index.ts
The views directory holds feature components like ProductListView and ProductDetailView. The hooks folder contains custom hooks such as useProductsList. Services houses API clients like productApi.ts and mappers. The store manages feature-scoped state. Utils keeps pure helpers tied to that domain. Types defines domain models like Product or ProductFilter.
Each feature’s root directory can have an index file for a clean public interface. A ProductListPage in the pages folder imports from features/productCatalog/index.ts-never the other way around. Feature folders help separate specific components from generic UI components, keeping boundaries crisp.
When should you split? Start with a single feature folder for checkout. Eventually, if it grows unwieldy, split into payment, shipping, and orderReview only when complexity justifies it. Each component should ideally have its own folder for organization within the feature.
In a B2B SaaS analytics app, TVL IT Solutions adopted feature folders so that separate squads could own dashboards, alerts, and user management with minimal merge conflicts. Feature folders group related components, hooks, and services, and that separation made new features straightforward to add.
The shared directory is where feature-agnostic code lives-your internal design system and utility library. Anything placed here must work independently of any single feature.
src/shared/
components/ (buttons, modals, inputs)
hooks/ (useDebounce, useViewport)
icons/
utils/ (date formatting, number formatting)
constants/ (app-wide enums, route names)
Use a dedicated folder for reusable React hooks. Custom hooks should be created for reusable logic to avoid duplicated code across features. The reusable components in shared/components are generic ui components-a Button, not a ProductButton.
The dependency rule is strict: shared cannot import from features. Features import from shared freely. This prevents circular coupling and keeps refactors safe.
A basic design system can start inside shared/components and gradually evolve into its own package. TVL IT Solutions often begins with a shared folder and later extracts a full UI kit package when multiple react projects-say a web admin panel and a mobile portal-need the same components.
Static files live in /public-favicon, robots.txt, manifest.json, and any images that do not need bundling. Imported assets like logos, illustrations, and fonts belong in /src/assets, where the bundler can optimize them.
public/ (favicon, robots.txt, static images)
src/assets/ (logos, illustrations, fonts)
src/styles/ (global.css, variables, themes)
Styling strategy affects folder layout in different types of ways:
Theme configuration-light and dark mode, typography scale, spacing tokens-should live in one place (styles/theme.ts or shared/styles) so both shared components and features consume the same tokens. This keeps look and feel consistent across multiple pages.
Accessibility concerns belong here too. Semantic HTML, focus states, and ARIA attributes are part of UI organization, not afterthoughts layered on top of styles.
React components should focus on rendering and orchestration. Data fetching, transformation, and business logic belong in dedicated layers-services, utilities, and type definitions. This separation keeps code testable and readable.
Structure it like this:
For instance, an orderService.ts file exports getOrders, createOrder, and cancelOrder. The corresponding React views call these functions instead of using fetch directly. Implementation details of the API layer stay hidden behind the service module.
The benefit becomes clear during migrations. In a 2022 TVL IT Solutions project, moving from REST to GraphQL required changes only in services and types-views remained untouched because the data layer was cleanly separated. That separation cut cross-component changes by over seventy percent.
Not all state deserves a global store. Component-local state (useState, useReducer) handles form inputs and toggles. Feature-level state manages context like cart items or report filters. App-level state covers auth, theme, and user session.
src/store/ (app-wide: auth, theme, session)
src/features/*/store/ (feature-scoped: cartSlice, reportFilters)
React applications often use Zustand for state management due to its minimal boilerplate. Redux Toolkit is a popular choice for global state management in larger apps. The React Context API can be used for sharing state across components when external libraries feel like overkill. State management libraries help manage shared states in react apps, and feature folders can include a store for state management.
The folder and file format stays tool-agnostic: a cartSlice.ts or useCartStore.ts lives inside the feature’s store directory. Selectors and reducers sit next to each other so developers can access related logic without jumping between folders.
Feature-level stores make it easier to lazy-load or disable features-for instance, toggling an experimental gamification module in a B2B app. In a multi-tenant CRM, TVL IT Solutions organized auth and permissions in /store while pipeline and accounts logic went into /features/*/store. Store files were testable without mounting React components.
Once you have dozens of feature folders, navigation becomes harder. Group closely related features into domains:
src/domains/
sales/ (features: leads, opportunities, quotes)
billing/ (features: invoices, payments, subscriptions)
For organizations with multiple applications sharing core logic, adopt a monorepo layout:
apps/ (customer portal, admin panel, internal dashboard)
packages/ (ui-kit, api-client, config, eslint-config)
This is appropriate for multi-app platforms, white-label SaaS with different frontends, or when multiple components and teams need independent release cycles. But premature complexity slows small teams-apply this pattern only when the big picture demands it.
TVL IT Solutions used an apps/ + packages/ layout for a client with web, mobile, and kiosk apps sharing core libraries. Packages and shared libraries must not depend on app-specific code. When your application grows beyond a single project, these boundaries keep functionality modular and dependency directions clean.
The same structural ideas-features, shared, app-transfer across environments with small adjustments.
For SPAs built with Vite or CRA, keep the classic /src layout with app, features, shared, and store. Use a pages folder or routes folder for routing components. Static files live in /public as usual.
For SSR and hybrid rendering with Next.js 13+ app router, segments under /app map to routes. Place feature folders in /src/features and have page.tsx files import feature views. This prevents mixing routing concerns with domain logic across multiple pages.
For React Native via Expo, use /src/app for navigation stacks, /features and /shared for logic and UI. Platform-specific files (Component.ios.tsx, Component.android.tsx) sit inside the relevant feature or shared component folder. A hooks folder for cross-platform custom hooks keeps logic reusable.
TVL IT Solutions delivered a platform with both a Next.js web front-end and an Expo mobile app. Aligning folder conventions across both codebases enabled shared logic-business rules, API clients, types-to live in a common package with no duplication.
Most teams inherit messy folder structures. A big-bang rewrite is rarely wise. Prefer a gradual approach:
Colocating tests with components makes writing tests straightforward. Keep tests alongside components for better organization, using a format like MyComponent.test.ts next to MyComponent.ts. Use PascalCase for folders and files containing React components, camelCase for pure JavaScript or TypeScript files and hooks, and kebab-case for general file names in your react project. Using consistent naming conventions helps in navigating the codebase at scale.
Real-world results from TVL IT Solutions engagements:
Sanity check: if deleting a feature folder breaks unrelated areas, your boundaries need work. If developers constantly ask “where do I put this?”, your structure is too vague.
A good react folder structure improves maintainability and reduces merge conflicts. It is foundational for security, scalability, and long-term digital transformation. If your team needs help designing or refactoring a React architecture, TVL IT Solutions brings hands-on experience turning tangled codebases into clean, scalable systems built for growth.
A scalable React project can organize code into app, features, shared, config, styles, types, and optional tests directories.
Feature-based structures keep related components, hooks, services, stores, and types together, making React applications easier to maintain and scale.
The shared folder should contain feature-agnostic reusable components, hooks, icons, utilities, and constants that can be used across different features.
Use local state for component-specific needs, feature-level stores for domain-specific state, and app-level stores for shared concerns such as authentication, themes, and sessions.
At TVL IT Solutions, we specialize in delivering scalable, secure, and custom software development services tailored to your unique business needs. Whether you’re a startup or an enterprise, our team is ready to turn your vision into reality.
Get Started Now
