<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://tech.uvoo.io/index.php?action=history&amp;feed=atom&amp;title=React_directory_structure</id>
	<title>React directory structure - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://tech.uvoo.io/index.php?action=history&amp;feed=atom&amp;title=React_directory_structure"/>
	<link rel="alternate" type="text/html" href="https://tech.uvoo.io/index.php?title=React_directory_structure&amp;action=history"/>
	<updated>2026-04-05T17:41:24Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.2</generator>
	<entry>
		<id>https://tech.uvoo.io/index.php?title=React_directory_structure&amp;diff=5647&amp;oldid=prev</id>
		<title>Busk at 03:32, 9 September 2025</title>
		<link rel="alternate" type="text/html" href="https://tech.uvoo.io/index.php?title=React_directory_structure&amp;diff=5647&amp;oldid=prev"/>
		<updated>2025-09-09T03:32:07Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 03:32, 9 September 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot; &gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;```&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;/src&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;/src&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;├── assets/&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;├── assets/&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l56&quot; &gt;Line 56:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 58:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;├── App.tsx&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;├── App.tsx&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;└── index.tsx&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;└── index.tsx&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;```&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Busk</name></author>
	</entry>
	<entry>
		<id>https://tech.uvoo.io/index.php?title=React_directory_structure&amp;diff=5646&amp;oldid=prev</id>
		<title>Busk: Created page with &quot;/src ├── assets/ │   ├── images/ │   └── styles/ ├── components/ │   ├── common/ │   │   ├── Empty.tsx │   │   ├── Stat...&quot;</title>
		<link rel="alternate" type="text/html" href="https://tech.uvoo.io/index.php?title=React_directory_structure&amp;diff=5646&amp;oldid=prev"/>
		<updated>2025-09-09T03:29:12Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;/src ├── assets/ │   ├── images/ │   └── styles/ ├── components/ │   ├── common/ │   │   ├── Empty.tsx │   │   ├── Stat...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/src&lt;br /&gt;
├── assets/&lt;br /&gt;
│   ├── images/&lt;br /&gt;
│   └── styles/&lt;br /&gt;
├── components/&lt;br /&gt;
│   ├── common/&lt;br /&gt;
│   │   ├── Empty.tsx&lt;br /&gt;
│   │   ├── StatusChip.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   ├── fields/&lt;br /&gt;
│   │   ├── MoneyField.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   └── inputs/&lt;br /&gt;
│       ├── AddressInput.tsx&lt;br /&gt;
│       └── index.ts&lt;br /&gt;
├── features/&lt;br /&gt;
│   ├── companies/&lt;br /&gt;
│   │   ├── CompanyCreate.tsx&lt;br /&gt;
│   │   ├── CompanyEdit.tsx&lt;br /&gt;
│   │   ├── CompanyList.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   ├── invoices/&lt;br /&gt;
│   │   ├── InvoiceCreate.tsx&lt;br /&gt;
│   │   ├── InvoiceEdit.tsx&lt;br /&gt;
│   │   ├── InvoiceList.tsx&lt;br /&gt;
│   │   ├── InvoiceShow.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   └── users/&lt;br /&gt;
│       ├── UserCreate.tsx&lt;br /&gt;
│       ├── UserEdit.tsx&lt;br /&gt;
│       ├── UserList.tsx&lt;br /&gt;
│       └── index.ts&lt;br /&gt;
├── hooks/&lt;br /&gt;
│   ├── usePermissions.ts&lt;br /&gt;
│   └── useDebounce.ts&lt;br /&gt;
├── layout/&lt;br /&gt;
│   ├── AppBar.tsx&lt;br /&gt;
│   ├── Layout.tsx&lt;br /&gt;
│   ├── Login.tsx&lt;br /&gt;
│   └── Menu.tsx&lt;br /&gt;
├── pages/&lt;br /&gt;
│   ├── Dashboard.tsx&lt;br /&gt;
│   └── Settings.tsx&lt;br /&gt;
├── providers/&lt;br /&gt;
│   ├── authProvider.ts&lt;br /&gt;
│   ├── dataProvider.ts&lt;br /&gt;
│   └── i18nProvider.ts&lt;br /&gt;
├── theme/&lt;br /&gt;
│   └── theme.ts&lt;br /&gt;
├── types/&lt;br /&gt;
│   ├── index.ts&lt;br /&gt;
│   └── react-admin.d.ts&lt;br /&gt;
├── utils/&lt;br /&gt;
│   ├── formatters.ts&lt;br /&gt;
│   └── history.ts&lt;br /&gt;
├── App.tsx&lt;br /&gt;
└── index.tsx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Of course. Here is a battle-tested directory structure for a scalable B2B React Admin application that emphasizes maintainability and separation of concerns.&lt;br /&gt;
This structure is organized around features (or &amp;quot;resources&amp;quot; in React Admin terms), which is a highly effective way to manage complexity as your application grows.&lt;br /&gt;
Example Directory Structure&lt;br /&gt;
Here is a visual representation of the recommended structure:&lt;br /&gt;
/src&lt;br /&gt;
├── assets/&lt;br /&gt;
│   ├── images/&lt;br /&gt;
│   └── styles/&lt;br /&gt;
├── components/&lt;br /&gt;
│   ├── common/&lt;br /&gt;
│   │   ├── Empty.tsx&lt;br /&gt;
│   │   ├── StatusChip.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   ├── fields/&lt;br /&gt;
│   │   ├── MoneyField.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   └── inputs/&lt;br /&gt;
│       ├── AddressInput.tsx&lt;br /&gt;
│       └── index.ts&lt;br /&gt;
├── features/&lt;br /&gt;
│   ├── companies/&lt;br /&gt;
│   │   ├── CompanyCreate.tsx&lt;br /&gt;
│   │   ├── CompanyEdit.tsx&lt;br /&gt;
│   │   ├── CompanyList.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   ├── invoices/&lt;br /&gt;
│   │   ├── InvoiceCreate.tsx&lt;br /&gt;
│   │   ├── InvoiceEdit.tsx&lt;br /&gt;
│   │   ├── InvoiceList.tsx&lt;br /&gt;
│   │   ├── InvoiceShow.tsx&lt;br /&gt;
│   │   └── index.ts&lt;br /&gt;
│   └── users/&lt;br /&gt;
│       ├── UserCreate.tsx&lt;br /&gt;
│       ├── UserEdit.tsx&lt;br /&gt;
│       ├── UserList.tsx&lt;br /&gt;
│       └── index.ts&lt;br /&gt;
├── hooks/&lt;br /&gt;
│   ├── usePermissions.ts&lt;br /&gt;
│   └── useDebounce.ts&lt;br /&gt;
├── layout/&lt;br /&gt;
│   ├── AppBar.tsx&lt;br /&gt;
│   ├── Layout.tsx&lt;br /&gt;
│   ├── Login.tsx&lt;br /&gt;
│   └── Menu.tsx&lt;br /&gt;
├── pages/&lt;br /&gt;
│   ├── Dashboard.tsx&lt;br /&gt;
│   └── Settings.tsx&lt;br /&gt;
├── providers/&lt;br /&gt;
│   ├── authProvider.ts&lt;br /&gt;
│   ├── dataProvider.ts&lt;br /&gt;
│   └── i18nProvider.ts&lt;br /&gt;
├── theme/&lt;br /&gt;
│   └── theme.ts&lt;br /&gt;
├── types/&lt;br /&gt;
│   ├── index.ts&lt;br /&gt;
│   └── react-admin.d.ts&lt;br /&gt;
├── utils/&lt;br /&gt;
│   ├── formatters.ts&lt;br /&gt;
│   └── history.ts&lt;br /&gt;
├── App.tsx&lt;br /&gt;
└── index.tsx&lt;br /&gt;
&lt;br /&gt;
## Explanation of Each Directory&lt;br /&gt;
features/ (or resources/)&lt;br /&gt;
This is the most important directory. Instead of grouping files by type (e.g., all &amp;quot;List&amp;quot; views together), you group them by the business feature or resource they represent. This makes the codebase much easier to navigate and maintain.&lt;br /&gt;
 * features/companies/: Contains all components related to the &amp;quot;companies&amp;quot; resource: CompanyList, CompanyEdit, CompanyCreate, etc.&lt;br /&gt;
 * index.ts: Each feature folder should have an index.ts file that exports all of its components (a &amp;quot;barrel file&amp;quot;). This allows for cleaner imports in your main App.tsx file.&lt;br /&gt;
   // src/features/companies/index.ts&lt;br /&gt;
export * from './CompanyList';&lt;br /&gt;
export * from './CompanyEdit';&lt;br /&gt;
export * from './CompanyCreate';&lt;br /&gt;
&lt;br /&gt;
components/&lt;br /&gt;
This folder is for shared, reusable UI components that are not tied to a single feature.&lt;br /&gt;
 * common/: General-purpose components like a custom Empty state component or a StatusChip used across multiple resources.&lt;br /&gt;
 * fields/: Custom React Admin &amp;lt;Field&amp;gt; components, such as a MoneyField that formats currency.&lt;br /&gt;
 * inputs/: Custom React Admin &amp;lt;Input&amp;gt; components, like a complex AddressInput group.&lt;br /&gt;
providers/&lt;br /&gt;
This is a dedicated place for your core React Admin providers. Keeping them together makes the app's data and authentication logic easy to find.&lt;br /&gt;
 * dataProvider.ts: Handles all communication with your API.&lt;br /&gt;
 * authProvider.ts: Manages login, logout, permissions, etc.&lt;br /&gt;
 * i18nProvider.ts: Handles internationalization and translations.&lt;br /&gt;
layout/&lt;br /&gt;
Use this directory to override React Admin's default layout components.&lt;br /&gt;
 * Layout.tsx: Your main app shell, which pulls in the custom AppBar and Menu.&lt;br /&gt;
 * Menu.tsx: A custom menu, perhaps with icons or role-based visibility.&lt;br /&gt;
 * Login.tsx: A custom-branded login page.&lt;br /&gt;
pages/&lt;br /&gt;
For any custom pages in your application that are not standard CRUD views.&lt;br /&gt;
 * Dashboard.tsx: A perfect place for a dashboard component that shows charts and summary data.&lt;br /&gt;
 * Settings.tsx: A user settings or application configuration page.&lt;br /&gt;
hooks/&lt;br /&gt;
For custom, reusable React hooks that contain business logic.&lt;br /&gt;
 * usePermissions.ts: A common hook in B2B apps to check the current user's roles and permissions.&lt;br /&gt;
 * useDebounce.ts: A utility hook to debounce user input, useful for search filters.&lt;br /&gt;
theme/&lt;br /&gt;
Contains your Material UI theme configuration.&lt;br /&gt;
 * theme.ts: Define your primary/secondary colors, typography, spacing, and component overrides here.&lt;br /&gt;
types/&lt;br /&gt;
Centralize your TypeScript types for better code quality and autocompletion.&lt;br /&gt;
 * index.ts: Define types for your data models (e.g., Company, User, Invoice).&lt;br /&gt;
 * react-admin.d.ts: Augment React Admin's own types if needed.&lt;br /&gt;
## Putting It All Together (App.tsx)&lt;br /&gt;
This structure leads to a very clean and readable main App.tsx file.&lt;br /&gt;
// src/App.tsx&lt;br /&gt;
import { Admin, Resource, CustomRoutes } from 'react-admin';&lt;br /&gt;
import { Route } from 'react-router-dom';&lt;br /&gt;
&lt;br /&gt;
// Providers&lt;br /&gt;
import { dataProvider } from './providers/dataProvider';&lt;br /&gt;
import { authProvider } from './providers/authProvider';&lt;br /&gt;
&lt;br /&gt;
// Layout and Pages&lt;br /&gt;
import { Layout } from './layout/Layout';&lt;br /&gt;
import { Dashboard } from './pages/Dashboard';&lt;br /&gt;
&lt;br /&gt;
// Features (Resources)&lt;br /&gt;
import { CompanyList, CompanyEdit, CompanyCreate } from './features/companies';&lt;br /&gt;
import { InvoiceList, InvoiceEdit, InvoiceShow } from './features/invoices';&lt;br /&gt;
import { UserList } from './features/users';&lt;br /&gt;
&lt;br /&gt;
const App = () =&amp;gt; (&lt;br /&gt;
  &amp;lt;Admin&lt;br /&gt;
    dataProvider={dataProvider}&lt;br /&gt;
    authProvider={authProvider}&lt;br /&gt;
    layout={Layout}&lt;br /&gt;
    dashboard={Dashboard}&lt;br /&gt;
  &amp;gt;&lt;br /&gt;
    &amp;lt;Resource&lt;br /&gt;
      name=&amp;quot;companies&amp;quot;&lt;br /&gt;
      list={CompanyList}&lt;br /&gt;
      edit={CompanyEdit}&lt;br /&gt;
      create={CompanyCreate}&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;Resource&lt;br /&gt;
      name=&amp;quot;invoices&amp;quot;&lt;br /&gt;
      list={InvoiceList}&lt;br /&gt;
      edit={InvoiceEdit}&lt;br /&gt;
      show={InvoiceShow}&lt;br /&gt;
    /&amp;gt;&lt;br /&gt;
    &amp;lt;Resource name=&amp;quot;users&amp;quot; list={UserList} /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    {/* Custom pages */}&lt;br /&gt;
    &amp;lt;CustomRoutes&amp;gt;&lt;br /&gt;
      &amp;lt;Route path=&amp;quot;/settings&amp;quot; element={&amp;lt;SettingsPage /&amp;gt;} /&amp;gt;&lt;br /&gt;
    &amp;lt;/CustomRoutes&amp;gt;&lt;br /&gt;
  &amp;lt;/Admin&amp;gt;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
export default App;&lt;/div&gt;</summary>
		<author><name>Busk</name></author>
	</entry>
</feed>