Project Awesome project awesome

Code Quality > Deslint

The design quality gate for AI-generated frontend code. 20 rules covering arbitrary colors/spacing/typography, design-system drift, responsive coverage, and WCAG 2.2 / 2.1 AA accessibility across React, Vue, Svelte, Angular, and plain HTML.

Package 2 stars GitHub

Deslint

CI npm License: MIT

Deslint is the verification layer for AI-generated code.

Deterministic design-system and accessibility rules, reproducible attestations, and a commit trailer your merge gate re-verifies. Runs inside the agent loop (MCP server for Claude Code, Cursor, Codex, Windsurf) and at the merge gate (GitHub Action). Catches spacing inconsistencies, typography drift, arbitrary colours, broken responsive layouts, WCAG accessibility failures, missing dark-mode coverage, and inline style violations in code generated by any AI coding tool.

Every scan now includes a Fix Plan: what can be auto-fixed immediately, what needs a design-token decision, which WCAG-mapped issues are merge risks, and where the highest design debt lives.

Zero LLM in the hot path. Zero code leaves your machine. Local-first, deterministic, framework-agnostic.

→ Live demo and docs: deslint.com

Quick Start

# One-shot launch readiness check (no install)
npx deslint launch-check
# Install
npm install -D @deslint/eslint-plugin @deslint/cli

# Set up config, scripts, and design system
npx deslint init
// eslint.config.js (ESLint v10+ flat config only)
import deslint from '@deslint/eslint-plugin';

export default [
  deslint.configs.recommended,  // all rules at 'warn'
  // ... your other configs
];
# Scan your project
npx deslint scan

# Scan only what changed since your base branch
npx deslint scan --diff origin/main

# Enforce an error budget
npx deslint scan --budget .deslint/budget.json

# Auto-fix violations
npx deslint fix --all

# Interactive fix (review each change)
npx deslint fix --interactive

# Tweetable scorecard, copied to clipboard
npx deslint share

# Emit a reproducible attestation artifact
npx deslint attest --stdout

deslint scan in text mode prints a prioritized Fix Plan and writes .deslint/report.html for a shareable local report with the same recommended next actions.

v0.8 Highlights

  • npx deslint launch-check — one-command launch-readiness scorer for AI-built frontends (alias of scan with a launch-readiness banner)
  • npx deslint share — copies a tweetable markdown scorecard to your clipboard
  • 3 new frontend-safety rules: no-dangerous-html (XSS), safe-external-links (rel guard, autofixable), iframe-sandbox
  • Validated against shadcn-ui/ui (3,110 .tsx files, 0 crashes, 0 parse errors)

v0.6 Highlights

  • Error budgets for CLI and MCP via scan --budget and enforce_budget
  • Diff-only scans via scan --diff <ref>
  • Reproducible attestations and Deslint-Compliance trailer helpers
  • GitHub Action trailer verification with optional strict-trailer
  • Fix Plan guidance in CLI output, PR comments, and HTML reports
  • Expanded MCP surface for compliance, rule metadata, prioritization, and budget vetoes

Rules (37)

Design system & layout (7)

Rule Description Auto-fix Default
no-arbitrary-spacing Flag hardcoded spacing values (p-[13px]) Yes warn
no-arbitrary-colors Flag hardcoded colors in Tailwind classes (bg-[#FF0000]) Yes warn
no-arbitrary-typography Flag arbitrary font size, weight, leading, tracking Yes warn
no-arbitrary-zindex Flag arbitrary z-index values (z-[999]) Yes warn
no-arbitrary-border-radius Flag arbitrary rounded-[7px] values Yes warn
no-inline-styles Flag style={{}} attributes; prefer utility classes No off
no-magic-numbers-layout Flag arbitrary numbers in grid/flex layout Yes warn

Consistency (7)

Rule Description Auto-fix Default
consistent-component-spacing Detect spacing divergence across components No warn
consistent-border-radius Detect mixed rounded-* values in same-type components No warn
consistent-color-palette Cap unique color families per file No off
no-conflicting-classes Detect contradictory Tailwind utilities (flex hidden) No warn
no-duplicate-class-strings Flag identical class strings repeated 3+ times in a file No off
max-tailwind-classes Cap utility classes per element No off
spacing-rhythm-consistency Detect mixed spacing sub-scales in same stack No off

Responsive & dark mode (3)

Rule Description Auto-fix Default
responsive-required Require responsive breakpoints on fixed-width containers No warn
dark-mode-coverage Flag elements missing dark: variants Yes off
missing-states Flag interactive elements missing hover/focus/disabled states No off

Accessibility — WCAG 2.2 mapped (16)

Rule WCAG Description Auto-fix Default
a11y-color-contrast 1.4.3 Check WCAG AA color contrast ratios No warn
image-alt-text 1.1.1 Flag <img> without alt or with meaningless alt text No warn
responsive-image-optimization 1.4.4 Require loading/width/height on <img> Yes warn
icon-accessibility 1.1.1 · 4.1.2 Require aria-label/aria-hidden on icons Yes warn
heading-hierarchy 1.3.1 · 2.4.6 Flag skipped heading levels (h1 → h3) No warn
form-labels 1.3.1 · 3.3.2 Match <label> to <input id>, walk ancestors No warn
autocomplete-attribute 1.3.5 Require autocomplete on identity/payment fields No warn
link-text 2.4.4 Flag generic link text (click here, read more) No warn
focus-visible-style 2.4.7 Flag outline-none without a focus indicator No warn
focus-trap-patterns 2.4.3 Require role="dialog" / aria-modal on overlays Yes warn
touch-target-size 2.5.8 Flag interactive targets smaller than 24×24 px No warn
prefers-reduced-motion 2.3.3 Require motion-reduce: variants on animations Yes warn
prefer-semantic-html 4.1.2 Prefer <button> / <nav> over <div> + ARIA No warn
lang-attribute 3.1.1 Require lang on root <html> Yes warn
viewport-meta 1.4.4 Flag user-scalable=no / maximum-scale=1 No error
aria-validation 4.1.2 Invalid roles, hallucinated aria-*, LLM typos No error

Frontend safety (3)

Rule Description Auto-fix Default
no-dangerous-html Flag dangerouslySetInnerHTML (XSS path on user-supplied input) No warn
safe-external-links Require rel="noopener noreferrer" on <a target="_blank"> Yes warn
iframe-sandbox Require a sandbox attribute on <iframe> No warn

Code quality (1)

Rule Description Auto-fix Default
max-component-lines Flag overly large components (default: 300 lines) No off

Auto-fix coverage: 14 of 37 rules auto-correct in place (the rest report only — adding a responsive breakpoint or naming a design token is a human decision).

Validation: tested across React/Next.js, Vue/Nuxt, Angular, and plain HTML codebases. No crashes observed in testing; false-positive rate has been low in the projects we've scanned, but we have not formally quantified it. Every rule is wrapped in try/catch. If you hit a false positive, please open an issue.

Design Health Score

Deslint computes a 0-100 Design Health Score across categories:

  • Spacing — consistency of padding, margin, gap values
  • Typography — adherence to type scale
  • Colors — design token usage vs. hardcoded values
  • Responsiveness — breakpoint coverage
  • Consistency — border-radius, z-index, component spacing

Accessibility-focused rules feed into these score buckets rather than living in a separate score category.

npx deslint scan
# Design Health Score: 92/100
# Spacing: 85 | Typography: 95 | Colors: 100 | ...

Framework Support

Framework Parsing Auto-fix Validated
React / Next.js Yes Yes Yes (multiple projects)
Vue / Nuxt Yes Yes Yes
Svelte Yes Yes Parser ready
Angular Yes Partial* Yes
Plain HTML Yes Yes** Yes (via @html-eslint/parser)

* Angular template parser nodes lack range — violations reported but auto-fix skipped on those rules.

** A handful of rules (consistent-component-spacing, consistent-border-radius, max-component-lines, missing-states, prefer-semantic-html) are JSX-only by design.

Packages

Package Description
@deslint/eslint-plugin ESLint rules for design quality
@deslint/cli CLI with scan, fix, diff scoping, budgets, reports, and attestations
@deslint/mcp MCP server for Cursor / Claude Code AI self-correction and budget enforcement
@deslint/shared Shared config, budget, compliance, trailer, and token utilities
@deslint/action GitHub Action for PR design reviews

MCP Server (AI Self-Correction)

Deslint includes an MCP server that enables AI coding tools to self-correct design violations:

# Install MCP server — auto-detects and configures Cursor and Claude Code
npx deslint-mcp install

Tools exposed:

  • analyze_file — lint a single file, get violations + score
  • analyze_project — scan entire project, get score + top violations
  • analyze_and_fix — analyze and auto-fix in one step
  • compliance_check — evaluate WCAG 2.2 / WCAG 2.1 AA coverage
  • get_rule_details — get rule metadata, docs URL, effort, and WCAG mapping
  • suggest_fix_strategy — prioritize fixes by impact and effort
  • enforce_budget — veto completion when the repo is over budget

GitHub Action

Add design quality checks to your PR workflow:

# .github/workflows/deslint.yml
name: Deslint design review
on:
  pull_request:
    branches: [main]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: jaydrao215/deslint/action@main
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          min-score: 80
          strict-trailer: true
          suggest-fixes: true          # one-click autofixes for safe rewrites
          require-signed: false        # flip to true once attestations are signed
          signer-identity: '^https://github\.com/<owner>/<repo>/\.github/workflows/.+$'

Posts a Design Health Score summary comment on every PR with a category breakdown, and drops inline review comments on the changed lines that introduced violations. Re-runs update the existing comment instead of spamming new ones. The PR comment also includes a Fix Plan so reviewers can see which command auto-fixes low-risk drift, which token decisions need a human, and which accessibility issues should block merge. When strict-trailer is enabled, the Action also verifies the head commit's Deslint-Compliance: trailer against a server-side re-scan.

One-click PR autofixes (suggest-fixes)

When an inline violation has an ESLint autofix, the Action renders the fix inside the review comment. The rendering depends on whether the fix is provably visually lossless:

  • identical — a bg-[#1A5276]bg-primary rewrite where the replacement token resolves (via designSystem.colors) to the same hex as the arbitrary value. Renders as a GitHub suggestion block so a reviewer can commit the fix in one click.
  • additive-safe — a prefers-reduced-motion fix that only wraps existing classes with motion-safe:. Also a one-click suggestion — users in the default state see no visual change.
  • heuristic — everything else (closest-match token swaps, opinionated rewrites). Rendered as a read-only code block with a "run deslint fix locally" nudge. Never a one-click suggestion, so a reviewer can't ship a pixel change they never saw.

Set suggest-fixes: false to suppress the fix block entirely and fall back to text-only violation comments.

Other Action inputs

Input Default Purpose
min-score 0 Fails the check below this Design Health Score (0–100).
strict-trailer false Fails when the head commit lacks a valid Deslint-Compliance: trailer or it does not match the server re-scan.
require-signed false Fails when .deslint/attestation.json is unsigned or the Sigstore signature does not verify.
signer-identity (empty) Regex the Sigstore cert SAN must match. Without it, any valid signer passes under require-signed: true.
signer-issuer (empty) Exact-match OIDC issuer URL (e.g. https://token.actions.githubusercontent.com).
agent-scorecard true Attributes violations to the authoring agent (Claude / Cursor / Codex / Copilot / Windsurf / humans) via git blame and renders a per-agent scorecard. Requires fetch-depth: 0.
token-drift true Diffs the designSystem block of .deslintrc.json between base and head and renders a token-drift section. Requires fetch-depth: 0.
suggest-fixes true Renders autofixes inside inline review comments. One-click suggestion blocks only for identical / additive-safe fixes; opinionated fixes render as read-only code blocks.

Performance

Project Size Scan Time Rate
74 files 0.45s 164 files/s
259 files 0.80s 324 files/s
1,700 files 3.33s 510 files/s
1,838 files 3.05s 602 files/s

Budget: < 15 seconds for 500 files. Actual: 25x under budget.

Development

# Prerequisites: Node.js >=20.19.0, pnpm >=9
pnpm install
pnpm build
pnpm test        # ~1,200+ tests across the workspace
pnpm lint
pnpm typecheck

Why Deslint?

The problem: AI code generators (Claude, Cursor, Copilot, v0, Bolt) produce working code — but drift from your design system, and nothing at the merge gate can objectively verify what they shipped. Visual regression tools tell you a screenshot looks wrong. "Ask Claude to review it" is circular. Deslint is the verification layer: deterministic rules produce reproducible scores, signed-ready attestations, and a commit trailer the merge gate re-verifies against the repo.

Why the positioning is durable:

  1. Verification, not linting. A verification layer can verify design tokens today, accessibility tomorrow, custom org standards next year — the positioning doesn't change when the set of things we verify grows.
  2. Deterministic by construction. An LLM-based reviewer can't produce a reproducible attestation. Zero LLM in the hot path is architectural, not a feature.
  3. Reads the same for a solo dev and for Deloitte. "My AI just wrote 400 lines; verify them" and "Our client deliverables come with signed proof of quality" are the same sentence applied to different scales.
  4. Proof, not claims. Attestations are byte-reproducible; the GitHub Action re-scans and verifies the commit trailer so an agent can't inflate its own score.

License

MIT

Back to ESLint