Start by creating a new nextjs project
Now let’s install everything.
npm install --save-dev prettier eslint-config-prettier husky lint-staged eslint-plugin-prettier
Now let’s create three files:
.prettierignore
,.eslintrc.json
, and.prettierrc
.Add this to your
.eslintrc.json
.{ "extends": ["eslint:recommended", "prettier", "next", "next/core-web-vitals"], "plugins": ["prettier"], "rules": { "prettier/prettier": "error" } }
Add this to your
.prettierignore
.#Ignore artifacts: dist .next/ public/ build #Ignore specific files: package-lock.json
Add this to your
.prettierrc
.{ "trailingComma": "es5", "useTabs": false, "tabWidth": 4, "semi": true, "singleQuote": true, "printWidth": 80, "bracketSpacing": true }
Now let's open
package.json
and write some scripts."scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "eslint src --report-unused-disable-directives --max-warnings 0", "lint:fix": "eslint src --fix", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,css,html}'" }
Now let’s open
eslint.config.js
to tell ESLint that we only want to lint files inside thesrc
folder and addfiles: ['src/**/*.{ts,tsx,js,jsx}']
. Your ESLint config array will look like this now:const eslintConfig = [ ...compat.extends('next/core-web-vitals', 'next/typescript'), { files: ['src/**/*.{ts,tsx,js,jsx}'], }, ];
Now let’s push our code to GitHub. The reason I’m doing this is that I want to show you how it will behave before and after configuring Husky.
Here, I’ve created a new GitHub repo and pushed everything there.
Now add hooks in the
package.json
file in the root directory alongside scripts and dependencies."husky": { "hooks": { "pre-commit": "lint-staged", "pre-push": "npm run lint && npm run format" } }, "lint-staged": { "src/**/*.{ts,tsx,js,jsx}": [ "npm run lint", "npm run format" ] }
Now run the
npx husky init
command. It will add a new folder to your project and add a new script to yourpackage.json
.Now add
npx lint staged
in yourpre-commit
file like thisNow let’s run
git add .
andgit commit -m '3rd commit'
to check if linting and formatting work.Now let’s check by adding an unused variable in
page.tsx
inside theapp
folder to see if our linting works.Run
git add .
andgit commit -m 'commit to check linting'
again.See the error:
a
is assigned but never read, and it is stopping us from committing.We can run
npm run lint:fix
to fix 90% of the linting errors because we’ve set up a script for that as well.Now, let’s remove the unused variable and try to commit and push.
Now, set the commit message policies so that people who push code to your repo follow certain commit message rules.
Install these two packages:
npm install --save-dev @commitlint/cli npm install --save-dev @commitlint/config-conventional
Now create a new file in the
.husky
folder and add:npx --no-install commitlint --edit "$1"
Create a new file
commitlint.config.cjs
in the root of the project and add this to your file:module.exports = { // extends: ['@commitlint/config-conventional'], extends: [], rules: { 'header-min-length': [2, 'always', 10], 'header-case-start-capital': [2, 'always'], 'header-end-period': [2, 'always'], }, plugins: [ { rules: { 'header-case-start-capital': ({ raw }) => { return [ /^[A-Z]/.test(raw), 'Commit message must start with a capital letter', ]; }, 'header-end-period': ({ header }) => { return [/\.$/.test(header), 'Commit message must end with a period']; }, }, }, ], };
This will ensure various things, such as: 'commit message must start with a capital letter,' 'should have a length of 10,' and 'ends with a full stop.'
Now let’s try to push something with a wrong commit message. Make sure you change something inside the
src
folder to trigger the hooks.And now, let’s fix the message and see.
Now let’s configure a CI pipeline. Create a
.github
folder and aworkflows
folder inside it. Then, create aci.yml
file inside theworkflows
folder.Paste this content in the file. You can ask ChatGPT to explain this file to you; it’s quite simple, to be honest.
name: CI workflow for Blog on: push: pull_request: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 # Fetch all history for all branches and tags - name: Use Node.js uses: actions/setup-node@v2 with: node-version: '20.17.0' - name: Install dependencies run: npm install - name: Run lint run: npm run lint - name: Run format check run: npm run format - name: Check commit messages uses: wagoid/commitlint-github-action@v3 with: configFile: commitlint.config.cjs
Now let’s test the CI pipeline we’ve created.
And let’s open the Actions tab in the GitHub repo.
We passed all the checks! LFG
Let’s try to learn about some warnings here (skip if you want). This wasn’t planned, but let’s address it and maybe upgrade our script according to them.
Warning 1: Ubuntu-latest pipelines will use ubuntu-24.04 soon
Details: GitHub is planning to update the default
ubuntu-latest
runner to useubuntu-24.04
. Currently, it likely usesubuntu-22.04
.This means that your workflow might soon start using Ubuntu 24.04 instead of the current version.
Warning 2: The set-output command is deprecated
Details: The
set-output
command was previously used in GitHub Actions to pass data between steps.GitHub has replaced this functionality with environment files, which are more secure and performant.
If your workflow uses an action or script that still relies on
set-output
, it will need to be updated.Fixing these using the new file—check code comments for changes.
name: CI workflow for Blog on: push: pull_request: jobs: build: runs-on: ubuntu-22.04 #replaced the latest to 22.04 steps: - uses: actions/checkout@v4 #updated version with: fetch-depth: 0 - name: Use Node.js uses: actions/setup-node@v4 #updated version with: node-version: '20.17.0' - name: Install dependencies run: npm install - name: Run lint run: npm run lint - name: Run format check run: npm run format - name: Check commit messages uses: wagoid/commitlint-github-action@v6 #updated version with: configFile: commitlint.config.cjs
So we are done here, and now let’s wrap up this blog by building a CD pipeline.
Go inside the
workflows
folder and create a new file calleddeploy.yml
. In this project, we will deploy to Vercel. Vercel deployment is really easy, but I want to give a sample of how things work here.name: CD Pipeline to Vercel on: push: jobs: deploy: runs-on: ubuntu-22.04 steps: - name: Checkout Repository uses: actions/checkout@v4 - name: Install Vercel CLI run: npm install --global vercel@latest - name: Pull Vercel Environment Information run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - name: Build Project Artifacts run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel run: vercel deploy --yes --prebuilt --token=${{ secrets.VERCEL_TOKEN }}
Now go to Vercel and get an access token. Name it
VERCEL_TOKEN
and paste this token in the GitHub repository secrets.And now, push the code to GitHub and see the magic happen in the Actions tab.