Skip to main content
This guide covers the linting and code formatting setup using ESLint and Prettier.

Quick Reference

Running Linters

ESLint Configuration

The project uses ESLint 9 with the new flat config format (eslint.config.mjs).

Base Configuration

Plugins

The following ESLint plugins are configured:
  • @typescript-eslint - TypeScript-specific rules
  • angular-eslint - Angular best practices
  • eslint-plugin-import - Import/export validation
  • eslint-plugin-rxjs - RxJS best practices
  • eslint-plugin-rxjs-angular - Angular + RxJS patterns
  • eslint-plugin-tailwindcss - TailwindCSS class validation
  • eslint-plugin-storybook - Storybook configuration
  • @bitwarden/platform - Custom platform rules
  • @bitwarden/components - Custom component rules
See eslint.config.mjs:14-38 for plugin configuration.

Code Quality Rules

General Rules

Always Use Curly Braces

Rule: curly: ["error", "all"] (line 95)

No Console Statements

Rule: no-console: "error" (line 96) Exception: Console is allowed in libs/nx-plugin (line 329-333)

TypeScript Rules

No Floating Promises

All promises must be awaited or explicitly handled:
Rule: @typescript-eslint/no-floating-promises: "error" (line 89)

Promise Return Values

Don’t misuse promises in conditionals:
Rule: @typescript-eslint/no-misused-promises (line 90)

Member Accessibility

Omit public keyword, be explicit about private and protected:
Rule: @typescript-eslint/explicit-member-accessibility (line 87)

Unused Variables

Unused function arguments are allowed (useful for interfaces):
Rule: @typescript-eslint/no-unused-vars: ["error", { args: "none" }] (line 93)

Import Rules

Import Ordering

Imports must be alphabetically sorted with newlines between groups:
Rule: import/order (line 98-119) Order:
  1. External packages (alphabetically)
  2. @bitwarden/* packages (alphabetically)
  3. src/** relative imports (alphabetically)
  4. Blank lines required between groups

Restricted Imports

The project enforces strict import boundaries to prevent circular dependencies.

Architecture Layers

Libs cannot import from apps:
See eslint.config.mjs:121-171 for path restrictions.

Library Dependencies

Each library has specific allowed dependencies: Common library - Base layer, cannot import from other libs:
See eslint.config.mjs:363-605 for complete dependency graph. Example violations:

Forbidden Patterns

Do not import from src/** across package boundaries:
Rule: no-restricted-imports (line 246-248, 696-711)

Custom Bitwarden Rules

Platform Rules

Required Using Statement

Must use using for disposable resources:
Rule: @bitwarden/platform/required-using: "error" (line 82)

No Enums

Prefer unions or const objects over enums:
Rule: @bitwarden/platform/no-enums: "error" (line 83)

No Page Script URL Leakage

Prevents URL leakage in browser extension context. Rule: @bitwarden/platform/no-page-script-url-leakage: "error" (line 84)

Component Rules

Theme Colors in SVG

SVGs must use theme color variables:
Rule: @bitwarden/components/require-theme-colors-in-svg: "error" (line 85) See Angular Patterns for more component rules.

Browser Extension Rules

Memory Leak Prevention

Don’t use addListener directly in popup context (Safari memory leak):
Rule: no-restricted-syntax (line 224-240) See eslint.config.mjs:216-242 for full configuration.

Background Script Globals

Background scripts cannot use window (service worker context):
Rule: no-restricted-globals (line 260-267)

Template Linting

TailwindCSS Validation

All tw-* classes must be valid TailwindCSS classes:
Rule: tailwindcss/no-custom-classname (line 195-202, 343-358) Whitelisted non-Tailwind classes:
  • bwi-* - Font icons
  • logo, logo-themed
  • file-selector
  • mfaType*
  • filter* (temporary)
  • tw-app-region*

Enforced Tailwind Patterns

Rules:
  • tailwindcss/enforces-negative-arbitrary-values: "error" (line 203)
  • tailwindcss/enforces-shorthand: "error" (line 204)
  • tailwindcss/no-contradicting-classname: "error" (line 205)
See eslint.config.mjs:175-213 for template configuration.

Prettier Configuration

Prettier is configured in .prettierrc.json:
Settings:
  • Print width: 100 characters
  • MDX files: Always wrap prose

Integration with ESLint

eslint-config-prettier disables ESLint formatting rules that conflict with Prettier:
This prevents conflicts between ESLint and Prettier formatting.

State Migration Rules

State migrations have special import restrictions to prevent breakage:
Migrations should rarely import from the main codebase to avoid future breaking changes. See eslint.config.mjs:633-652.

Ignored Files

The following paths are excluded from linting:
See eslint.config.mjs:655-688 for the complete list.

Cache Strategy

ESLint uses content-based caching for better performance:
Cache file: .eslintcache (gitignored)

Linter Options

Unused Disable Directives

Unused eslint-disable comments are treated as errors:
This prevents commented-out disable directives from being left in the code.

Parser Configuration

TypeScript Files

HTML Templates

Templates use Angular’s specialized parser for template syntax.

Next Steps