<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nicholas Fane</title>
    <description>The latest articles on Forem by Nicholas Fane (@fanebytes).</description>
    <link>https://forem.com/fanebytes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3518923%2F939ce1d7-5797-4e71-a77b-ffa1f198f1f0.jpeg</url>
      <title>Forem: Nicholas Fane</title>
      <link>https://forem.com/fanebytes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fanebytes"/>
    <language>en</language>
    <item>
      <title>A Practical React Project Structure</title>
      <dc:creator>Nicholas Fane</dc:creator>
      <pubDate>Sun, 21 Sep 2025 04:50:30 +0000</pubDate>
      <link>https://forem.com/fanebytes/a-practical-react-project-structure-you-can-reuse-332e</link>
      <guid>https://forem.com/fanebytes/a-practical-react-project-structure-you-can-reuse-332e</guid>
      <description>&lt;p&gt;Keep your app predictable, modular, and scalable from day one. This structure combines Bulletproof React ideas with a simple feature-first layout that avoids domain specifics and stays easy to navigate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear boundaries&lt;/strong&gt;: Separate generic vs feature-specific code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast imports&lt;/strong&gt;: Use path aliases, rather than needlessly traversing the file structure in your code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeatable pattern&lt;/strong&gt;: “Copy the structure,” not reinvent it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Base Layout (app-wide)
&lt;/h3&gt;

&lt;p&gt;Use a small set of top-level folders and stick to them. &lt;br&gt;
&lt;em&gt;Note that this structure exists under your 'src' folder, as the root of your project may differ based on what framework you are using (I am using &lt;a href="https://vite.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  app/            # App entry, providers, global styles, bootstrapping
  routes/         # Route files (code-split where possible)
  components/     # Highly generic, reusable UI only (no feature logic)
  features/       # Feature modules (each self-contained)
  hooks/          # Reusable cross-feature hooks
  utils/          # Pure utilities and helpers
  services/       # Integrations with external systems
  types/          # Global/shared TypeScript types
  store/          # Store logic and state management
  assets/         # Static assets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;app&lt;/strong&gt;: central wiring (providers, theming, error boundaries).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;routes&lt;/strong&gt;: route-level code splitting and lazy loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;components&lt;/strong&gt;: generic-only; if you feel tempted to add feature logic here, it belongs in &lt;code&gt;features/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;features&lt;/strong&gt;: replicate a mini version of the base structure per feature (see below).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;store&lt;/strong&gt;: generic state management code, like bootstrapping/exporting the main provider. Specific reducers/selectors will usually exist in their respective feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;services&lt;/strong&gt;: any code required to connect with an external system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;hooks/utils/types&lt;/strong&gt;: shareable and framework-agnostic where possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Path Aliases
&lt;/h3&gt;

&lt;p&gt;Keep imports short and consistent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@components/ui/Button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@features/user/services/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;formatDate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@utils/date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Common aliases&lt;/strong&gt;: &lt;code&gt;@/&lt;/code&gt;, &lt;code&gt;@components/&lt;/code&gt;, &lt;code&gt;@features/&lt;/code&gt;, &lt;code&gt;@hooks/&lt;/code&gt;, &lt;code&gt;@utils/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your tsconfig &lt;code&gt;paths&lt;/code&gt; property will probably need to look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paths&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@app/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/app/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@components/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/components/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@features/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/features/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@hooks/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/hooks/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@types/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/types/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@utils/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/utils/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@store/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/store/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@services/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/services/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@assets/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/assets/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Features Folder Pattern
&lt;/h3&gt;

&lt;p&gt;Each feature is a self-contained slice. Replicate the same internal pattern for every feature to scale cleanly. Below is an example, but the core idea is that you can/should copy the structure defined above to build suit the feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/features/&amp;lt;feature-name&amp;gt;/
  components/     # Feature UI (dumb-first; compose small pieces, but don't stress about making stuff 'overly-generic')
  hooks/          # Feature-specific hooks
  services/       # Data fetching, adapters, caching, side effects
  types/          # Feature-only types/interfaces
  index.ts        # Public surface (barrel exports)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep feature concerns inside the feature&lt;/strong&gt;. Avoid reaching into other features. If you find you need to import a hook from another feature, then congratulations, you've just found a practical use case to create a generic hook&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export only what the rest of the app should use&lt;/strong&gt; from &lt;code&gt;index.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If something becomes generic across features, &lt;strong&gt;promote&lt;/strong&gt; it to &lt;code&gt;@components/&lt;/code&gt;, &lt;code&gt;@hooks/&lt;/code&gt;, or &lt;code&gt;@utils/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bulletproof React Principles (essentials)
&lt;/h3&gt;

&lt;p&gt;This structure is derived from &lt;a href="https://github.com/alan2207/bulletproof-react" rel="noopener noreferrer"&gt;Bulletproof React&lt;/a&gt;, which is a great foundation to expand upon depending on your needs.&lt;/p&gt;

&lt;p&gt;Some of the core concepts are below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feature-first&lt;/strong&gt;: colocate logic, UI, and types by feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Barrel files&lt;/strong&gt; (&lt;code&gt;index.ts&lt;/code&gt;): define clear public APIs per folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type safety&lt;/strong&gt;: strict TypeScript, no &lt;code&gt;any&lt;/code&gt;; define props and service types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Early returns over nesting&lt;/strong&gt;: keep components/functions shallow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small, focused modules&lt;/strong&gt;: single responsibility; extract when files grow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure utilities&lt;/strong&gt; in &lt;code&gt;@utils/&lt;/code&gt;: deterministic and easy to test.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to Add a New Feature (repeatable)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;src/features/&amp;lt;feature-name&amp;gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;components/&lt;/code&gt;, &lt;code&gt;hooks/&lt;/code&gt;, &lt;code&gt;services/&lt;/code&gt;, &lt;code&gt;types/&lt;/code&gt;, &lt;code&gt;index.ts&lt;/code&gt; (or add the required folders at the time you need them).&lt;/li&gt;
&lt;li&gt;Build feature-specific UI in &lt;code&gt;components/&lt;/code&gt;, stateful logic in &lt;code&gt;hooks/&lt;/code&gt;, side effects in &lt;code&gt;services/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Export the minimal public surface from &lt;code&gt;index.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Wire it into &lt;code&gt;routes/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Test at the feature boundary; add E2E coverage if it affects user flows.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What Goes Where (quick rules)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generic UI&lt;/strong&gt;: &lt;code&gt;@components/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature UI/logic&lt;/strong&gt;: &lt;code&gt;@features/&amp;lt;feature&amp;gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable hooks&lt;/strong&gt;: &lt;code&gt;@hooks/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure helpers&lt;/strong&gt;: &lt;code&gt;@utils/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared types&lt;/strong&gt;: &lt;code&gt;types/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes &amp;amp; splitting&lt;/strong&gt;: &lt;code&gt;routes/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App bootstrapping&lt;/strong&gt;: &lt;code&gt;app/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope you found this helpful. Feel free to share your thoughts on what works and what doesn't with this structure. Otherwise, happy developing and good luck on your next project.&lt;/p&gt;

&lt;p&gt;Find me here:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/nicholas-fane-06205897/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/nicholas-fane-06205897/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/NickFane/" rel="noopener noreferrer"&gt;https://github.com/NickFane/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>productivity</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
