Welcome to nextjs professional boilerplate, an open source template for nextjs. It is prepared with functionalities that will help you make quality code, and will facilitate the maintainability of the code. You can find versions with different functionalities among the branches. I hope you like it
You can find these things in the template:
- Next.js - Pre-configured, with default src and app router + Bundler analyzer
- TailwindCSS - By default, CSS Framework for rapid UI development
- CVA - To easily manage component variants
- Biome - To find and fix linting, formatting, and import order problems
- Typescript - By default, configured with strict types and with ts-reset for types safety
- Vitest and Testing Library - For unit tests and integration tests
- Storybook - To create tests and use cases for your components
- Husky - Configured to raise, git hooks for the pre commit, pre push and commit message
- Commitlint with Conventional commit - To maintain a clean and solid commit history
- Github Actions - Pre-configured actions for smooth workflows
- Zod - For type validation
- Zustand - To handle global states simply and cleanly
- T3 Env - Manage your environment variables
- Cypress - For End-to-End (E2E) testing
- NYC - For code coverage reports and management
To start using this template, follow the following steps:
- Fork & clone repository:
git clone https://github.com/<your_username>/<repo_name>.git
- Install the dependencies:
In this case you can use the package manager you want. I personally recommend
pnpm
pnpm install
- Run the development server:
pnpm dev
-
Open
http://localhost:3000
with your browser to see the result. -
The project uses husky and patch-package to automate git hooks and validate dependencies. This is executed, with the "postinstall" every time you do install:
npx patch-package && node setup-husky.js
If you do not want to run husky on every installation, remove this && node setup-husky.js
from the postinstall
in the package.json
The template has the following scripts available in the package.json
:
dev
: Starts the development server with Turbopack, ensuring colored output.build
: Builds the application for production.analyze
: Analyzes the bundle sizes for Client, Server, and Edge environments.start
: Starts the production server.lint
: Checks for linting, formatting, and import sorting issues using Biome.lint:fix
: Automatically fixes linting issues with Biome (may include unsafe changes).types:check
: Verifies TypeScript types without emitting files.clean
: Removes all generated files from.next
,out
,coverage
,.swc
, and.nyc_output
.commitlint:last
: Verifies if the last commit follows the commitlint rules.format
: Checks if the code follows the correct format using Biome.format:fix
: Automatically fixes formatting issues and organizes imports using Biome.prepare
: Runs the Husky setup script.unit:run
: Executes unit tests using Vitest.unit:watch
: Runs unit tests in watch mode.unit:coverage
: Runs unit tests and generates a coverage report.cy:open
: Opens the Cypress interface for running end-to-end tests.cy:run
: Runs Cypress end-to-end tests in headless mode.cy:serve:ci
: Starts the development server and runs Cypress tests in CI mode.cy:serve:app
: Starts the development server and opens Cypress in interactive mode.cover:unit
: Generates a coverage report for unit tests usingnyc
.cover:e2e
: Combines end-to-end test coverage withnyc
and prevents overwriting previous coverage data.cover:report
: Generates a combined coverage report for all tests.cover
: Cleans previous coverage data, runs unit and e2e tests, and generates a full coverage report.test:storybook
: Runs acceptance tests for Storybook.storybook
: Starts the Storybook development server on port 6006.storybook:serve
: Serves the pre-built Storybook at port 6006.build:storybook
: Builds the Storybook for deployment.postinstall
: Applies patches to external dependencies and runs theprepare
script.
/
├── __test__/ # In this folder all the tests
│ ├── app/ # The structure is a mirror of src
│ ├── components/
│ ├── lib/
│ ├── styles/
│ └── types/
├── .vscode/ # VSCode config folder
├── .github/ # GitHub folder
├── .husky/ # Husky Hooks
├── .storybook/ # Storybook folder
├── public/ # Public assets folder
├── src/
│ ├── app/ # Next JS App (App Router)
│ ├── components/ # React components
│ ├── lib/ # 3rd party libraries configuration
│ ├── styles/ # Styles folder
│ └── models/ # Types, Enums, Models, schemas
├── .editorconfig # Editor config
├── .nycrc.json # NYC configuration for code coverage
├── biome.json # Patterns eslint should ignore
├── cypress.config.ts # Cypress configuration
├── lint-staged.config.mjs # Lintstaged config
├── commitlint.config.cjs # Commit lint config and commit examples
├── coverage.mjs # Script to generate combined code coverage
├── env.ts # Environment variables config by t3-env
├── next.config.ts # Next config file
├── postcss.config.cjs # Postcss config file
├── README.md # README file
├── report-bundle-size.js # Script to analyze bundle size
├── setup-husky.js # Script to raise husky on start githooks
├── tailwind.config.mjs # Tailwind CSS configuration
├── vitest.config.ts # Vitest config
├── vitest-setup.ts # Vitest testing library setup
└── tsconfig.json # TypeScript configuration
The template does not force you to use a specific package manager so you can choose the one you want. This is why no lock file was uploaded.
However, if you are sure of the package manager you are going to use for the project. You can upload the lock file. And change the npx
commands to the one you are using.
In case you choose to use yarn
as a package manager you should add some things:
- Add this dependency:
yarn add postinstall-postinstall --save-dev
- Update post install:
You need to find the postinstall script and add the
-y
flag to it
"postinstall": "npx patch-package -y && node setup-husky.js"
If you have already decided on the package manager you use, you can consider adding this line to the end of your package.json
:
"packageManager": "<manager>@<version>"
Example:
You only need one, but I leave you examples for these 3 handlers:
"packageManager": "[email protected]"
"packageManager": "[email protected]"
"packageManager": "[email protected]"
We use Vitest for unit and integration tests, taking advantage of its fast performance and modern testing capabilities. For end-to-end (e2e) testing, Cypress is utilized, offering a reliable and robust browser testing framework. Additionally, we generate coverage reports using nyc, including a combined report for both unit and e2e tests.
Below are some examples of how to execute tests and generate coverage reports using pnpm
:
- Unit and Integration Tests: Execute tests with Vitest using
pnpm unit:run
or run them in watch mode withpnpm unit:watch
. - Unit Test Coverage: Generate a coverage report for unit tests with
pnpm unit:coverage
. - End-to-End (e2e) Tests:
- Open the Cypress interface with
pnpm cy:open
. - Run Cypress tests in headless mode with
pnpm cy:run
. - Start the app and run e2e tests in CI mode with
pnpm cy:serve:ci
.
- Open the Cypress interface with
- Combined Coverage Report:
- Generate a full coverage report (unit + e2e) by running
pnpm cover
. This cleans old reports, runs all tests, and generates a combined report. - Use
pnpm cover:report
to manually generate the combined report if coverage files already exist.
- Generate a full coverage report (unit + e2e) by running
- Storybook Tests: Run acceptance tests for Storybook with
pnpm test:storybook
.
The combined coverage report will be generated in the coverage
folder. Open the index.html
file inside the folder to view a detailed breakdown of test coverage for both unit and e2e tests.
This setup ensures comprehensive test coverage and streamlined testing workflows for both unit and end-to-end scenarios.
Storybook is a development tool that allows you to build and document user interface (UI) components in isolation. It is a kind of sandbox where you can develop and view your components independently of the rest of the application. This makes it easier to design, test, and document reusable components, allowing development and design teams to work more efficiently and collaboratively.
Storybook is not only useful for building and visualizing components, but also offers tools for automated testing, improving code quality and reliability. You can write your acceptance tests using storybook's play function. To run the storybook tests you may need to have playwright installed with (Example with pnpm):
pnpm exec playwright install --with-deps
Ready to run the Storybook tests, you must first have Storybook executed pnpm storybook
and in another terminal execute pnpm test:storybook
For styles, added Tailwind CSS, a CSS framework for quick styling. In case you need to use your own CSS, it is recommended to use CSS Modules.
The template comes by default with cva, clsx and tw-merge. These utilities serve to facilitate the creation of variants for your components, this will help you maintain a design system easily. Then CVA will simplify the process of creating variants for your design systems, without compromising CSS control.
The template comes by default with Zustand, a great state manager that is quite simple, but very powerful. This great state manager is the option I recommend but if you don't like it you can use whatever you want.
In case Zustand is not your grade, it leaves you with other good options:
-
Jotai: This global state management library developed for React, and is from the same creators of Zustand. It has an atomic approach based on the concept of atoms and offers a simple and granular API to manage its state, while still being highly optimized to reduce package size.
-
Recoil: Is a state management library developed by Meta, designed specifically for React applications. It allows you to create a data flow that flows from atoms (shared state) through selectors (pure functions) and towards your React components. Its key benefit is the ability to update components only when the state they are subscribed to changes, reducing unnecessary replays and keeping your application fast and efficient.
T3 Env is a library that facilitates the validation and transformation of environment variables at compile time, as well as checking their types. This tool ensures that your application uses the correct environment variables and that their values match the expected types, eliminating the risk of runtime errors due to incorrect use of these variables.
The configuration is managed in the env.js
file. You just need to define the variables for the client and server, and then import env
into any file in your project to use them.
If you have an error with the variables you will see a message similar to this in the console specifying the error:
❌ Invalid environment variables: { VARIABLE: [ 'Error message' ] }
Husky makes it easy to configure and manage these git hooks directly from your project, without having to do it manually in the file system. This will allow you to automate certain tasks, which normally can be easily forgotten.
In this case there is a script that automatically raises 3 hooks for you:
The pre-commit hook runs just before committing, allowing you to run a script to verify or modify the code. In this case, the hook executes the command
npx lint-staged
Lint staged is a tool that allows you to run linters or other code quality tasks only on files that are about to be committed. This makes the validation process more efficient, by only validating in each commit the files that were modified (Assuming that the previous files have already passed the linting process). For NextJS, you can change the lint staged configuration in the .lintstagedrc.cjs
file. In this case lint staged executes these two commands:
prettier --write --file "stagedFiles..."
Then
next lint --fix --file "stagedFiles..."
The commit-msg hook is executed before making a commit, but after validating the pre-commit, it allows you to validate the code message to maintain a convention in your project. The hook is running:
npx commitlint --edit
Comitlint is a tool used to ensure that commit messages follow a predefined format, such as semantic commits. This is useful for improving the readability and structure of messages, making it easier to maintain and understand project history.
The pre-push hook is executed just before executing the push and allows you to validate the complete code before sending it to the remote repository and even cancel the push if necessary. The hook is running:
npx tsc && npx jest --detectOpenHandles --passWithNoTests
In this case, only the tests are validated before pushing