Skip to main content
The Bitwarden Clients repository is organized as a monorepo containing multiple applications and shared libraries. This structure promotes code reuse, maintains consistency, and enables efficient development across multiple platforms.

Workspace Layout

The repository follows a clear separation between deployable applications and reusable libraries:

Apps vs Libs

Applications (apps/)

Applications are the final, deployable artifacts. Each app:
  • Has its own build configuration (webpack, tsconfig, etc.)
  • Targets a specific platform (browser extension, desktop app, web app, CLI)
  • Consumes shared libraries from libs/
  • Contains platform-specific code that doesn’t belong in shared libraries
Available Applications:

Libraries (libs/)

Libraries contain reusable code shared across multiple applications. Each library:
  • Focuses on a specific domain or functionality
  • Has minimal dependencies on other libraries
  • Exports a clear public API through index files
  • Is framework-agnostic when possible (except Angular-specific libs)
Key Libraries:
  • auth - Authentication, login strategies, SSO, 2FA
  • vault - Cipher management, folders, collections
  • admin-console - Organization and provider management
  • billing - Subscription and payment handling
  • key-management - Cryptographic operations, key derivation
  • common - Core business logic, models, services
  • platform - Platform abstractions (storage, crypto, state)
  • angular - Angular-specific utilities and base classes
  • node - Node.js-specific implementations
  • components - Shared UI component library (Storybook)
  • assets - Icons, images, fonts
  • tools - Generator, importer, exporter functionality
  • state - State management primitives
  • serialization - JSON serialization utilities
  • guid - GUID type definitions and utilities
  • core-test-utils - Common testing utilities
  • state-test-utils - State testing helpers
  • storage-test-utils - Storage mocking utilities

Workspace Configuration

The monorepo uses npm workspaces defined in package.json:
package.json
This configuration:
  • Hoists dependencies to the root node_modules for efficiency
  • Links local packages automatically (no need for npm link)
  • Enables workspace commands like npm run build --workspace=@bitwarden/auth

TypeScript Path Mappings

The tsconfig.base.json defines path aliases for all libraries, enabling clean imports across the monorepo:
tsconfig.base.json
Usage Example:

Project Structure Conventions

Each library follows a consistent internal structure:

Key Conventions:

Abstractions First

Define interfaces in abstractions/ folders before implementing services

Index Exports

Only export public APIs through index.ts - keep internals private

Framework Separation

Separate Angular code (angular/) from framework-agnostic code (common/)

Colocation

Keep related files together (model, service, tests in same folder)

Dependency Guidelines

Allowed Dependencies:

  • Apps can depend on any library
  • Libraries should minimize cross-dependencies
  • Avoid circular dependencies between libraries
  • Platform libraries (common, platform) should have minimal dependencies

Dependency Anti-Patterns:

Avoid These Patterns:
  • Libraries depending on apps
  • Circular dependencies between libraries
  • Direct imports from library internals (use index exports)
  • Framework-specific code in common/ folders

Enterprise Code Organization

Enterprise/commercial features live in bitwarden_license/:
This separation:
  • Maintains clear licensing boundaries
  • Enables building GPL-only versions by excluding this directory
  • Follows the same organizational patterns as the open-source code

Adding New Code

When to Create a New Library:

1

Identify the domain

Does your code represent a distinct business domain (auth, vault, billing)?
2

Check for reusability

Will this code be used by multiple applications?
3

Consider boundaries

Does it have clear boundaries with minimal dependencies?
4

Evaluate size

Is it substantial enough to warrant a separate library?
If all answers are yes, create a new library. Otherwise, add to an existing library or app.

When to Add to an Existing App:

  • Platform-specific implementation details
  • Application-specific UI components
  • Integration code that glues libraries together
  • Code that will never be shared

Best Practices

Next Steps

Nx Workspace

Learn how Nx manages builds, caching, and task execution

Dependency Injection

Understand service registration and DI patterns