Next.js in Turborepo with Chakra UI & TailwindCSS

Ujjwol Kayastha
wesionaryTEAM
Published in
8 min readJul 4, 2022

--

Hello everyone 👋, in this tutorial, we are going to build a monorepo using Turborepo and then add Next.js projects and integrate Chakra UI and TailwindCSS with toppings by setting up shared TS, eslint, husky pre-commits configurations.

Overview:

  1. Setup turborepo monorepo with Next.js applications.
  2. Setup TailwindCSS
  3. Setup shared typescript configuration, eslint configuration, husky pre-commits, and shared UI library
  4. Integrate Chakra UI and TailwindCSS in the project.

Turborepo

Monorepos that make ship happen.
Turborepo is a high-performance build system for JavaScript and TypeScript codebases. — turborepo.org

Turborepo is a blazing fast build system for JavaScript/TypeScript monorepos: codebases containing multiple projects, often using multiple frameworks, in a single unified code repository.

Why Turborepo?

  • Fast incremental builds with content-aware hashing: Turborepo builds the app from the cache if the caching hashis not altered. This makes the build of the application fast by determining and figuring out what needs to be built.
  • Zero runtime overhead: Turborepo doesn’t interfere with our runtime code or touch our source maps. It only does what it needs to do.
  • Parallel execution: Execute builds using every core at maximum parallelism without wasting idle CPUs.
  • Other reasons to use Turborepo are enlisted in the docs here.

Let’s start by creating a Turborepo monorepo with the following command:

npx create-turbo@latest

This command will first ask us where we want to create our turborepo and then it will ask which package manager we’d like to use. (I chose yarn, you can choose: npmor pnpm(Personal preference).

Once the setup is complete, we can cd into the directory and open the project in IDE of your preference.

Let’s go ahead and talk about the folder structure and project created by turborepo.

  • apps: applications we have. By default, it creates docs and web applications which are both Next.js applications. Since we’ll be creating our own Next.js applications with tailwindcss setup, we’ll later delete these two and create our own.
  • packages: This is the file for shared configuration (eslint, tsconfig and a shared ui for the monorepo)
  • package.json: as we can see, this uses yarn workspaces. We have our dependencies and scripts here, which run the applications in apps directory and run its command.
  • turbo.json: Turbo configuration with pipelines: build, lint, dev. This is a powerful tool. It allows us to create ,dependsOn: hierarchial running of commands. In the screenshot above, build pipeline depends on [‘^build’], caret means: it depends on topological dependencies to build first and then build ours. It makes sure all dependencies and dev-dependencies of a project are built first and then only runs the build script.

Now, let's remove the code that we won’t use in this project:

rm -rf node_modules apps/docs apps/web

Reason: We’ll add the Next.js application with typescript and tailwindcss configured. Let’s add the app by using the following command:

cd apps && yarn create next-app --example with-tailwindcss demo-app && cd ..

NOTE: In this tutorial, I’ll be showing the configuration file and setup for single project, but the process will be the same if we need no projects inside appsdirecotry.

This will create demo-app in our app's directory with typescript and tailwind configurations.

demo-app with tailwind and typescript configured

Now let us make slight updates to our package.json and next.config.js files in the demo-appproject. Let’s start by adding the name, versionattributes and then add ui and ts-config dependencies from the packages directory. Now your package.jsonand next-config.js file will look like this.

Now run: yarn install

Now let’s go ahead and create shared configuration files. Let's go-to packages directory where we have our typescript and eslint configurations. As we can see in the tsconfig folder, we’ve base.json which is extended by next.json. As we already have the code here, why make it redundant by adding the same code in demo-app project. So let/s change the tsconfig.json file in the project to look like this:

Prettier Configuration

Now, let’s add prettierrc.json file in the root directory. We don’t need to do anything as it was already installed when we ran turborepo setup. So just adding the file with configuration works like a charm. My prettierrc.json file looks like this:

Shared eslint configuration

As we’ve configured share typescript configuration, let’s go ahead and do the same for eslint configuration as well. We can add the configuration as per our requirements. But just for the demo, I’ve added a "no-console": 2 rule in packages/eslint-config-custom/index.js.

module.exports = { 
extends: ['next', 'prettier'],
rules: {
'no-console': 2,
'@next/next/no-html-link-for-pages': 'off',
'react/jsx-key': 'off',
},
};

Now create a .eslintrc.js file in demo-app's root directory and add the following lines of code.

What we are basically doing is extending the eslint configurationfrom the shared eslint-config-custom folder. Just for verification, we can add a console.log statement in our code: we get error as in screenshot below:

Means our shared eslint config is working 🎉

Shared Tailwind Configuration

We already have tailwindcss setup in our demo-app project.

In case we need next application, we need to share the tailwind configuration as well. Let’s go ahead and do this in this new section. Let's do this by adding dependencies we need to configure tailwind: postcss autoprefixer prettier-plugin-tailwindcss and tailwindcss. Add dependencies to uipackage using the following command:

yarn workspace ui add -D tailwindcss postcss autoprefixer prettier-plugin-tailwindcss

What this does is, add the dependencies in the packages/ui directory. Now, let’s go ahead and add tailwind configuration files in packages/ui:

postcss.config.js

module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

tailwind.config.js.

module.exports = {
content: [
'./**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
plugins: [],
}

Now, let’s import the shared config to tailwind.config.js in demo-app.

module.exports = {
...require('ui/tailwind.config'),
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'../../packages/ui/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
plugins: [],
};

Also, since we are using Next application: let’s update tsconfig.json file in packages/ui to take configuration form packages/tsconfig.

{
"extends": "tsconfig/nextjs.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}

To test, that it is working, let’s modify the button component in packages/ui as:

import * as React from 'react';export const Button = () => {
return <button className="rounded-full bg-blue-500">Boop</button>;
};

and use the component in the index.tsxin demo-app. We can see that our tailwindcss is working in our project. 🎉

Husky and lint-staged Setup:

Husky improves your commits and more 🐶 woof! — husky

Husky is a cool tool that allows us to manage how different hooks work with our GitHub repository so that we can add different scripts to run against different types of git hooks like pre-commit, commit-message, deploy, and so on.

lint-staged: what lint-staged does is instead of linting all files when we run lint, we could run lint-staged and it only lent the changed file so it saves us some time.

Now, let’s go ahead and add Husky and lint-staged to our project.

yarn add -D -W husky lint-staged

What this command does is, -W installs dependencies in root package.json.

Add 'prepare':'husky install' , script in scripts section in root package.json file. This runs and installs husky. Now, run to install husky.

yarn prepare
Verify that the husky the installed in the project

Also, it creates .husky folder in the root of the repository. To configure lint-staged, let’s go into our package.json file in the root directory and add the following code:

"lint-staged": {
"apps/**/*.{js,ts,jsx,tsx}": [
"eslint --fix"
],
"packages/ui/**/*.{js,ts,jsx,tsx}": [
"eslint --fix"
],
"*.json": [
"prettier --write"
]
}

What this actually does is it lints our projects in appsand packages/ui. Now let’s add the pre-commit hook using following command:

npx husky add .husky/pre-commit "npx lint-staged"

This command creates a pre-commit file in .husky directory:

This runs lint-staged against the files that are staged for git before letting the user commit. Now to test and verify, that our husky and lint-staged setup is actually running, let’s try to commit the changes in our project using following command:

git commit -am 'medium article setup turborepo, tailwind, lint, husky'

And just for verification, when I add console.log("TEST") in index.tsxand try to run the git commit, our lint-staged throws an error:

After removing the console log the commit is successful.

We can see that our pre-commit hook is working like a charm. 🎉

Now, let’s learn about ChakraUIand integrate into our very own application we created in this tutorial.

Chakra UI

Create accessible React apps with speed

Chakra UI is a simple, modular and accessible component library that gives you the building blocks you need to build your React applications. — chakra-ui.com

Now, let’s start by adding the chakra UI packages to our project by using the following command:
Note: -W flag installs the dependencies in our root package.json file.

yarn add -W @chakra-ui/react @emotion/react @emotion/styled framer-motion

Once, the setup is complete, we can see the dependencies in our package.json file. To test the setup, follow the following steps:

  1. Update _app.tsxfile in our Next.js project. Wrap it up with ChakraProvider.

2. Now, let’s update our button component with Chakra Button component.

3. Let’s use our button in the index.tsx page. Voila, we have our ChakraUI working like a charm.

Button component built with Chakra Button 🎉

Finally, we’ve our monorepo application built with Turborepo having Next.js application. We also setup shared typescript, eslint, tailwindcss configurations. And lastly, we setup the husky pre-commits.We then integrated ChakraUI in our application.

For reference, below is the Github repository link. If anything comes up, please feel free to leave your comment. Your feedback is really appreciated. 🙇 🙏

Github repo: https://github.com/UjjwolKayastha/next-chakra-tailwind

See you in next article. 👋 Happy coding. 👨🏻‍💻

--

--