I'd like to share my approach to architecting a quite large front-end application consisting of dozens of pages and hundreds of components, implemented in parallel by a dozen front-end developers, highlighting the folder structure I'm using to streamline the development in the team.
The main technologies used are TS, React, React Router, Tanstack Query, styled components, but the structure is technology agnostic.
I prefer to keep the folder structure as flat as possible to reduce the learning curve for newly added developers
/elements
/components
/features
/layouts
/pages
...
App.tsx
router.tsx
Basic building blocks, typically having minimal internal state, usually enhanced basic components from the UI library.
Examples:
/elements
/Textbox
/Tooltip
/MultiSelectCheckmarks
Blocks composed with multiple /elements
. Typically, it does not have API access but can have complex internal states or access to global contexts.
Examples:
/components
/DataGrid
/List
/Modal
/ErrorState
Set of components grouped by domain, typically constructed on top of /components
and /elements
, with data access, with shared API hooks
Examples:
/features
/Users
/UsersList
/UserEditModal
Users.api.ts
Users.api.mocks.ts
Users.types.ts
/Projects
/ProjectsDataGrid
/ProjectEditModal
/ProjectHeader
/ProjectSidebar
Projects.api.ts
Projects.api.mocks.ts
Projects.types.ts
Templates shared between multiple pages, say pages in some area of the app shares footer and sidebar.
Examples:
/layouts
/ProjectLayout
/AdminLayout
/StandalonePreviewLayout
Actual pages connected to routes. Composed with layout and components imported from features
and components
folders
Examples:
/pages
/AdminDashboard
/AdminUsers
/Project
/ProjectAddTask
Certain folder like /hooks
, /contexts
, /utils
can be added to top or individual components or feature level on demand
Individual components follow the agreed file structure to simplify search and maintainability:
/ComponentName
index.ts
ComponentName.tsx
ComponentName.styles.tsx
ComponentName.types.ts
ComponentName.tests.tsx
ComponentName.stories.tsx
Where:
index.ts
- re-export to shorten importsComponentName.tsx
- component codeComponentName.styles.tsx
- styled componentsComponentName.types.ts
- TS types used more than once, or placed in separate file to avoid circular dependenciesComponentName.test.tsx
- unit testsComponentName.stories.tsx
- storybook stories for component
Plus files typically found in /features
:
FeatureName.api.ts
- API hooks used amount the components included into the featureFeatureName.api.mocks.ts
- mocks for API call to use in tests and storybook storiesFeatureName.types.ts
- TS types used amount the components included into the feature
I'm using ComponentName
prefix everywhere to ease search in IDE and logs, and have the full context of the file when looking at opened files tabs in IDE.
Certain files can be omitted as I'm putting things inline when if makes sense and extracting out certain styles components and styles when they're used more than once and it makes sense to achieve better code structure
I've found the above folders and file structure quite usable in large enough frontend applications from my almost 15 years of development experience. Glad to hear your feedback in the comments!
Putting the expanded structure example below:
/elements
/Textbox
index.ts
Textbox.tsx
Textbox.styles.tsx
Textbox.types.ts
Textbox.tests.tsx
Textbox.stories.tsx
/features
/Users
/UsersList
index.ts
UsersList.tsx
UsersList.styles.tsx
UsersList.types.ts
UsersList.tests.tsx
UsersList.stories.tsx
Users.api.ts
Users.api.mocks.ts
Users.types.ts
/Projects
/ProjectsDataGrid
index.ts
ProjectsDataGrid.tsx
ProjectsDataGrid.styles.tsx
ProjectsDataGrid.types.ts
ProjectsDataGrid.tests.tsx
ProjectsDataGrid.stories.tsx
Projects.api.ts
Projects.api.mocks.ts
Projects.types.ts
/layouts
/ProjectLayout
index.ts
ProjectLayout.tsx
ProjectLayout.styles.tsx
ProjectLayout.types.ts
ProjectLayout.tests.tsx
ProjectLayout.stories.tsx
/pages
/Project
index.ts
Project.tsx
Project.styles.tsx
Project.types.ts
Project.tests.tsx
Project.stories.tsx
App.tsx
router.tsx