A full setup of Next JS with Redux, Tailwind, Material UI, PWA, and Docker
Published: 2023-04-02 18:11:12

The final code for this guide can be found here.

Next JS Banner
Pre-requisites before going forward:
You have a basic understanding of React.
You have Node (Version 10 or newer) and NPM installed.
Let’s get started
We will refer to our project directory as my_project.

First, we will set up Tailwind CSS as it comes directly with Next JS. Open your terminal and type the following:

npx create-next-app -e with-tailwindcss my-project
cd my-project
This will automatically configure your Tailwind setup based on the official Next.js example.

Configure Tailwind with a theme and config:
Let’s talk about the theme we will be using. This is the theme object:


The paper is the background color we can use for the elements that are present off-focus. Like the body color.

primary and secondary are objects that define the focus elements of our page. For example, you would use primary maincolor for the background of a card and then secondary main for a call to action button on the card.

error and fg(foreground) are colors for the text that will be in contrast to our primary and secondary colors.

These objects have a dark property for different combinations.

The breakpoints are for media queries. It is good practice to define custom breakpoints.

The purge array contains paths to all those files which might be using our tailwind classes. This is important as tailwind only keeps the classes we used when we build the app for production.

We add an extra ha object in the screens object. This will add an extra breakpoint using which we can prevent :hover from applying to devices that do not support them. Thus, ha:hover:text-2xl this will not increase font size on mobile devices when you tap them.

Don’t change the keys for the default theme yet. This is because this theme object has been made keeping Material UI’s theme structure in mind as MUI is a bit strict when it comes to theming. We will discuss that later.

Now you can configure tailwind to use this theme. Got to tailwind.config.js and replace everything with the code below:


You can find more about the theming here.

Next, we create a fileglobal.css in /styles/global.css . You will have to create the styles folder as well.


This will apply all the tailwind classes to your project. You can add more default styles here.

Finally, we need to import this CSS file into our project. Go to /pages/_app.js Remove the default tailwind import and Import the CSS at the top:

import "../styles/global.css";
...rest of _app.js
With this, our tailwind is set up in Next JS. You can find more information here.

Setting up Redux
Installing the libraries:

npm install next-redux-wrapper react-redux redux
To make redux work with async actions I will install redux-thunk:

npm install redux-thunk
Create a file named store.js in the root. Import the following things:

import { createStore, applyMiddleware } from "redux";
import { createWrapper } from "next-redux-wrapper";
import thunk from "redux-thunk";
The redux-thunk middleware helps us to use redux even with promises by providing with a dispatch function.

We need to create an action to dispatch. First, let’s create a helper file which will have a list of all ACTION_TYPES.

Create a folder helpers and a file utils.js in it. This will have utilities and some configs. Put this in it:

export const ACTION_TYPES = Object.freeze({
AUTH: "auth",
});
Let’s create a sample action for our redux. Create a folder actions in root and a file in it user_actions.js :


Notice how we get dispatch from redux-thunk . We can use it as many times we want in this function. Here we dispatch an action of type: AUTH and payload: some data . This will be directly passed to the reducer.

Next we need to create a reducer for our store. Create a folder reducers in the root and a file named default.js . Put this into it:


default.js
This will hold initialize and control the state of our store. A default state = {} has been passed initialized.

You can read about HYDRATE but in simple terms, it populates our state during app load and is automatically called by next-redux-wrapper .

Now create a index.js file in the reducers folder. Put this code:


We can make multiple reducers such as a user_reducer.js to store user data. Then we pass it to the combine reducers function which stores a union of all states.

Now we just need to pass this combined reducer to the store. Open store.js

Import your default reducer:

import reducers from "./reducers";
Create the store and apply the middlewares:

const createStoreWithMiddleware = applyMiddleware(
thunk
)(createStore);
Now we create the store and wrap it with next-redux-wrapper

const makeStore = (context) => createStoreWithMiddleware(reducers);
export const wrapper = createWrapper(makeStore, { debug: true });
This is how your store.js should look like:


Your redux is now set up.

You can refer to this guide for more configurations and advanced use cases.

Setting up Material UI for React in Next JS
Install the Material UI library:

npm install @material-ui/core
Next, we define the theme for Material UI. Create a file theme.js under the helpersfolder.


We define a similar theme with differences in breakpoints definition. This is because Material-UI uses a rigid theme. Read more here.

Now, we will create a Wrapper and use a layout with a header and footer.

You can create /Components/Header/Header.js and /Components/Footer/Footer.js files and export your header and footer components.

After this, create a folder hoc that will hold our custom wrappers. Create a file Layout.js in hoc :


Now, create a Wrapper.js in the hoc folder:


We define a function to accept a Component and return the wrapped component. This format is good if you want to do things like user validation for a particular page.

Here we provide our theme to the MUI’s ThemeProvider. We also call an action to the redux store using useDispatch hook and read the state through useSelector hook.