Building Your Starter App with Next.js 🛠️

🌟 Follow these steps to create and set up your new Next.js starter app, complete with essential tools for a smooth development experience. 🔧

Steps to Setup

Step 1: Create a Next.js Application

npx create-next-app@latest

This command initializes a new Next.js project in a directory of your choice, setting up the necessary files and dependencies.

Step 2: Install Prettier and ESLint

npm i -D prettier eslint-config-prettier eslint-plugin-prettier

Install Prettier and ESLint along with the necessary configuration for integrating Prettier with ESLint.

Step 3: Install Tailwind CSS ESLint Plugin

npm install eslint-plugin-tailwindcss --save-dev

Ensure your Tailwind CSS classes are linted properly.

Step 4: Install Husky and Lint-Staged

npm i -D husky lint-staged

Husky helps enforce Git hooks, and lint-staged ensures that only staged files are linted and formatted.

Step 5: Initialize Husky

npx husky-init

This command creates a .husky directory with a pre-configured Git hook.

Step 6: Configure Pre-Commit Hook

npx husky add .husky/pre-commit 'npx lint-staged'

Add a pre-commit hook to run lint-staged, which will check your code before committing.

Step 7: Install Commitlint

npm install -D @commitlint/cli @commitlint/config-conventional

To enforce commit message conventions, install Commitlint and its conventional config.

Step 8: Configure Commit Message Hook

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

Add a commit message hook to validate your commit messages using Commitlint.

Step 9: Install Prettier Plugin for Tailwind CSS

npm i -D prettier prettier-plugin-tailwindcss

If you're using Tailwind CSS, install the Prettier plugin for Tailwind CSS.

Step 10: Install Commitizen

npm i -D commitizen

Commitizen helps create standardized commit messages.

Step 11: Install Conventional Changelog Adapter

npm i -D cz-conventional-changelog

Finally, install the Conventional Changelog adapter for Commitizen.

Step 12: Install Next Theme

npm install next-themes

Install Next Theme to enable easy light and dark theme toggling.

Step 13: Install Next PWA

npm install @ducanh2912/next-pwa

Install Next PWA for Progressive Web App support.

Configuration Files

ESLint Configuration (.eslintrc.json)

{
  "extends": ["eslint:recommended", "next",
   "next/core-web-vitals", "prettier"],
  "plugins": ["prettier", "tailwindcss"],
  "rules": {
    "prettier/prettier": "error",
    "tailwindcss/classnames-order": "warn",
    "tailwindcss/no-custom-classname": "off"
  }
}

Husky Configuration (.husky/pre-commit)

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

Husky Configuration (.husky/commit-msg)

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no-install commitlint --edit $1

Commitlint Configuration (commitlint.config.js)

module.exports = {
  extends: ["@commitlint/config-conventional"],
};

Prettier Configuration (.prettierrc)

{
  "plugins": ["prettier-plugin-tailwindcss"],
  "semi": true,
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "endOfLine": "lf",
  "jsxSingleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true
}

Next-Theme Configuration (theme-provider.tsx, layout.tsx)

// theme-provider.tsx
'use client';

import { ThemeProvider as NextThemesProvider }
from 'next-themes';
import { type ThemeProviderProps } 
from 'next-themes/dist/types';

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>
  {children}
  </NextThemesProvider>;
}

// layout.tsx
<body>
  <ThemeProvider
    attribute="class"
    defaultTheme="system"
    enableSystem
    disableTransitionOnChange
  >
    {children}
  </ThemeProvider>
</body>

PWA Configuration (next.config.js)

/** @type {import('next').NextConfig} */
const withPWA = require('@ducanh2912/next-pwa').default({
  dest: 'public',
  disable: process.env.NODE_ENV === 'development',
  register: true,
  scope: '/',
  cacheOnFrontendNav: true,
  aggressiveFrontEndNavCaching: true,
  cacheStartUrl: true,
  reloadOnOnline: true,
  swcMinify: true,
  fallbacks: {
    document: '/offline',
  },
});

const nextConfig = {
  reactStrictMode: true,
};

module.exports = withPWA(nextConfig);

Package Configuration (package.json)

{
    "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start -p 4000",
    "preview": "next build && next start -p 4000",
    "lint": "eslint src --ext ts,tsx,js,jsx --report-unused-disable-directives --max-warnings 0",
    "lint:fix": "eslint src --ext js,jsx,ts,tsx --fix",
    "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,css,html}'",
    "commit": "git cz"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "src/**/*.{ts,tsx,js,jsx}": [
      "npm run lint",
      "npm run format"
    ]
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  },
  "dependencies": {
    "@ducanh2912/next-pwa": "^10.2.9",
    "next": "14.2.15",
    "next-themes": "^0.3.0",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@commitlint/cli": "^19.5.0",
    "@commitlint/config-conventional": "^19.5.0",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "commitizen": "^4.3.1",
    "cz-conventional-changelog": "^3.3.0",
    "eslint": "^8",
    "eslint-config-next": "14.2.15",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.2.1",
    "eslint-plugin-tailwindcss": "^3.17.5",
    "husky": "^8.0.3",
    "lint-staged": "^15.2.10",
    "postcss": "^8",
    "prettier": "^3.3.3",
    "prettier-plugin-tailwindcss": "^0.6.8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  },
}

Continuous Integration (.github/workflows/ci.yml)

name: Continuous Integration

# Trigger CI on all kinds of branches and PRs
on:
  push:
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Fetch all history for all branches and tags

      - name: Cache node modules
        uses: actions/cache@v4

      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'

      - 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