Start New Next.js Project Notes
Tags: nextjs, typescript, eslint, husky
Published: 2021-05-16 15:33:13

Please read the [Getting Started](https://nextjs.org/docs/getting-started) guide, it is really good.

# Create a new app

Run `yarn create next-app` and follow the instructions.


# Move code to src folder

I like to keep all source code in one folder. Next.js [supports](https://nextjs.org/docs/advanced-features/src-directory) `src` folder by default. Create `src` folder and move `pages` and `styles` there.


# Add Typescript

Next.js [provides](https://nextjs.org/docs/basic-features/typescript) an integrated TypeScript experience out of the box.

Create TypeScript config file:
```
touch tsconfig.json
```

Next.js will automatically configure this file with default values.

Install dependencies:
```
yarn add --dev typescript @types/react @types/node
```

Run dev server with `yarn dev`. Next.js will generate `tsconfig.json` file for us.

Change `strict` inside `compilerOptions` to `true` if you want the real TypeScript experience. This option will prevent you from not specifying types and from using `any`.


# Add absolute imports

[Add](https://nextjs.org/docs/advanced-features/module-path-aliases) `baseUrl` parameter to the `tsconfig.json` config `compilerOptions`:
```
{
  "compilerOptions": {
    ...
    "baseUrl": "."
    ...
  }
}
```

Restart dev server with `yarn dev`. Now we should be able to import with an absolute path from the project's root.
```
import 'src/styles/globals.css'
```


# Add ESLint

```
yarn add --dev eslint @typescript-eslint/parser  @typescript-eslint/eslint-plugin eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y
```

- `eslint` is the main ESLint package
- `@typescript-eslint/parser` will allow ESLint to parse TypeScript files
- `@typescript-eslint/eslint-plugin` will add TypeScript specific lint rules
- `eslint-plugin-react` will add React specific lint rules
- `eslint-plugin-react-hooks` will add React Hooks rules
- `eslint-plugin-jsx-a11y` will add accessibility related rules

Create a `.eslintrc.js` config file:
```
module.exports = {
  root: true,
  env: {
    node: true,
    es6: true,
  },
  parserOptions: { ecmaVersion: 2020 },
  ignorePatterns: ['node_modules/*', '.next/*', '.out/*'],
  extends: ['eslint:recommended'],
  overrides: [
    // This configuration will apply only to TypeScript files
    {
      files: ['**/*.ts', '**/*.tsx'],
      parser: '@typescript-eslint/parser',
      settings: { react: { version: 'detect' } },
      env: {
        browser: true,
        node: true,
        es6: true,
      },
      extends: [
        'eslint:recommended',
        'plugin:@typescript-eslint/recommended',
        'plugin:react/recommended',
        'plugin:react-hooks/recommended',
        'plugin:jsx-a11y/recommended',
      ],
      rules: {
        'react/prop-types': 'off',
        
        // No need to import React when using Next.js
        'react/react-in-jsx-scope': 'off',

        // This rule is not compatible with Next.js's <Link /> components
        'jsx-a11y/anchor-is-valid': 'off',

        // Why would you want unused vars?
        '@typescript-eslint/no-unused-vars': ['error'],

        // I suggest this setting for requiring return types on functions only where useful
        '@typescript-eslint/explicit-function-return-type': [
          'warn',
          {
            allowExpressions: true,
            allowConciseArrowFunctionExpressionsStartingWithVoid: true,
          }
        ]
      }
    }
  ]
}

```


# Add Prettier

```
yarn add --dev prettier eslint-plugin-prettier eslint-config-prettier
```

Create a `.prettierrc.js` config file:
```
module.exports = {
  semi: false,
  trailingComma: 'none',
  singleQuote: true,
  printWidth: 100,
  tabWidth: 2,
  useTabs: false,
}
```

Add prettier to ESLint config:
```
module.exports = {
  // ...
  overrides: [
    {
      // ...
      extends: [
        // ...
        'plugin:prettier/recommended', // Prettier plugin
      ],
      rules: {
        // ...
        'prettier/prettier': ['error', {}, { usePrettierrc: true }], // Includes .prettierrc.js rules
      },
    },
  ],
}
```


# Add Husky

Add `lint` script to `package.json`:
```
{
  "scripts": {
    ...
    "lint": "tsc --noEmit && eslint 'src/**/*.{js,jsx,ts,tsx}' --fix"
  }
  ...
}
```

Add `lint-staged` config to `package.json`:
```
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "yarn lint"
    ]
  },
```

Install Husky and Lint-staged:
```
yarn add husky lint-staged -D
```

Add Husky pre-commit hook:
```
yarn husky install
yarn husky add .husky/pre-commit "yarn lint-staged"
```

Start development server `yarn dev` and enjoy coding! 🎉

P.S. Please checkout the [repo](https://github.com/vladimir-vovk/nextjs-starter) if you stuck. 🙌🏻

# Credits

Photo by <a href="https://unsplash.com/@giabyte?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Gia Oris</a> on <a href="https://unsplash.com/s/photos/start?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>