Project src/ Structure
Projects should try to adhere to these src/ folder guidelines to keep things organized and easy to find.
src/App.js- The primary<App>component.src/Routes.js- Site routing to separate it from<App>. Projects are encouraged to use@loadable/componentsorReact.lazyto allow code-splitting of routes.src/ui/- React User Interface components without notable application logic in them. To avoid the UI folder growing too large, components should be organized into subfolders if good grouping subdirectories can be identified. Common UI subfolders follow.src/ui/inputs/- Custom inputs, e.g. a<DateField>that implements a<TextField>-like interface with a date picker.
src/layout/- Components that make up the general site layout.src/layout/Layout.js- A common<Layout>component.
src/utils/- General purpose utilities. Generic functions, hooks, and possible non-UI components.src/routes/- Site page route components.- Routes should be placed in route family subfolders (e.g.
dashboard,user,auth, etc...) so that subfolders such asui/can be created for additional components directly related to a single route family. - e.g.
src/routes/dashboard/Dashboard.js
- Routes should be placed in route family subfolders (e.g.
src/{sub-system}/- Other parts of the app (both parts common to different projects and project specific parts) should be grouped into "sub system" folders.- Guidelines for common sub-systems are documented below (see Common sub-systems)
- If a sub-system is "library-like", i.e. it may contain internal parts that should not be imported outside the sub-system, some of these internals may be separated out into internal files for organization, and/or it has a defined API for the sub-system as a whole instead of disconnected parts. The sub-system should include an index file with the sub-system's API. Files outside the sub-system should import the sub-system as a whole and be discouraged from importing files inside the sub-system. If a library-like sub-system is used frequently around the app it's encouraged to write it in TypeScript so that Intellisense will be available even in JavaScript code.
Common sub-systems
API client (src/api/)
Projects with an API should have an api sub-system. The implementation will vary by project requirements and backend type, but the client should follow these common guidelines.
- It should be library-like and export a single API
- It should export a provider (e.g.
<ApiProvider>,<ApiRoot>,<GqlApiProvider>) to setup the client in a shared root - It should export a hooks API (e.g.
useQuery) if it a fully-featured hooks using client like Apollo Client is not being used - It should use an env variable to configure the API endpoint/base URL instad of hardcoding it
- A default can be provided in CRA using a shared
.envor in other frameworks with a|| default value
- A default can be provided in CRA using a shared
- It's suggested that the API client should support a USE_MOCKS env which in development will use mock API data to support development of the frontend without running a dev backend
Authentication (src/auth/)
Projects with user authentication should have an auth sub-system.
- It should be library-like and export a single API
- It should export a provider (e.g.
<AuthProvider>,<AuthRoot>) to setup the auth context - It should export a hooks API to get the current auth context and actions e.g.
useUser,useAuthActions(or specific hooks likeuseLogoutAction)
Dashboard Widgets (src/dashboard-widgets/)
If a project has a dashboard route with widgets the widgets should be implemented as part of a widget sub-system under the name dashboard-widgets following these guides. Projects entirely based around widgets would work similarly but have a different sub-system name.
src/dashboard-widgets/widgets/*.js- Individual widget implementations- If the widget system uses
src/dashboard-widgets/widgets/index.js- An index file that exports adefaultexport with an object mapping widget names to widget implementations.- Depending on the widget system implementation it may be beneficial to have a
widgets.jsthat uses 1-line re-exports of widget implementations so theindex.jscan be justimport * as widgets from './widgets'; export default widgets;and avoid the need to duplicate identifiers.
- Depending on the widget system implementation it may be beneficial to have a
src/dashboard-widgets/index.js- Should export the widget API, helpers likegetWidgetand a<DashboardWidget>component are recommended instead of having the dashboard itself handle thewidgetsobject.