Skip to main content
The Bitwarden Clients codebase uses an Nx monorepo structure with a shared library architecture that enables code reuse across multiple client applications (Web, Desktop, Browser, CLI, and Mobile).

Library Architecture

Bitwarden’s core libraries are organized in the libs/ directory and provide shared functionality that can be consumed by any client application. This architecture follows the principle of Domain-Driven Design (DDD) and separation of concerns.

Key Libraries

Common Library

Platform abstractions, models, services, and business logic shared across all applications

Angular Library

Shared Angular components, directives, pipes, and services for Angular-based clients

Auth Library

Authentication and authorization abstractions, services, and models

Vault Library

Vault-specific models, services, and cipher management functionality

Admin Console

Organization and user management features for admin functionality

Key Management

Cryptographic key management, encryption, and security services

Platform Library

Platform-specific implementations and utilities

Components Library

Shared UI component library with design system components

Nx Workspace Structure

The monorepo uses Nx to manage dependencies, builds, and tests across libraries and applications.

Path Mappings

Libraries are imported using TypeScript path mappings defined in tsconfig.base.json:
{
  "compilerOptions": {
    "paths": {
      "@bitwarden/common/*": ["./libs/common/src/*"],
      "@bitwarden/angular/*": ["./libs/angular/src/*"],
      "@bitwarden/auth/common": ["./libs/auth/src/common"],
      "@bitwarden/vault": ["./libs/vault/src"],
      "@bitwarden/components": ["./libs/components/src"]
    }
  }
}

Library Project Configuration

Each library has a project.json file that defines its Nx configuration:
{
  "name": "@bitwarden/common",
  "sourceRoot": "libs/common/src",
  "projectType": "library",
  "tags": ["scope:common", "type:lib"],
  "targets": {
    "build": { "executor": "nx:run-script" },
    "test": { "executor": "nx:run-script" },
    "lint": { "executor": "@nx/eslint:lint" }
  }
}

How Applications Consume Libraries

Import Pattern

Applications import library code using the scoped package names:
// Import from common library
import { CipherService } from '@bitwarden/common/vault/abstractions/cipher.service';
import { PlatformUtilsService } from '@bitwarden/common/platform/abstractions/platform-utils.service';

// Import from Angular library
import { JslibModule } from '@bitwarden/angular/jslib.module';
import { IfFeatureDirective } from '@bitwarden/angular/directives/if-feature.directive';

// Import from auth library
import { AuthService } from '@bitwarden/auth/common';

Dependency Injection

Services from libraries are typically registered in the application’s dependency injection container:
// Example: Registering services in an Angular application
import { CipherService } from '@bitwarden/common/vault/abstractions/cipher.service';
import { DefaultCipherService } from '@bitwarden/common/vault/services/cipher.service';

@NgModule({
  providers: [
    {
      provide: CipherService,
      useClass: DefaultCipherService
    }
  ]
})
export class AppModule {}

Build Dependencies

Nx automatically tracks dependencies between libraries and applications. When a library is modified, Nx rebuilds dependent projects:
# Build all libraries
nx run-many --target=build --projects=@bitwarden/common,@bitwarden/angular

# Test affected projects
nx affected:test

Library Organization Principles

Abstraction-First Design

Libraries define abstract interfaces (abstractions) that concrete implementations follow:
// libs/common/src/platform/abstractions/storage.service.ts
export abstract class StorageService {
  abstract get<T>(key: string): Promise<T>;
  abstract set<T>(key: string, value: T): Promise<void>;
  abstract remove(key: string): Promise<void>;
}

Domain Models

Domain models encapsulate business logic and data transformations:
// libs/common/src/vault/models/domain/cipher.ts
export class Cipher extends Domain {
  id: string;
  name: EncString;
  type: CipherType;
  
  async decrypt(key: SymmetricCryptoKey): Promise<CipherView> {
    // Decryption logic
  }
}

Platform-Specific Implementations

Applications provide platform-specific implementations of abstractions:
  • Browser: Uses Chrome storage API
  • Desktop: Uses Electron storage
  • Web: Uses browser localStorage/sessionStorage
  • CLI: Uses file system storage

Shared Code Categories

Abstractions

Abstract service interfaces that define contracts for implementations

Models

Domain models, data models, view models, request/response models

Services

Concrete service implementations and business logic

Enums & Types

Shared enumerations, type definitions, and constants

Testing Utilities

The monorepo includes dedicated testing libraries:
  • @bitwarden/core-test-utils: Core testing utilities and helpers
  • @bitwarden/state-test-utils: State management testing utilities
  • @bitwarden/storage-test-utils: Storage service mocks and test helpers

Next Steps

Common Library

Explore the common library structure and key abstractions

Angular Library

Learn about shared Angular components and directives

Build docs developers (and LLMs) love