Skip to main content

ESLint

For AI agents: see llms.txt for the complete documentation index. Markdown versions are available by adding .md to a page URL or requesting Accept: text/markdown.

The Convex lint rules are an ESLint plugin, so ESLint supports every rule and autofix.

Setup​

Install the plugin with:

npm i @convex-dev/eslint-plugin --save-dev

For ESLint 9+ (flat config, using eslint.config.js), add this to your eslint.config.js file:

import { defineConfig } from "eslint/config";

import convexPlugin from "@convex-dev/eslint-plugin";

export default defineConfig([
// Other configurations

...convexPlugin.configs.recommended,
]);

ESLint needs a TypeScript parser to read your Convex functions. If your config doesn’t set one up yet, use the config in Type-aware linting below.

If you’re using the deprecated .eslintrc.js format

Install these two libraries:

npm i @typescript-eslint/eslint-plugin @convex-dev/eslint-plugin --save-dev

In .eslintrc.js, add:

module.exports = {
extends: [
// Other configurations
"plugin:@typescript-eslint/recommended",
"plugin:@convex-dev/recommended",
],
ignorePatterns: ["node_modules/", "dist/", "build/"],
};
If your Convex functions are in a directory other than convex

By default, the Convex ESLint plugin will only apply rules in the convex directory.

If you’re customizing the Convex directory location, here’s how to adapt your ESLint configuration:

// eslint.config.js
import { defineConfig } from "eslint/config";

import convexPlugin from "@convex-dev/eslint-plugin";

const recommendedConfig = convexPlugin.configs.recommended[0];
const recommendedRules = recommendedConfig.rules;

export default defineConfig([
// Other configurations go here...

// Custom configuration with modified directory pattern
{
files: ["**/src/convex/**/*.ts"],
plugins: {
"@convex-dev": convexPlugin,
},
rules: recommendedRules,
},
]);
If you’re using the next lint command from Next.js

For next lint to run ESLint on your convex directory you need to add that directory to the default set of directories. Add this section to your next.config.ts:

const nextConfig: NextConfig = {
/* other options here */

eslint: {
dirs: ["pages", "app", "components", "lib", "src", "convex"],
},
};

Type-aware linting​

Some rules use TypeScript type information to give more precise results: explicit-table-ids reads the table name from Id<"tableName"> types so it can fix calls for you, and no-collect-in-query (off by default) suggests replacements. The rules still work without it, but they fall back to matching code by name.

To turn it on, set up typed linting with typescript-eslint:

npm i typescript-eslint --save-dev
// eslint.config.js
import { defineConfig } from "eslint/config";
import tseslint from "typescript-eslint";

import convexPlugin from "@convex-dev/eslint-plugin";

export default defineConfig([
// Other configurations

{ ignores: ["convex/_generated/**"] },
{
files: ["**/*.ts"],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
...convexPlugin.configs.recommended,
]);

Type-aware linting is slower, since ESLint has to type check your code as it lints it.

Turning on more rules​

The recommended config leaves a few rules off, like no-collect-in-query and require-access-control. To turn one on, add it after the recommended config:

// eslint.config.js
export default defineConfig([
// Other configurations

...convexPlugin.configs.recommended,
{
files: ["**/convex/**/*.ts"],
rules: {
"@convex-dev/no-collect-in-query": "error",
},
},
]);