Smart dev-server overlay for ESLint and TypeScript errors.
npm install vite-plugin-lint-overlay
A Vite dev-server overlay that shows ESLint + TypeScript problems in an overlay.
- ✅ ESLint diagnostics
- ✅ TypeScript diagnostics (optional)
- ✅ Uses own worker threads: one for ESLint, one for TypeScript
- ✅ Runs on dev start, file events, and browser reload
src="https://raw.githubusercontent.com/max-matinpalo/vite-lint-overlay/main/assets/example.png"
width="480"
alt="vite-plugin-lint-overlay example"
/>
``bash`
npm install -D vite-plugin-lint-overlay
Peer dependencies: vite, eslint, typescript.
/ vite.config.ts)`js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import lintOverlay from 'vite-plugin-lint-overlay';
export default defineConfig({
plugins: [
react(),
lintOverlay({
rootDir: 'src',
ts: true, // default false, enables typescript
tsconfigPath: 'tsconfig.app.json',
})
]
});
`
| Option | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| rootDir | string | 'src' | Root directory to watch and lint for ESLint issues. |boolean
| ts | | false | Set to true to enable the TypeScript compiler check. |string
| tsconfigPath | | '' | Path to tsconfig. Defaults to tsconfig.json. |
The plugin runs only in vite dev. It injects a small client UIvirtual:lint-overlay-client.js
into the page via a virtual module () and transformIndexHtml.
On the server side it starts an ESLint worker (lint-worker.js) and, if ts: true,ts-worker.js
a TypeScript worker (). Workers send { type: "SNAPSHOT", errors: [...] }smart-overlay:update
messages back to the plugin. The plugin merges TS + ESLint errors and pushes them to the
browser using Vite’s WebSocket custom event .
Lint triggers:
- Initial: LINT_ALL on server start.LINT_ALL
- On client connect (page load/reload/new tab): resend current state + .rootDir
- On file changes inside matching .(js|jsx|ts|tsx): LINT for that file.UNLINK
- On file delete: to clear cached results for that file.
ESLint lints files inside rootDir (default: src).
When do we lint?
- Dev start: lint all matching files.
- Browser reload / new tab: lint all again, so the overlay reflects reality after refresh.
- File edits: lint only the changed file (add/change). On delete/unlink, we drop cached results for that file.
Which files are included in “lint all”?
All files under rootDir that match:*/.{js,jsx,ts,tsx}
-
Why not “dependency-aware” linting?
TypeScript --watch understands the project graph and re-checks all impacted files when one file changes.
ESLint does not automatically track “this change in file A affects file B”, so linting only the edited file can miss new issues in other files until they are scanned.
That’s why this plugin stays fast on edits (single-file lint) but still runs full scans on start and on browser reload.
TypeScript runs in a separate Node worker using the TypeScript watch API (createWatchProgram).tsconfig
It loads your (auto-detects tsconfig.app.json / tsconfig.json or uses tsconfigPath)
and publishes a fresh diagnostics snapshot whenever the program updates.
Because it’s watch-based, TypeScript automatically re-checks all affected files via the project graph.
The plugin code is tiny! 🪶 Since eslint and typescript` are peer dependencies, it reuses the packages already in your project to save disk space and prevent unnecessary bloat.
MIT