- Set up a new Next JS app with TypeScript (docs):
yarn create next-app --typescript
Copy and paste these settings into the project's .vscode
directory:
extensions.json
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"gruntfuggly.todo-tree",
"ecmel.vscode-html-css",
"eamodio.gitlens",
"analytic-signal.preview-mp4",
"josefbiehler.cypress-fixture-intellisense",
"tnrich.vscode-extension-open-cypress",
"jock.svg"
]
}
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Brave",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"runtimeExecutable": "C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe"
}
]
}
settings.json
{
"eslint.packageManager": "yarn",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"npm.packageManager": "yarn",
"typescript.tsdk": "node_modules\\typescript\\lib",
"npm.enableRunFromFolder": true,
"[svg]": {
"editor.defaultFormatter": "jock.svg"
}
}
- Install Sass (Next docs):
yarn add sass
This enables autocomplete for CSS/SCSS/Sass modules.
-
Install the plugin:
yarn add typescript-plugin-css-modules -D
-
Add the plugin to
tsconfig.json
:{ "compilerOptions": { "plugins": [{ "name": "typescript-plugin-css-modules" }] } }
-
Install Prettier:
yarn add --exact prettier -D
-
Create a new configuration file named
.prettierrc.json
and put this in it:{ "singleQuote": true, "jsxSingleQuote": true, "semi": false }
-
Create a new file named
.prettierignore
and copy the contents of .gitignore over to it. -
Add a new script to
package.json
:"format": "prettier --write ."
-
Execute the script with
yarn format
-
Execute
yarn lint
. This should set up a.eslintrc.json
file if it's not already there. -
Add the following to
.prettierignore
and.gitignore
# ES Lint .eslintcache
-
Install the Prettier config for ES Lint:
yarn add eslint-config-prettier -D
-
Add the Prettier configuration to
.eslintrc.json
:{ "extends": ["next/core-web-vitals", "prettier"] }
-
Run the following (docs):
npx mrm@2 lint-staged
-
Running the previous command adds a log file named
6
in the project's root directory. Delete it. -
Replace the default
lint-staged
settings inpackage.json
with this:"lint-staged": { "*.{md,html,css,scss}": "prettier --write", "*.{js,jsx,ts,tsx}": [ "prettier --write", "eslint --cache" ] }
-
Install Cypress (docs):
yarn add cypress -D
-
Add the following to your
.gitignore
and.prettierignore
files:# Cypress /cypress/videos /cypress/screenshots /cypress/downloads
-
Launch Cypress:
yarn run cypress open
-
In the Cypress application, choose the option to delete all the example files. Close the application.
-
Add the following to
cypress.json
:{ "$schema": "https://raw.githubusercontent.com/cypress-io/cypress/develop/cli/schema/cypress.schema.json", "baseUrl": "http://localhost:3000" }
-
In the
cypress/support
directory, convert the*.js
files to*.ts
files. -
Sometimes you will need to add custom Cypress commands. The types for these custom commands go in a file named
cypress/cypressCustomTypes.d.ts
. Create that file and put this in it:declare namespace Cypress { interface Chainable<Subject = any> { getInputByLabel(value: string): Chainable<Subject> } }
-
Add the following to
cypress/support/commands.js
:Cypress.Commands.add('getInputByLabel', (label: string) => { return cy .contains('label', label) .invoke('attr', 'for') .then((id) => { cy.get('#' + id) }) }) export {}
-
Create a new
cypress/tsconfig.json
file and put this in it:{ "extends": "../tsconfig.json", "compilerOptions": { "types": ["cypress"] }, "include": [ "../next-env.d.ts", "cypressCustomTypes.d.ts", "**/*.ts", "**/*.tsx" ] }
-
By default, Next will use the root directory
tsconfig.json
for type checking when it builds. This causes a problem because it will type check thecypress/
directory, and it is unaware of thecypress
types. As a workaround, create another file in the root directory namedtsconfig.build.json
and put this in it:{ "extends": "./tsconfig.json", "exclude": [ "node_modules", "cypress" ] }
-
Then, tell Next to use the
tsconfig.build.json
file when it builds the site innext.config.js
:module.exports = { typescript: { // The build process has its own tsconfig.json, which ignores the cypress directory. tsconfigPath: './tsconfig.build.json', }, }