The Nx Node/React Stack part 3 - Next
Tags: nextjs, nx
Published: 2023-07-22 17:27:40



Let's get straight to it
```shell
nx g @nx/next:app site
```
Here we are creating the next site application, this will be our frontend.

![Dialog CSS Library](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xaqmpk49vl2rfi4d56e3.png)
Choose `None` we don't want any of these format provided, we will set up tailwind later.

![Dialog App Router](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/voxqetd7kmrebvajcmp7.png)

Choose app router, if you would like to learn more about it visit the [docs](https://nextjs.org/docs/app)



## Tailwind Setup

Now we need to set up tailwind, we are also using `daisyui` component library built upon tailwind

```shell
npm install -D tailwindcss
npm i -D daisyui@latest
nx g @nx/react:setup-tailwind --project=site
```

now we go to `tailwind.config.js` inside the site app and paste the following boilerplate

```js
import { createGlobPatternsForDependencies } from '@nx/react/tailwind'
import join from 'node:path'

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: [
        join(
            __dirname,
            '{app}/**/*!(*.stories|*.spec).{ts,tsx,html}'
        ),
        ...createGlobPatternsForDependencies(__dirname),
    ],
    theme: {
        extend: {},
    },
    daisyui: {
        themes: [],
    },
    plugins: [require('daisyui')],
}
```

now go to `global.css` and replace the existing code with the following

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## App structure

Our structure will be a mix of [featured sliced design](https://feature-sliced.design/) and [redux app structure](https://redux.js.org/faq/code-structure) 

Firstly create a `src` dir inside `apps/site` then move the app inside the `src` Next will be able to capture it automatically.

You will end up with folder structure like the following:
```js
apps/site
├── public
├── src
│   └── app
```

Now we will add some other folders to structure our app.

```js
apps/site
├── public
├── src
│   └── app
│       └── layout.tsx
│       └── global.css
│       └── page.tsx
│       └── [pageName]
│           └── layout.tsx
│           └── page.tsx
│   └── hooks
│   └── components
│   └── shared
│       └── store
│       └── helpers
│   └── features
│       └── [featureName]
│            └── api
│            └── ui
│            └── model
|                └── slice.ts
|                └── types.ts
│            └── lib
│            └── commands
│            └── queries
│            └── index.ts
```


Now let's explain each one responsibility:

`app`: This is the app directory from Next.js check this [Next routing & layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required)

`shared`: This will contain any business logic or fetch library that will be shared across the features.
It will host the redux store and provider, 
> Side NOTE: make sure to wrap the children of layout.tsx component inside the store provider and add `use client` directive atop of the module; to be able to use `Redux Provider` as it lives only on `React Client Component`.

`hooks`: This will contain the React hooks, These are the ones that are only related to this monorepo, if you have for example check authorization hook this should be a global hook where you need to create shared next app to store it.

`components`: This will act like the `widget` directory in the [FSD](https://feature-sliced.design) the idea here you are storing here the pure components or components that access multiple selectors only to render, it must not contain business logic, these the presentational by design.

`features`: This is heavily inspired by redux features directory but it is a little different. 
It combines `presentational entities`.(e.g., User, Product, Order) and user interactions, actions that bring business value to the user.(e.g. SendComment, AddToCart, UsersSearch). you can do split them they same way [described here](https://feature-sliced.design/docs/get-started/overview) does. But here we are combining because we are not creating interfaces entirely for the frontend, instead we are sharing them via `shared` lib.
> You can think of it as `cross-cutting` domain but for UI.


The features contains the following directories

1. `lib`: Contains the data manipulation & presentational logic.
> This library and the entire front-end is totally isolated from the business logic, as we in later chapters show where it will live.

2. `commands`: You can think of them as the GraphQL Mutations related to the feature, let's say the feature is `cart` the commands would be for example `addToCart`, `removeFromCart` and `checkoutCart`, all commands start with a commanding verb like `create`, `modify`, `patch`, `replace` etc.

3. `queries`: These hold the presentational responsibilities `ui` dir. Meaning they will decide what to present or what needed to command the backend. The queries will start with the verb `get`, assuming we have a feature called product we will have queries like `getProductByName`, `getRecommendedProducts`.

4. `ui`: It is the feature's React components basically they are the components that depend upon the feature store where it will render some jsx, there are some unwritten rules here we need to address them, think of them as a simple <Button> but with store accessibility and an `onClick` action.  

- Components Should never take props or depend on other features' slices this violates [SRP](https://dev.to/ibrahimshamma99/the-single-responsibilty-principle-474n/edit)
- Components will present final results cooked in the slice, meaning it will not depend `useState` or the `lib`. The decision of what it will present was already made and stored inside the slice.

5. `model`: this dir will contain two modules
* `slice.ts`: where we will create the redux slice
* `types.ts`: this directory contains the extended types for the ui from the `shared` types

6. `api`: This directory will contain the async redux actions, this directory will depend upon the `lib`,`commands`,`queries` heavily.
Let's say we are working on an Markdown editor and we are creating an API that gets the file from the server look at the following:
* You will need to take the fetch lib or `executeQuery` from the `shared` dir
* The query statement and params will be managed in `queries` modules.
* `lib` will manage data post processing before the api 'stores' the result into the slice
* The `ui` will be accessing the respected `slice` and manages presenting the UI.


There are general rules to be followed here 

* All functions are `camelCase`, components are `PascalCase` and all `dir` are `kebab-case`

* outside the feature directory nothing can be imported directly, we are only exporting the ui components and the store, in this regard we are applying the following eslint rule in the coming parts of this series.
> Note each feature has one [barrel file](https://basarat.gitbook.io/typescript/main-1/barrel), if you put barrel file in `ui` folder and import it in the feature one, it may cause issues with bundling

* All feature ui components are `react client components` meaning each module will start with `use client`, because simply we are utilizing the user slice aka user state.
So Try to but in the feature component as much less UI as possible and leave the main components to take care the rest while utilizing [`RSC`](https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components)



## What else you would do to improve our template?


We as Engineers love to ask ourselves what else we can improve.

Here are some tips but not limited to:

1. Separate related components into a an independent `lib` this way need to import them dynamically and this can improve [FCP](https://web.dev/fcp/)

2. If the features are growing and changing, more teams are created with this rule, you need to look at various Micro-Frontend options, look at [Module Federation](https://module-federation.io/) where you can split your `app` into `mirco-apps` each has its own responsibilities and deployed independently, the special thing with module federation is that modules are imported in runtime.

3. Create an UI `lib` where will host all UI components needed for the entire app, this way you can share the same theme and colors across the app.




In summary, the provided guide not only aids in building a solid foundation for a frontend application but also emphasizes the importance of architectural decisions that can enhance collaboration, development speed, and the overall user experience. By embracing the recommended practices and considering future enhancements, developers can create a robust and adaptable frontend solution.