{"id":16173293,"url":"https://github.com/eiskalteschatten/scalable-react-project","last_synced_at":"2025-10-26T14:34:37.759Z","repository":{"id":64918799,"uuid":"579415892","full_name":"eiskalteschatten/scalable-react-project","owner":"eiskalteschatten","description":"An experimental example of how to structure a React project to make it scalable.","archived":false,"fork":false,"pushed_at":"2022-12-19T12:26:17.000Z","size":415,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-13T12:32:09.410Z","etag":null,"topics":["reactjs","scalability","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eiskalteschatten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-12-17T16:14:06.000Z","updated_at":"2023-01-31T22:16:12.000Z","dependencies_parsed_at":"2023-01-29T21:31:05.130Z","dependency_job_id":null,"html_url":"https://github.com/eiskalteschatten/scalable-react-project","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiskalteschatten%2Fscalable-react-project","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiskalteschatten%2Fscalable-react-project/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiskalteschatten%2Fscalable-react-project/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiskalteschatten%2Fscalable-react-project/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eiskalteschatten","download_url":"https://codeload.github.com/eiskalteschatten/scalable-react-project/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247623005,"owners_count":20968574,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["reactjs","scalability","typescript"],"created_at":"2024-10-10T04:08:01.504Z","updated_at":"2025-10-26T14:34:37.694Z","avatar_url":"https://github.com/eiskalteschatten.png","language":"TypeScript","readme":"# Scalable React Project\n\nAn experimental example of how to structure a React project to make it scalable.\n\nThis project is constantly evolving and I would love to hear any feedback, suggestions, questions, etc you might have. See the \u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e section for more information on that.\n\n\n## Table of Contents\n\n- \u003ca href=\"#terminology\"\u003eTerminology\u003c/a\u003e\n- \u003ca href=\"#project-structure\"\u003eProject Structure\u003c/a\u003e\n- \u003ca href=\"#file-division\"\u003eFile Division\u003c/a\u003e\n- \u003ca href=\"#state-management\"\u003eState Management\u003c/a\u003e\n- \u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\n\n## Terminology\n\n### Module\nModules are the largest building blocks. They can contain multiple pages (routes), components, services, contexts, etc. They can also contain submodules that follow the same file structure.\n\nEach module should be divided into logical units that make sense for your application. An example for a web store could be:\n\n- ProductModule\n- CartModule\n- UserAccountModule\n- LandingPageModule\n- etc…\n\nThe RootModule is the only \"required\" module. This is where the homepage and the 404 page reside. Static pages that don’t require much logic, such as a privacy statement page, could be added here as well.\n\n### Page\nA page is where a route will land. It can contain multiple components and services, but should only have one context at most.\n\nPages also set their own page titles.\n\n### Service\nThis is where application logic happens such as data processing, etc. Services for modules, pages and components should be built using a `useService` hook by default so that they have access to other hooks, i.e. useContext hooks.\n\n### Context\nThis is where data is stored. Optionally, it can be fetched and sent from a context as well.\n\n### Components\nComponents are the smallest unit and are at the bottom of the hierarchy. They should contain nothing but markup, styles and a little bit of logic specific for that individual component. They can use parent contexts, local states, etc, but should not have their own services or contexts.\n\n### Layouts\nLayouts are a sort of scaffolding for your application. They contain the page designs as well as components relevant to the design such as the header, main menu, footer, etc.\n\nIt is recommended to add them at module-level to maintain flexibility. If you need multiple layouts per module, you should probably rethink your code division.\n\n\n## Project Structure\n\nThe following structure should reside in the `src` folder which was left out for brevity in the diagram below:\n\n```\nindex.tsx\nApp.tsx\nApp.scss\nApp.context.tsx (The application context for global state)\nApp.test.tsx\nassets\n└─── Images, fonts, etc\ni18n\n└───  Translations, etc\nmodules\n└─── [ModuleName]\n│   │    index.tsx (Where the routes are defined)\n│   │    [ModuleName].context.tsx\n│   │    [ModuleName].test.tsx\n└─── pages\n│   │    [PageName]\n│   │    index.tsx\n│   │    [PageName].module.scss\n│   │    [PageName].service.ts\n│   │    [PageName].context.tsx\n│   │    [PageName].test.tsx\n│   │    [PageName].interfaces.ts\n│   └─── [ComponentName]\n│   │   │    index.tsx\n│   │   │    [ComponentName].module.scss\n│   │   │    [ComponentName].test.tsx\n│   │   │    [ComponentName].interfaces.ts\n│   └─── components (Modules can have components that are shared across multiple pages)\n│   │   └─── [ComponentName]\n│   │   │   │   index.tsx\n│   │   │   │   [ComponentName].module.scss\n│   │   │   │   [ComponentName].test.tsx\n│   │   │   │   [ComponentName].interfaces.ts\n│   └─── interfaces (Modules can have shared TypeScript interfaces)\n│   └─── hooks\n│   └─── etc...\nlayouts\n└─── [LayoutName]\n│   │    index.tsx\n│   │    [LayoutName].module.scss\n│   └─── [ComponentName]\n│   │   │    index.tsx\n│   │   │    [ComponentName].module.scss\n│   │   │    [ComponentName].test.tsx\n│   │   │    [ComponentName].interfaces.ts\nshared (Anything that is shared between multiple modules, components, etc should go here)\n└─── components\n│   │    [ComponentName]\n│   │    index.tsx\n│   │    [ComponentName].module.scss\n│   │    [ComponentName].test.tsx\n│   │    [ComponentName].interfaces.ts\n└─── services\n└─── helpers\n└─── etc...\n```\n\n### Folder Nesting\nThe official recommendation for folder nesting from the React project is [\"as flat as possible\"](https://reactjs.org/docs/faq-structure.html#avoid-too-much-nesting).\n\nWhile the structure above does make use of nested folders, it is designed to limit them as much as possible. The deepest folder should never be deeper than four or five levels deep from the `src` folder to avoid wonky imports. The most deeply-nested folder in this structure can be found at `modules/[ModuleName]/pages/components/[ComponentName]`.\n\n### Naming Conventions\nConsistent naming conventions are vital for larger projects. They make files and their functions predictable for both old and new developers alike.\n\nThe approach taken by this project is to consistently name files after the module, page or component they inherit from. This name combined with its function (i.e. `[PageName].service.ts` or `[ModuleName].context.ts`), combine to form an easily distguishable name that says exactly what the file does. The exceptions to this rule are the `index.tsx` files which serve as the base of each directory as well as where it doesn't make sense such as helpers, hooks, etc.\n\n## File Division\nFile division should follow the priciple of \"one file, one purpose\". The purpose should be defined in the file name (see above, \"Naming Conventions\").\n\nThere are a few examples of code division below. Every project is slightly different in terms of its file requirements and so each module, page, component, etc should be made accordingly. The important thing is that there is a clear division that is easily definable by a single word to be put in the file name.\n\n### Modules\n- `index.tsx` - Routes within the module should be defined here as well as the layout the module uses. The layout should be defined in the `src/layouts` folder.\n- `[ModuleName].context.tsx` - If the module needs a context, it should be defined here.\n- `[ModuleName].test.tsx` - The test for the module routes.\n\n### Pages\n- `index.tsx` - This is where markup the code for the page resides. The only logic this file should contain is anything directly pertaining to the display or layout of the entire page.\n- `[PageName].service.ts` - The service is where the business logic should happen. This includes any data handling, etc needed for the page.\n- `[PageName].module.scss` - This is where any CSS belongs that is directly used by this page.\n- `[PageName].context.tsx` - If the page needs a context, is should be defined here.\n- `[PageName].test.tsx` - The test for the page.\n- `[PageName].interfaces.ts` - This is where any necessary TypeScript interfaces should reside that affect the entire page.\n\n### Components\n- `index.tsx` - Like with the page, this is where markup the code resides. The only logic this file should contain is anything directly pertaining to the display or layout of the entire page.\n- `[ComponentName].module.scss` - This is where any CSS belongs that is directly used by this page.\n- `[ComponentName].test.tsx` - The test for the page.\n- `[ComponentName].interfaces.ts` - This is where any necessary TypeScript interfaces should reside.\n\n## State Management\nThe eagle-eyed amongst you may have noticed there there is no Redux or other state-mangement system in this project. That is because it uses contexts that React provides natively. Redux and other tools were born before React offered cross-component state management natively. By only using contexts, you significantly reduce your chunk sizes and your boilerplating.\n\nThe project is organized such that contexts are hierarchical:\n\n- `App.context.tsx` is used for global application state. The provider is included in `App.tsx`.\n- `[ModuleName].context.tsx` is used for module states that affect multiple pages within that module. The provider is included in the `index.tsx` of the module.\n- `[PageName].context.tsx` is used for page states that affect multiple components within that page. The provider is included in the `index.tsx` of the module and wrapped around the page component in the `\u003cRoute\u003e`. This is so that the page itself has access to it.\n\nAs a general rule, local state should be preferred. This means that state should be kept at the lowest possible level to avoid unnecessary rerendering. Contexts should only be used if the state truly affects multiple sub-components.\n\n## Contributing\nI would love to hear any feedback, suggestions, questions, etc you might have:\n\n- Feedback, questions, discussions, etc: https://github.com/eiskalteschatten/scalable-react-project/discussions\n- Suggestions, corrections, etc: https://github.com/eiskalteschatten/scalable-react-project/issues\n\nAlso, feel free to fork and create a pull request!\n\n---\n\nAlex Seifert - https://www.alexseifert.com\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feiskalteschatten%2Fscalable-react-project","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feiskalteschatten%2Fscalable-react-project","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feiskalteschatten%2Fscalable-react-project/lists"}