Appearance
React project files and directories names convention
Context
Across the ecosystem, we can find all sorts of files and directory naming conventions in React projects. The variety of conventions causes misalignment and shifts focus away from more important matters.
Although there are no silver bullets for this topic, committing to a convention will reduce cognitive load by triggering pattern recognition, enabling engineers to focus their brainpower on their tasks.
Consistency, Predictability and Familiarity
Consistency and Predictability are key to reducing cognitive load and facilitating the onboarding process.
More often than not, "familiarity" is what people call "Good Developer Experience", and we believe that is good thing, imagine if JavaScript Programming Language Runtimes move around modules and global objects, change the syntax of the language, or change the meaning and behavior of built-in functions based on personal preferences, that would be a nightmare. We wouldn't be productive if we had to pay attention to every single detail every time we write code.
We also believe that "Familiarity" does not mean "Perfection", and there is a cost to learning and adapting to a new convention,
But we believe that the cost is worth it in the long run. Although, the ADR may feel overwhelming at first, we promise that it will become second nature after a while, and some of the rules will lead you to a codebase that barely changes over time. They are that many ways to configure i18n
Strong Cohesion, Controlled Coupling, and Risk Mitigation
When something goes wrong, we need to add, remove, update or fix a use case; we need to answer the simple question:
- Where do we need to do that?
The simplest way to answer that question is to ask which Route is involved, and work your way up or down the Application Tree.
For that reason, we need to have a strong cohesion and controlled coupling of the files between the routes is critical. The higher your changes are in the Application Tree, the more risk you are introducing to the application. The lower your changes are in the Application Tree, the less risk you are introducing to the application since the changes are more isolated.
Probably the most important part of the ADR is the fact that you can not import or have circular dependencies between sibling routes, you will require to move the files to a common root directory that is a parent to the routes. Signaling that the files are shared between the routes and that the files are increasing the risk of the application.
Resolution
- You MUST not import between routes. You MUST use colocate the files to a common root directory that is a parent to the routes.
- You MUST not have circular dependency between sibling directories. You MUST use a common root directory that is a parent to the sibling directories.
- You MUST use
<rootDir>/src/@types
to store TypeScript definition files (*.d.ts
). - You MUST use
<rootDir>/src/polyfills
to store polyfills. - You MUST use
_
as a prefix for Private Directories under<rootDir>/src/app
to opt-out of the routing system. - You SHOULD avoid re-exporting files, and you SHOULD use the file directly.
- You SHOULD use relative imports when importing sibling files or nested to under the same parent directory.
- You SHOULD use absolute imports when importing from a different parent directory.
- You MUST NOT use Private Directories inside
<rootDir>/src/libs/[lib name]
. - You MUST use
__tests__
for testing support files under<rootDir>/src
. - You MUST colocate Component's Unit Test sibling to component file by using
[component name].test.[extension]
.
Libraries Only
- You MUST use
<rootDir>/src/libs/[lib name]
to store Libraries. - You SHOULD wait until you have at least two consumers with the exact same code in production for at least two months, that required the same changes to be made in all two consumers before adding anything to a
<rootDir>/src/libs/[lib name]
. - You SHOULD wait until you have at least three consumers with the exact same code in production for at least three months, that required the same changes to be made in all two consumers before moving a
<rootDir>/src/libs/[lib name]
to a separate package. - You MUST not have circular dependencies between Libraries.
Next.js Only
- You MUST use Next.js App Router directory structure.
- You MUST NOT use Next.js Pages Router directory structure.
- You MUST use
<rootDir>/src/app
directory to store the Next.js Router. - You MUST use
<rootDir>/public
to store static files. - You MUST NOT import Server Action files from another Server Action file.
- You MUST NOT call a Server Action function from another Server Action function.
React Native Only
- You MUST use Expo Router directory structure.
- You MUST use
<rootDir>/src/app
directory to store the Expo Router. - You MUST use
<rootDir>/src/assets
to store assets files. - You MUST NOT use
<rootDir>/assets
to store assets files.
Vite Only
Related to Vite projects only.
- You MUST use
<rootDir>/src/app/index.tsx
as the entry point for the Vite application.
Fractal Pattern
A fractal pattern is a pattern that you could repeat over and over again.
You MUST follow the fractal pattern under the
<rootDir>/src
,<rootDir>/src/app
,<rootDir>/src/components/[component name]
, and<rootDir>/src/libs/[lib name]
directories.You MUST prefix all directories under
<rootDir>/src/app
with_
to opt-out of the routing system and define the directory as a Private Directory.You MUST use
<fractalDir>/services
to store anything related to any communication with External Services.You MUST use external service brand name as a file or subdirectory in
<fractalDir>/services/[service name]
.You MUST use
<fractalDir>/storages
to store anything related to the device. You MUST uselocal
,session
,cookies
,websql
, andindexeddb
as subdirectories based on the storage type.You MUST use
<fractalDir>/schemas
to store anything related to Joi, Yup schemas or any similar package.You MUST use
<fractalDir>/components
to store reusable React components.You MUST use
<fractalDir>/hooks
to store reusable React hooks.You MUST use
<fractalDir>/contexts
to store React contexts definitions.You MUST use
<fractalDir>/constants
to store constants variables.You MUST use
<fractalDir>/types
to store reusable TypeScript types.You MUST use
<fractalDir>/styles
to store components styles such as CSS or Stylesheets.You MUST colocate CSS Module Component's Styles sibling to component file with the following naming convention
[component name].module.[extension]
.You MUST use
<fractalDir>/assets
to store files such as images, fonts, and any other files that are no Stylesheets or JavaScript files.You MUST use
<fractalDir>/i18n
to store anything related to Internationalization.You MUST use
<fractalDir>/i18n/messages
to store the i18n messages.You MUST use
<fractalDir>/i18n/datetime
to store i18n date and time formatting. Read more about the intent at Intl.DateTimeFormat.You MUST use
<fractalDir>/i18n/list
to store i18n sensitive list formatting. Read more about the intent at Intl.ListFormat.You MUST use
<fractalDir>/i18n/numbers
to store i18n number formatting. Read more about the intent at Intl.NumberFormat.You MUST use
<fractalDir>/i18n/plural
to store i18n pluralization formatting. Read more about the intent at Intl.PluralRules.You MUST use
<fractalDir>/i18n/relative-time
to store i18n relative-time formatting. Read more about the intent at Intl.RelativeTimeFormat.You MUST use
<fractalDir>/helpers/datetime
to store anything related to Dates or Times. Except formatters, use<fractalDir>/i18n/datetime
instead.You MUST use
<fractalDir>/helpers/currency
to store anything related to currency. Except formatters, use<fractalDir>/i18n/numbers
instead.You MUST use
<fractalDir>/helpers
to store anything that does not fall into any of the other helper directory categories.
Next.js Fractal Pattern
Related to Next.js projects only.
- You MUST use
<fractalDir>/server
to store anything related to the Next.js server-side code. You MUST add'use server;'
directive to the top of the files. - You MUST use
<fractalDir>/server/actions
to store anything related to Next.js Server Actions.
Terminology
Libraries
Libraries are a set of shared code intended to be moved to a separate package in the future.
Route
A Route, in the context of React DOM, Route is a path or segments of URL that the user is visiting.
A Route, in the context of React Native, it is a screen.
External services
Any piece of software external to your application that crosses some network boundary such as APIs, 3rd party tools (Google Analytics, Sentry), and so on.
Private Directory
A Private Directory is a directory that should not be considered by the routing system, thereby opting the directories and all its subdirectories out of routing system. This is inspired by the Next.js App Router directory structure.