loading...
Cover image for An easy React 17 + TypeScript + Tailwind CSS + NextJS setup
CodeChem

An easy React 17 + TypeScript + Tailwind CSS + NextJS setup

nikolovlazar profile image Lazar Nikolov Originally published at blog.codechem.com ・5 min read

NextJS is becoming a de facto framework for modern web development. In this article we will build a starter repo that you can use for every new project.

Tech Stack:

Creating a new project

As with any new project, we'll create a new directory for our starter repo and initialize it with npm/yarn:

mkdir next-ts-starter
cd next-ts-starter
yarn init
Enter fullscreen mode Exit fullscreen mode

Hit enter on everything if you don't want to configure your npm package yet.

This will create a package.json file for you. That's all we need to start adding the other packages.

Setting up TypeScript

We'll add the TypeScript packages first, so later we can immediately add the typings. First, let's add the TypeScript package as a dev dependency:

yarn add --dev typescript
Enter fullscreen mode Exit fullscreen mode

Then, we will need to create a new file in the root directory called tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "sourceMap": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Now let's start adding our packages.

Installing React

Installing react is straightforward. We'll only need to add the following npm packages:

yarn add react react-dom
Enter fullscreen mode Exit fullscreen mode

And the TypeScript support packages:

yarn add --dev @types/node @types/react
Enter fullscreen mode Exit fullscreen mode

Setting up Next JS

First, we'll need to add the Next JS package:

yarn add next
Enter fullscreen mode Exit fullscreen mode

Now let's go back to packages.json and add the Next JS scripts:

...
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
},
...
Enter fullscreen mode Exit fullscreen mode

Then we'll need to create a next-env.d.ts file for the types:

/// <reference types="next" />
/// <reference types="next/types/global" />
Enter fullscreen mode Exit fullscreen mode

And optionally, we can create the next.config.js file in which we can extend the webpack config, or add our environment variables:

module.exports = {
  distDir: 'build',
  publicRuntimeConfig: {
    // add your public runtime environment variables here with NEXT_PUBLIC_*** prefix
  },
  webpack: (config) => {
    // extend your webpack configuration here
    return config;
  },
}
Enter fullscreen mode Exit fullscreen mode

Now let's create the initial page and test if it works. Create a new directory called pages in the root, and inside create an index.tsx file:

import { FC } from 'react';

const IndexPage: FC = () => {
    return <h1>Hello, CodeChem!</h1>;
};

export default IndexPage;
Enter fullscreen mode Exit fullscreen mode

Tip: as with React 17, you don't need to add "import React from 'react';" in your component files anymore!

Okay so now let's execute yarn dev and head to http://localhost:3000. You should see the "Hello, CodeChem!" heading. And that means everything works fine and we're ready to move on.

Setting up Tailwind CSS

First, we'll need to install the tailwindcss package:

yarn add tailwindcss
Enter fullscreen mode Exit fullscreen mode

Optionally, we can create the empty tailwind.config.js file in the root directory:

module.exports = {
  important: true,
  purge: {
    content: ['./pages/**/*.tsx']
  },
  theme: {},
  variants: {},
  plugins: [],
  future: {
    purgeLayersByDefault: true,
  },
};
Enter fullscreen mode Exit fullscreen mode

Tip: to completely utilize the purging functionality, add your new folders in the second line with the tsx postfix.

Next, we'll need to install the postcss-import package:

yarn add postcss-import@^12.0.0
Enter fullscreen mode Exit fullscreen mode

At the time of writing this article, postcss-import version 13.0.0 is breaking the tailwind implementation, therefore we will explicitly use the ^12.0.0 version.

Then create a new file postcss.config.js file:

module.exports = {
  plugins: [
    'postcss-import',
    'tailwindcss',
    'autoprefixer',
  ],
};
Enter fullscreen mode Exit fullscreen mode

In order to include Tailwind into our app, first we'll need to create a new CSS file in the root directory that includes Tailwind CSS. You can name this as you wish. We'll name it global.css for now:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
Enter fullscreen mode Exit fullscreen mode

Now, in order to include it in our app, we'll need to override Next JS's _app.tsx page by creating a new file: pages/_app.tsx:

import { FC } from 'react';
import { AppProps } from 'next/app';

import '../global.css';

const App: FC<AppProps> = ({ Component, pageProps }: AppProps) => <Component {...pageProps} />;

export default App;
Enter fullscreen mode Exit fullscreen mode

So to validate that everything works, let's head back to index.tsx and add a tailwind class to the <h1>Hello, CodeChem!</h1> like so:

<h1 className="text-green-500">Hello, CodeChem!</h1>
Enter fullscreen mode Exit fullscreen mode

Execute yarn dev and go to http://localhost:3000. You should see the label with smaller font size than previously and with green text color.

Bonus

For better code consistency and developer experience, let's install and configure the Prettier and Eslint plugins to work with TypeScript.

Eslint

First, let's install Eslint and its React plugins:

yarn add --dev eslint eslint-plugin-react eslint-plugin-react-hooks
Enter fullscreen mode Exit fullscreen mode

Then we need to add Eslint's typings:

yarn add --dev @typescript-eslint/eslint-plugin @typescript-eslint/parser
Enter fullscreen mode Exit fullscreen mode

With that in place, let's create the Eslint config file .eslintrc.js in the root directory:

module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
      'plugin:react/recommended',
      'plugin:@typescript-eslint/recommended',
      'plugin:react-hooks/recommended',
  ],
  parserOptions: {
      ecmaVersion: 2020,
      sourceType: 'module',
      ecmaFeatures: {
          jsx: true,
      },
  },
  rules: {

  },
  settings: {
      react: {
          version: 'detect',
      },
  },
};
Enter fullscreen mode Exit fullscreen mode

And that's it! If you're using Visual Studio Code and Eslint doesn't automatically start, a reload won't hurt.

Also, since you don't need to import React since React 17, Eslint might still suggest you do. In order to fix that, head to .eslintrc.js and add the following line in the rules section:

'react/react-in-jsx-scope': 'off',
Enter fullscreen mode Exit fullscreen mode

Prettier

To top it off, we'll add Prettier into the mix! Let's start by installing the Prettier package and the Eslint plugin:

yarn add --dev prettier eslint-config-prettier eslint-plugin-prettier
Enter fullscreen mode Exit fullscreen mode

Now let's create a .prettierrc.js file in the root directory:

module.exports =  {
    semi: true,
    trailingComma: 'all',
    singleQuote: true,
    printWidth: 120,
    tabWidth: 4,
    quoteProps: 'preserve'
 };
Enter fullscreen mode Exit fullscreen mode

And to configure Eslint to work with Prettier, let's head back to .eslintrc.js to add the Prettier extensions in the extends array:

'prettier/@typescript-eslint',
'plugin:prettier/recommended',
Enter fullscreen mode Exit fullscreen mode

Your final .eslintrc.js should look like this:

module.exports = {
    parser: '@typescript-eslint/parser',
    extends: [
        'plugin:react/recommended',
        'plugin:@typescript-eslint/recommended',
        'plugin:react-hooks/recommended',
        'prettier/@typescript-eslint',
        'plugin:prettier/recommended',
    ],
    parserOptions: {
        ecmaVersion: 2020,
        sourceType: 'module',
        ecmaFeatures: {
            jsx: true,
        },
    },
    rules: {},
    settings: {
        react: {
            version: 'detect',
        },
    },
};
Enter fullscreen mode Exit fullscreen mode

And that's it! You can push this in a separate GitHub project and use it as a starter for your new projects.

Discussion

pic
Editor guide
Collapse
rtivital profile image
Vitaly Rtishchev

I think you do not need this, since you are using typescript parser:

parserOptions: {
        ecmaVersion: 2020,
        sourceType: 'module',
        ecmaFeatures: {
            jsx: true,
        },
    },
Enter fullscreen mode Exit fullscreen mode
Collapse
nikolovlazar profile image
Lazar Nikolov Author

I do actually need that. Since I'm using the @typescript-eslint/parser, the default value for ecmaVersion is 2018, and the ecmaFeatures > jsx is false by default.

Collapse
dbshanks profile image
Derek Shanks

Thanks Lazar! This is a great setup. I converted to NextJS months ago. While it’s minimalistic in nature. There are still many discoveries yet to be made.

I’ve been trying really hard to make the TypeScript jump. Attempt #44 inbound. Haha!

It’s also nice to see another UI / UX dev make the jump to Tailwind! 🙌

Collapse
nikolovlazar profile image
Lazar Nikolov Author

I'm glad you like it man! Tailwind is amazing! Next JS as well. It does seem minimalistic in nature, but take a look at what blitzjs.com/ are doing! I'm building a small absence tracker for internal company use with that. I'm also thinking about starting a live stream where I build it in public.

Collapse
dbshanks profile image
Derek Shanks

Yeah I have been watching Blitz from the sidelines. Excited to see where that project goes. Happy it is NextJS under the hood.

Good luck on running a live stream.