Setup Production Ready Next.js App - Part 1
Tags: nextjs, javascript, webdev, beginners
Published: 2024-02-16 08:08:24

Creating a Next.js project is a single-line command. But taking it from there to production takes much more. This article explains different steps to create a robust Next.js project.

Completed project Github repo: [https://github.com/jobyjoseph/nextjs-boilerplate](https://github.com/jobyjoseph/nextjs-boilerplate). Each step here can be checked out with the corresponding branch name.

## 1. Create Next App

Baby steps first. Decide a project folder on your laptop. Navigate to the folder in terminal and run:

```
npx create-next-app@latest
```
> When asked for project name, if you do not want to create a new folder, just enter `.`

Give `No` for TypeScript and ESLint. We can add them later. Your answers look like:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eegnn8ps21377z12j6vm.png)

My package versions:

```json
"dependencies": {
    "react": "^18",
    "react-dom": "^18",
    "next": "14.1.0"
  }
```

You just created a Next.js app. Well done. 

## 2. Simple Home Page

When we install Next.js the home page looks like:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4gyb3kyk2v35auhtiqe.png)

Make it simple. Delete all contents of `app/page.js` and  paste below code React component code in `app/page.js`.

```javascript
export default function Home() {
  return <h1>Hello World</h1>;
}
```

Next, delete all contents of `app/layout.js` and replace it with:
```javascript
export const metadata = {
  title: 'Next.js',
  description: 'Generated by Next.js',
}

export default function RootLayout({ children }) {
 return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
```

Delete below 2 files:
1. page.module.css
2. globals.css

Now, we have a very simple home page. We cleaned up our project to start with very minimal files.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asr36t0unzhw68rdfjgm.png)

## 3. Lock Node.js Version
Team members might be using different versions of Node.js. We want to standardize it.

Create `.nvmrc` file in project root. Add just one line to that file.

```
lts/iron
```

Above setting helps a developer to easily switch to Node.js v20(lts/iron) if they do `nvm install`.

Next, go to `package.json` file and add `engine` details.

```json
"engines": {
    "node": ">=20.0.0"
  }
```
Now, if a developer tries to run the project using Node.js version 18, below error is displayed.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a8u5zsrg51450rrsv93v.png)

## 4. Stick with Yarn

It is not fun when the team uses both yarn and npm. It creates extra lock files and confusion.

Let us stick with yarn.

Create `.npmrc` in project root. Add just this line to strictly follow engine versions mentioned in package.json file.

```
engine-strict=true
```

And in package.json, `engines` section is updated to:

```
"engines": {
    "node": ">=20.0.0",
    "yarn": ">=1.22.0",
    "npm": "please-use-yarn"
  },
```

Now try, `npm install`. You will get this error.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ens952x7l82ul4xvbja.png)

This prevents the accidental creation of a package-lock.json file.

## 5. Setup ESLint

ESLint helps to catch many errors much earlier. You already will have a `yarn lint` command ready. Run it. If the command is not there, add it.

When asked, choose "strict" option.

It will install `eslint` and `eslint-config-next` as dependencies.

```json
"devDependencies": {
    "eslint": "^8.56.0",
    "eslint-config-next": "^14.1.0"
  }
```

Also an `.eslintrc.json` will be created with the below contents:

```json
{
  "extends": "next/core-web-vitals"
}
```

Now, run `yarn lint` again. The terminal says that everything is good.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scmhxembc93rp2idik6c.png)

**Testing one case:**

Let us check if Next.js catches a linting error. There is a [inline script id](https://nextjs.org/docs/messages/inline-script-id) rule. Let us violate that.

Go to `app/page.js`.

Add import to `next/script`.

```javascript
import Script from "next/script";
```

Use the `Script` tag without an id attribute inside JSX.

```javascript
<Script>{`console.log('Hello world!');`}</Script>
```

Save and run `yarn lint`. It throws error.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g8ap1e75wnmniklgh6vx.png)

So default Next.js linting is working. Undo the test code.

[Part 2](https://dev.to/jobyjoseph/setup-production-ready-nextjs-app-part-2-3e71)


## References
[How to Build Scalable Architecture for your Next.js Project](https://www.youtube.com/watch?v=Iu5aZDqZt8E)
[ESLint Next.js Documentation](https://nextjs.org/docs/app/building-your-application/configuring/eslint)