/nextjs-pro

Boilerplate to develop production nextjs application πŸ› οΈπŸŽ‰

Primary LanguageTypeScriptMIT LicenseMIT

Boilerplate or Starter Template for Next.JS

Production boilerplate/template to develop nextjs application πŸ› οΈπŸŽ‰. Next.js App Directory + TypeScript + ESLint + Prettier + Husky + Jest + Testing Library + Cypress + Storybook + Commitlint + VSCode + Tailwind CSS + Redux Tookit + RTK Query.

Click "Use this template" to use this template and getting the updates

Features

Developer experience first:

⚑ Next.js with App Router
πŸ”₯ Type checking TypeScript
πŸ’Ž Tailwind CSS to develop the UI
πŸŽ‰ Storybook for UI documentation
🦺 Unit Testing with Jest and React Testing Library
πŸ§ͺ E2E Testing with Cypress
πŸ—ΊοΈ Support multi language
βœ… Strict Mode for TypeScript and React 18
πŸ“ Linter with ESLint (default NextJS, NextJS Core Web Vitals, Eslint testing library, JS Doc, Import/Export)
πŸ’– Code Formatter with Prettier
🦊 Husky for Git Hooks
πŸš“ Lint git commit with Commitlint
πŸ—‚ VSCode configuration: ESLint, Prettier

Built-in feature from Next.js:
πŸ’‘ Absolute Imports using @ prefix
β˜• Minify HTML & CSS
πŸ’¨ Live reload
βœ… Cache busting
πŸ—ΊοΈ Sitemap.xml and robots.txt with next-sitemap

Installed Packages

Category Context Package Name Status
UI UI CSS Support Tailwind βœ…
State State Management Redux Toolkit and Redux Persist βœ…
State Data Fetching and Caching Tool RTK Query βœ…
Doc Component Documentation Storybook βœ…
Rules GitHub - Commit Rules Husky with Commitlint and ConventionCommit βœ…
Rules Eslint - Auto Sort Import Eslint auto import βœ…
Rules Eslint - Data Test ID format Eslint plugin testing library βœ…
Rules Eslint - Require JSDoc Eslint plugin JS Doc βœ…
Rules Eslint - Export Rules Eslint plugin import βœ…
Testing Unit Testing Jest βœ…
Testing Component Testing Jest and React Testing Library βœ…
Testing Automation Testing Cycpress βœ…
I18n Internationalization Language based on route e.g. /en, /id. in server with async and client with context and custom hooks useTranslation βœ…
Analytic Analytic Google Analytic βœ…
PWA Progressive Web Apps πŸ› οΈ πŸ› οΈ

Getting Started

Install the dependency and trigger husky

npm install && npm prepare

Run the project

npm run dev

Environments

Name Description
NODE_ENV e.g. production, development
NEXT_PUBLIC_API_BASE_URL e.g. https://dummyjson.com
NEXT_PUBLIC_WEB_BASE_URL e.g. https://didikmulyadi.com
NEXT_PUBLIC_GOOGLE_ANALYTIC_MEASUREMENT_ID e.g. G-XXXXXXX

Rules

Commit

By default, you will got an error when the commit format is wrong. See the rules commitlint.config.js

Eslint

We implement the eslint to enforce React best practice is applied in the project. The config stored in eslintrc.json

  1. For the import rules, check "simple-import-sort/imports" from rules
  2. For the test id format, check "testing-library/consistent-data-testid" from rules
❌ input__email#
βœ… input__email
βœ… button__login
βœ… list__user
βœ… item__user1
  1. For the boolean props name, check "react/boolean-prop-naming" from rules
❌ enabled
βœ… isEnabled
βœ… hasItem
  1. For the component function type, check "react/function-component-definition" from rules
❌ function Component() {
    return (
        ...
    )
}
βœ… const Component = () => {
    return (
        ...
    )
}
  1. For the JS Doc, every interface or function should have a js-doc, check "jsdoc/require-jsdoc" from rules
/**
 * Used to store the main data after logged-in
 */
export interface IUserSlice {
  /**
   * User name
   */
  name: string
  /**
   * Authorization token
   */
  token: string
}
  1. For the export, we will throw you an error when the export is unused. check "import/no-unused-modules" from rules. This rules is disabled for spesific path, the configuration is stored in .eslintrc.json
  "overrides": [
    {
      "files": [
        "./src/app/**/*.ts",
        "./src/redux/modules/**/*.api.ts",
        "./src/redux/modules/**/*.slice.ts",
        "./src/component/**/*.stories.ts"
      ],
      "rules": {
        "import/no-unused-modules": "off"
      }
    }
  ],
  1. For the export should be in the last of the code. check "import/exports-last" from rules.

Project Structure

nextjs-advance
β”œβ”€ .env.example
β”œβ”€ .eslintrc.json
β”œβ”€ .gitignore
β”œβ”€ .husky
β”‚  β”œβ”€ commit-msg
β”‚  └─ _
β”‚     β”œβ”€ .gitignore
β”‚     └─ husky.sh
β”œβ”€ .huskyrc
β”œβ”€ .prettierrc.json
β”œβ”€ .storybook
β”‚  β”œβ”€ main.ts
β”‚  └─ preview.ts
β”œβ”€ .swc
β”‚  └─ plugins
β”‚     └─ v7_windows_x86_64_0.98.5
β”œβ”€ .vscode
β”‚  └─ settings.json
β”œβ”€ commitlint.config.js
β”œβ”€ cypress
β”‚  β”œβ”€ downloads
β”‚  β”œβ”€ e2e
β”‚  β”‚  └─ app.cy.ts
β”‚  β”œβ”€ fixtures
β”‚  β”‚  └─ example.json
β”‚  β”œβ”€ support
β”‚  β”‚  β”œβ”€ commands.ts
β”‚  β”‚  β”œβ”€ component-index.html
β”‚  β”‚  β”œβ”€ component.ts
β”‚  β”‚  └─ e2e.ts
β”‚  └─ tsconfig.json
β”œβ”€ cypress.config.ts
β”œβ”€ jest.config.js
β”œβ”€ jest.setup.js
β”œβ”€ next.config.js
β”œβ”€ package-lock.json
β”œβ”€ package.json
β”œβ”€ postcss.config.js
β”œβ”€ public
β”‚  β”œβ”€ next.svg
β”‚  └─ vercel.svg
β”œβ”€ README.md
β”œβ”€ src
β”‚  β”œβ”€ app
β”‚  β”‚  β”œβ”€ favicon.ico
β”‚  β”‚  β”œβ”€ globals.css
β”‚  β”‚  β”œβ”€ robots.ts
β”‚  β”‚  β”œβ”€ sitemap.ts
β”‚  β”‚  └─ [lang]
β”‚  β”‚     β”œβ”€ about
β”‚  β”‚     β”‚  β”œβ”€ page.client.tsx
β”‚  β”‚     β”‚  └─ page.tsx
β”‚  β”‚     β”œβ”€ layout.tsx
β”‚  β”‚     └─ page.tsx
β”‚  β”œβ”€ component
β”‚  β”‚  β”œβ”€ button
β”‚  β”‚  β”‚  β”œβ”€ button.css
β”‚  β”‚  β”‚  β”œβ”€ button.stories.ts
β”‚  β”‚  β”‚  β”œβ”€ button.test.tsx
β”‚  β”‚  β”‚  β”œβ”€ button.tsx
β”‚  β”‚  β”‚  └─ __snapshots__
β”‚  β”‚  β”‚     └─ button.test.tsx.snap
β”‚  β”‚  └─ layouts
β”‚  β”œβ”€ config
β”‚  β”‚  └─ env.ts
β”‚  β”œβ”€ i18n
β”‚  β”‚  β”œβ”€ dictionaries
β”‚  β”‚  β”‚  β”œβ”€ en.ts
β”‚  β”‚  β”‚  β”œβ”€ id.ts
β”‚  β”‚  β”‚  └─ index.ts
β”‚  β”‚  β”œβ”€ index.tsx
β”‚  β”‚  └─ type.ts
β”‚  β”œβ”€ middleware.ts
β”‚  β”œβ”€ redux
β”‚  β”‚  β”œβ”€ libs.tsx
β”‚  β”‚  β”œβ”€ modules
β”‚  β”‚  β”‚  β”œβ”€ index.ts
β”‚  β”‚  β”‚  └─ user
β”‚  β”‚  β”‚     β”œβ”€ user.api.ts
β”‚  β”‚  β”‚     β”œβ”€ user.slice.ts
β”‚  β”‚  β”‚     β”œβ”€ user.type.reqres.ts
β”‚  β”‚  β”‚     └─ user.type.ts
β”‚  β”‚  └─ store.ts
β”‚  └─ types
β”‚     └─ common.ts
β”œβ”€ tailwind.config.js
└─ tsconfig.json

Guide

Internationalization / Translation

Add new language

  1. Create a file in /src/i18n/dictionaries/[lang].ts e.g. ch.ts
  2. Add your new language in /src/i18n/dictionaries/index.ts
const dictionaries = {
  ...
  ch: () => import('./ch').then((module) => module.default),
}

export const i18n = {
  ...
  locales: [..., 'ch'],
} as const

Add new content in dictionary

  1. Add your new content in dictionary type /src/i18n/type.ts, it will require you to update the dictionary in existing language
  2. Open the existing dictionary /src/i18n/dictionaries/{en|id}.ts, add your content

Access translation in the server

const About = async ({ params }: INextPage) => {
  const t = await getTranslation(params.lang)

  return (
    ...
  )

Access translation in the client

  1. Define the translation in the server
  2. Wrap your page component with translation
// src/app/[lang]/about/page.tsx
const About = async ({ params }: INextPage) => {
  const t = await getTranslation(params.lang)

  return (
    <TranslationProvider translation={t}>
      <AboutPage />
    </TranslationProvider>
  )
  1. Access the translation with custom hooks useTranslation
// src/app/[lang]/about/page.client.tsx
export const AboutPage = () => {
  const t = useTranslation()
  const tAbout = t.about

  return (
    <div>{tAbout['DICTIONARY_KEY']}</div>
  )
}

Remove Package Guide

Remove Material UI Guide

TBD

Remove Tailwind UI Guide

TBD

Remove Eslint Auto Import Rules

  1. run npm uninstall eslint-plugin-simple-import-sort
  2. remove "simple-import-sort" from plugins in eslintrc.json
  3. remove "simple-import-sort/imports" from rules in eslintrc.json

Remove Eslint Testing Library

  1. run npm uninstall eslint-plugin-testing-library
  2. remove ""testing-library"" from plugins in eslintrc.json
  3. remove "testing-library/*" from rules in eslintrc.json

Remove Eslint JS Doc

  1. run npm uninstall eslint-plugin-jsdoc
  2. remove ""js-doc"" from plugins in eslintrc.json
  3. remove "jsdoc/*" from rules in eslintrc.json

Remove Export Rules

  1. run npm uninstall eslint-plugin-import
  2. remove ""import"" from plugins in eslintrc.json
  3. remove "import/no-unused-modules" from rules in eslintrc.json
  4. remove "import/exports-last" from rules in eslintrc.json