Package Exports
- ultracite
- ultracite/prettier
- ultracite/stylelint
Readme
Ultracite
Ultracite is a robust linting preset for modern TypeScript apps. It's comprised of configuration files for ESLint, Prettier and Stylelint. It is incredibly opinionated and strict, enforcing the maximum amount of type safety and code quality through ESLint rules and TypeScript compiler options. It is designed for Next.js apps, but can be used with any TypeScript project, such as React Native or Node.js.
Features
ESLint
Ultracite uses ESLint to enforce code quality and type safety. It includes a wide range of rules to ensure your code is consistent and error-free. Ultracite combines with pre-defined rulesets for ESLint, as well as the following plugins: Import, jsx-a11y, React, React Hooks, jest, promise, n, Typescript, Prettier, Next.js, Cypress, HTML, SonarJS, Compat, Unicorn, GitHub and TanStack Query.
Prettier
Ultracite uses Prettier to format your code. It's configured to work with ESLint, so you can use both tools together without conflicts. Ultracite includes a pre-defined Prettier configuration that ensures your code is formatted consistently, as well as the Tailwind plugin for automatic class sorting.
Stylelint
Ultracite uses Stylelint to enforce CSS code quality. Ultracite combines with pre-defined rules for Stylelint, as well as the Stylelint-Prettier plugin to ensure Stylelint and Prettier work together without conflicts.
Installation
Run the command below to install Ultracite with peer dependencies:
pnpm add -D ultracite eslint@8 prettier stylelint typescript jest
If you're running VS Code, ensure you have the following extensions installed:
code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension bradlc.vscode-tailwindcss
code --install-extension stylelint.vscode-stylelint
Setup
Create an eslint.config.mjs
with the following contents:
export { default } from 'ultracite';
Create a prettier.config.mjs
with the following contents:
export { default } from 'ultracite/prettier';
Create a stylelint.config.mjs
with the following contents:
export { default } from 'ultracite/stylelint';
Ultracite is designed to be used with VS Code, and includes a .vscode/settings.json
file that enables full formatting on save. Create a .vscode/settings.json
file with the following contents:
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"emmet.showExpandedAbbreviation": "never",
"editor.codeActionsOnSave": {
"source.fixAll.esbenp.prettier-vscode": "explicit",
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"eslint.useFlatConfig": true,
"eslint.options": {
"overrideConfigFile": "eslint.config.mjs"
},
"eslint.runtime": "node"
}
Lastly, ensure your tsconfig.json
(if it exists) includes your new ESLint config and that strictNullChecks
is enabled.
{
"compilerOptions": {
"strictNullChecks": true
},
"include": ["eslint.config.mjs"]
}
Usage
Once Ultracite is set up, it will automatically format your code on save.
Configuration
You can opt-out of certain rules by modifying your eslint.config.mjs
file. For example, here's a common exception I use to avoid linting shadcn/ui components:
import ultracite from 'ultracite';
for (const config of ultracite) {
config.ignores = config.ignores || [];
config.ignores.push('./components/ui/**/*');
}
export { default } from 'ultracite';
Ultracite also lints the browser compatibility of your code. You can specify which polyfills exist in your project by modifying your eslint.config.mjs
file. For example, here's how you can add polyfills for Next.js:
import ultracite from 'ultracite';
for (const config of ultracite) {
config.settings = config.settings || {};
config.settings.polyfills = config.settings.polyfills || [];
config.settings.polyfills.push(
// These are from Next.js - https://nextjs.org/docs/architecture/supported-browsers#polyfills
'fetch',
'URL',
'Object.assign',
// This one is running on the server
'URLSearchParams'
);
}
export { default } from 'ultracite';
Debugging
If you're having issues with Ultracite, you can open the ESLint Output panel in VS Code to see what's going on. Optimally, it should look something like this:
[Info - 10:42:49 PM] ESLint server is starting.
[Info - 10:42:49 PM] ESLint server running in node v18.15.0
[Info - 10:42:49 PM] ESLint server is running.
[Info - 10:42:50 PM] ESLint library loaded from: /Users/haydenbleasel/GitHub/ultracite/node_modules/.pnpm/eslint@8.51.0/node_modules/eslint/lib/unsupported-api.js
If you see any errors, it could be related to peer dependencies or changes in dependency versions. Feel free to report these as issues.
Usage in Monorepos
If you're using Ultracite in a monorepo, you will need to do two things:
- Place the files above in every package and application, as well as the root.
- Add the following to your
.vscode/settings.json
file:
{
"eslint.workingDirectories": [
{
"mode": "auto"
}
]
}
This will ensure ESLint works correctly in all packages and applications by automatically detecting the working directory based on the nearest package.json
and eslint.config.mjs
, thus limiting the scope of ESLint to the current package or application and improving performance.