Skip to content

Instantly share code, notes, and snippets.

@zomars
Last active May 28, 2024 18:19
Show Gist options
  • Select an option

  • Save zomars/ebf93c3281b714ae4048e9f43b0ff20e to your computer and use it in GitHub Desktop.

Select an option

Save zomars/ebf93c3281b714ae4048e9f43b0ff20e to your computer and use it in GitHub Desktop.

Revisions

  1. zomars revised this gist Jun 4, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions modularized-nextjs-project-strucutre.md
    Original file line number Diff line number Diff line change
    @@ -137,3 +137,4 @@ export { default } from '~/modules/users/pages/show';
    ## More resources

    - [Evolution of a React folder structure and why to group by features right away](https://profy.dev/article/react-folder-structure)
    - https://twitter.com/swyx/status/1010922550912802816?s=20&t=rSoEUOlYp-s56EJ1abcuCg
  2. zomars revised this gist Jun 4, 2022. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions modularized-nextjs-project-strucutre.md
    Original file line number Diff line number Diff line change
    @@ -133,3 +133,7 @@ export { default } from '~/modules/users/pages/show';
    // pages/company/[companyId]/[userId].tsx
    export { default } from '~/modules/users/pages/show';
    ```

    ## More resources

    - [Evolution of a React folder structure and why to group by features right away](https://profy.dev/article/react-folder-structure)
  3. zomars revised this gist Feb 22, 2022. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions modularized-nextjs-project-strucutre.md
    Original file line number Diff line number Diff line change
    @@ -75,6 +75,19 @@ import { DefaultLayout } from '~/modules/common';
    import { UserForm } from '~/modules/users';
    ```

    We would need to config `tsconfig.json` or `jsconfig.json` accordingly:

    ```json
    {
    "compilerOptions": {
    "baseUrl": ".",
    "paths": {
    "~/modules/*": ["modules/*"]
    }
    }
    }
    ```

    For this way of organizing to be scalable, certain guidelines must be followed when naming variables.

    - `components`: When a component belongs to a specific module it must have its model name at the beginning.
  4. zomars renamed this gist Feb 22, 2022. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  5. zomars created this gist Feb 22, 2022.
    122 changes: 122 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,122 @@
    # File structure

    The main file structure is organized as follows:

    ```bash
    ├── __test__
    ├── assets
    ├── configs
    ├── modules
    │ ├── common (Here is what is reused in various modules)
    │ │ ├── components
    │ │ │ ├── index.ts
    │ │ │ ├── Layouts
    │ │ │ └── (...generic components)
    │ │ ├── hooks
    │ │ │ ├── index.ts
    │ │ │ └── (...generic hooks)
    │ │ └── types
    │ │ ├── index.ts
    │ │ └── (...generic definitions)
    │ │ └── utils
    │ │ ├── index.ts
    │ │ └── (...helpers or generic utilities)
    │ └── users
    │ ├── actions.ts (API calls, caches, redux, etc.)
    │ ├── components
    │ │ ├── index.ts
    │ │ ├── Form.tsx (user form)
    │ │ ├── Table.tsx (user table)
    │ │ └── (...user components)
    │ ├── hooks
    │ │ ├── index.ts
    │ │ ├── useUserActions.ts
    │ │ └── (...user hooks)
    │ ├── pages
    │ │ ├── listing.tsx (user listing page)
    │ │ ├── new.tsx (page to add a user)
    │ │ ├── edit.tsx (page to edit a user)
    │ │ ├── show.tsx (page to display a user)
    │ │ └── (...other user pages)
    │ └── types
    │ ├── index.ts
    │ ├── responses.ts (user API responses)
    │ └── models.ts (definition of the user model)
    ├── pages
    └── public
    ```

    - `__tests__`: Tests to ensure that the app works correctly are included here.
    - `assets`: Here are the resources that need to be processed (e.g. SASS files, unminified images, SVGs, etc.)
    - `configs`: It is mainly used to store global settings that do not change often (e.g. main menu items, supported file types, etc.).
    - `modules`: Application-specific modules.
    - `pages`: Here we define the paths where the pages of the Next.js app will be.
    - `public`: These are the resources that will be copied as they are to the public root of the application.

    Most of the source code is inside the `modules` folder. When a new module needs to be added, it should be added here.

    Here is a practical example: You need to add "notifications" to the application, the first step would be to add a new "module" that will live in `modules/notifications`. Following this, you will need to add their respective parts such as `components`, `types`, `hooks`, `pages`, `actions`, etc.

    Each new module must have its own index `index.ts` in the root, as well as in each of its sub-directories:

    ```js
    // modules/notifications/index.ts
    export * from './actions';
    export * from './components';
    export * from './hooks';
    export * from './types';
    ```

    This allows us to have better control when importing parts from other modules:

    ```js
    import { useAuthActions } from '~/modules/auth';
    import { DefaultLayout } from '~/modules/common';
    import { UserForm } from '~/modules/users';
    ```

    For this way of organizing to be scalable, certain guidelines must be followed when naming variables.

    - `components`: When a component belongs to a specific module it must have its model name at the beginning.
    - Examples:
    - `UserTable`
    - `UserFilter`
    - `UserForm`
    - etc.
    - `hooks`: Every hook must begin with the word `use`, followed by the model e.g. `User`, `Notification`, etc. (or if it is a common hook it can be omitted) and ending with the action or subject to be used.
    - Examples:
    - `useUserActions`
    - `useEffectOnUpdate`
    - `useAuthUser`
    - `useSession`
    - `useAPIData`
    - etc.
    - `actions`: The actions of a module should be named first with the verb to be performed (`get`, `update`, `delete`, etc.) followed by the name of the module. Examples: `updateUser`, `createUser`, `deleteNotification`. This in turn allows us to standardize the actions that can be performed in each model and control the consequences of these actions in one place (e.g. update caches, modify status, send notifications, etc.).

    ## Why have `pages` inside `modules`?

    Having the pages separate from the directory provided by Next.js ensures that the application paths are independent of the views. This gives us some flexibility, for example: to change the user listing path from `/config/users` to `/users`, we simply move the `/config/users/index.tsx` file to `/users/index.tsx` without needing to modify the `import` of the listing. In this case the `index.ts` file simply re-exports the list to be displayed:

    ```js
    // pages/users/index.tsx
    export { default } from '~/modules/users/pages/listing';
    ```

    Or if you need to run some Next.js method like `getServerSideProps` it is also re-exported from the same file:

    ```js
    // pages/users/index.tsx
    export { default, getServerSideProps } from '~/modules/users/pages/listing';
    ```

    Another use case would be that some view is visible in two different paths, for example: the detail of a user can be visible in `/users/[userId]` or in `/company/[companyId]/[userId]`.

    ```js
    // pages/users/[userId]/index.tsx
    export { default } from '~/modules/users/pages/show';
    ```

    ```js
    // pages/company/[companyId]/[userId].tsx
    export { default } from '~/modules/users/pages/show';
    ```