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
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
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 | π οΈ | π οΈ |
Install the dependency and trigger husky
npm install && npm prepare
Run the project
npm run dev
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 |
By default, you will got an error when the commit format is wrong. See the rules commitlint.config.js
We implement the eslint to enforce React best practice is applied in the project. The config stored in eslintrc.json
- For the import rules, check
"simple-import-sort/imports"
fromrules
- For the test id format, check
"testing-library/consistent-data-testid"
fromrules
β input__email#
β
input__email
β
button__login
β
list__user
β
item__user1
- For the boolean props name, check
"react/boolean-prop-naming"
fromrules
β enabled
β
isEnabled
β
hasItem
- For the component function type, check
"react/function-component-definition"
fromrules
β function Component() {
return (
...
)
}
β
const Component = () => {
return (
...
)
}
- For the JS Doc, every interface or function should have a js-doc, check
"jsdoc/require-jsdoc"
fromrules
/**
* Used to store the main data after logged-in
*/
export interface IUserSlice {
/**
* User name
*/
name: string
/**
* Authorization token
*/
token: string
}
- For the export, we will throw you an error when the export is unused. check
"import/no-unused-modules"
fromrules
. 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"
}
}
],
- For the export should be in the last of the code. check
"import/exports-last"
fromrules
.
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
- Create a file in
/src/i18n/dictionaries/[lang].ts
e.g.ch.ts
- 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 your new content in dictionary type
/src/i18n/type.ts
, it will require you to update the dictionary in existing language - Open the existing dictionary
/src/i18n/dictionaries/{en|id}.ts
, add your content
const About = async ({ params }: INextPage) => {
const t = await getTranslation(params.lang)
return (
...
)
- Define the translation in the server
- 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>
)
- 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>
)
}
TBD
TBD
- run
npm uninstall eslint-plugin-simple-import-sort
- remove
"simple-import-sort"
fromplugins
ineslintrc.json
- remove
"simple-import-sort/imports"
fromrules
ineslintrc.json
- run
npm uninstall eslint-plugin-testing-library
- remove
""testing-library""
fromplugins
ineslintrc.json
- remove
"testing-library/*"
fromrules
ineslintrc.json
- run
npm uninstall eslint-plugin-jsdoc
- remove
""js-doc""
fromplugins
ineslintrc.json
- remove
"jsdoc/*"
fromrules
ineslintrc.json
- run
npm uninstall eslint-plugin-import
- remove
""import""
fromplugins
ineslintrc.json
- remove
"import/no-unused-modules"
fromrules
ineslintrc.json
- remove
"import/exports-last"
fromrules
ineslintrc.json