Configuring Next.js with Typescript, Tailwind CSS, ESLint, and Jest
Tags: react, css, javascript, tutorial
Published: 2020-12-05 13:28:51

---
title: Configuring Next.js with Typescript, Tailwind CSS, ESLint, and Jest
description: Learn to configure Next.js with Typescript, Tailwind CSS, ESLint, and Jest
canonical_url: https://blog.alexandrudanpop.dev/posts/configuring-next-js-with-typescript-tailwind-css-eslint-jest-46ob/
---

**Next.js** might be the best way to set up a new React project in 2020 & 2021. I don't even know if it's worth to appraise it even more, but yeah the Next.js team did a great job!

It just stands out with all the needed features to build bulletproof web applications: hybrid approach with SSR, SSG, ISR, hosting can be done on the **Vercel** platform on a serverless runtime. Static assets are where they belong, hosted in a CDN edge network for fast delivery. 🏃🏃🏃

> So let's configure Next with our favorite tools: Typescript & Tailwind CSS, and we'll use ESLint for lining and Jest to write tests.

## Setup Next.js with TS
Go to a terminal and run (replace *next-ts-tailwind* with your desired app name):
- `npx create-next-app next-ts-tailwind`
- `cd next-ts-tailwind`
- Create a `tsconfig.json` file:
`touch tsconfig.json`
```json
{
    "compilerOptions": {
      "allowJs": true,
      "alwaysStrict": true,
      "esModuleInterop": true,
      "forceConsistentCasingInFileNames": true,
      "isolatedModules": true,
      "jsx": "preserve",
      "lib": ["dom", "ES2020"],
      "module": "esnext",
      "moduleResolution": "node",
      "noEmit": true,
      "noFallthroughCasesInSwitch": true,
      "noUnusedLocals": true,
      "noUnusedParameters": true,
      "resolveJsonModule": true,
      "skipLibCheck": true,
      "strict": true,
      "target": "esnext"
    },
    "exclude": ["node_modules"],
    "include": ["**/*.ts", "**/*.tsx"]
  }
```

- Add TS dependencies
`yarn add --dev typescript @types/react @types/node`

- Go to /pages/index.js and change it to index.tsx

- Run `yarn dev` - all good and running on `http://localhost:3000/`

## Setting up Tailwind CSS
The Tailwind team already put together an [excellent tutorial](https://tailwindcss.com/docs/guides/nextjs) to set this up with Next.js, but there are just a few changes needed for it to work with TS files.

- `yarn add tailwindcss postcss autoprefixer`
- `yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9`
- `npx tailwindcss init -p`

- Go to `tailwind.config.js` and change `purge: [],` with:
` purge: ["./components/**/*.{js,ts,jsx,tsx}", "./pages/**/*.{js,ts,jsx,tsx}"],`
This makes sure that when we build for production **only** the classes that we use from the tailwind framework will remain in the final production css file. It's called *tree shaking* if you need a more fancy term to impress your grandma. 👵
- Include tailwind at the top of your ./styles/global.css file
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

- Go to your `pages/_app.js` (that you should rename to _app.tsx) component and make sure it looks like this:
```jsx
import "../styles/globals.css";
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;
```
- To test tailwind is working go to `index.tsx` and change it to:
```jsx
import Head from "next/head";
import styles from "../styles/Home.module.css";

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <div
        className="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4"
        role="alert"
      >
        <p className="font-bold">Be Warned</p>
        <p>You are using Tailwind CSS!</p>
      </div>
    </div>
  );
}
```

Running the app with `yarn dev` you should see: 
![tailwind example](https://dev-to-uploads.s3.amazonaws.com/i/18gjgdj3xvyhq95pzfr7.PNG)

## Setting up ESLint
- `yarn add --dev eslint` 
- Run `npx eslint --init` and answer with the following:

![initialize ESLint](https://dev-to-uploads.s3.amazonaws.com/i/6yt7uoumpylp3e7cl8nk.PNG)

Go to `package.json` and in the scripts section, add:
`"lint": "eslint ."`

Now, if you try `yarn lint`, you will see a bunch of errors. Go to `eslintrc.json` and modify it to:
```json
{
    "env": {
        "browser": true,
        "es2021": true,
        "node": true,
        "jest": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "parser": "@typescript-eslint/parser",
    "settings": {
        "react": {
            "version": "detect"   // Automatically detect the react version
        }
    },
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "@typescript-eslint"
    ],
    "rules": {
        "react/react-in-jsx-scope": "off",
        "@typescript-eslint/explicit-module-boundary-types": "off"
    }
}
```
Note that I also disabled the `explicit-module-boundary-types` because I like TS to do its job and infer the return types for me, but you can remove that if you like to always add return types to your functions. There will be other lint warnings that you will probably not like and turn off, that's totally fine.

Running `yarn lint` now should result in no warnings and errors. 

> Note that you should probably use the [ESLint VSCode extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) if you use VSCode. This way you can see errors and fix them as they pop-up while you code. 

## Adding Jest
- `yarn add --dev babel-jest jest @types/jest @types/babel-generator`
- in `package.json` scripts section - add `"test": "jest --watch"`
- create a `.babelrc` file in the root and add in it:
```json
{
    "presets": ["next/babel"]
}
```
- Create a `jest.config.js` with:
```js
module.exports = {
  setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
  testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/node_modules/"],
};
```

- And a `jest.setup.ts` with:
```js
import "@testing-library/jest-dom";
```

Next, let's add the **React testing** packages:
- `yarn add --dev @testing-library/react @testing-library/dom @testing-library/jest-dom @testing-library/user-event`

Create in the components folder a file `SomeComp.test.tsx` with:
```jsx
import { render } from "@testing-library/react";

function SomeComp() {
  return <div>Hello</div>;
}

describe("SomeComp", () => {
  it("renders Hello", () => {
    const { getByText } = render(<SomeComp />);
    expect(getByText("Hello")).toBeInTheDocument();
  });
});
```
Run `yarn test`:
 PASS  components/SomeComp.test.tsx
  SomeComp
    √ renders Hello (24 ms)

## Conclusions
If you got this far congrats - you have a Next.js app configured with TS, Tailwind CSS, ESLint, and the testing is set up with Jest and RTL. 🥳

If you got stuck or prefer to see the working solution directly you can check it out on [Github](https://github.com/alexandrudanpop/nextjs-ts-tailwind-eslint-jest).

I post more cool content on [Twitter](https://twitter.com/alexandrudanpop) 🔥🔥.