πŸ—οΈ Architecture

Architecture Overview

Ever Gauzy is built as a modern, full-stack TypeScript monorepo using enterprise-grade frameworks. This document provides a high-level view of the platform's architecture.

System Architecture

Diagram; its source is available below
Diagram source
graph TB
    subgraph Client["Client Layer"]
        A1["Angular UI<br/>(Web SPA, Port: 4200)"]
        A2["Desktop App<br/>(Electron, Embedded)"]
        A3["Desktop Timer<br/>(Electron, Standalone)"]
        A4["Ever Teams<br/>(React/RN)"]
    end

    subgraph Server["Server Layer β€” NestJS API Server (Port: 3000)"]
        B1["Auth Guards"]
        B2["CQRS Commands"]
        B3["REST API / Swagger"]
        B4["GraphQL (WIP)"]
        B5["MCP Server (AI Tools)"]
        B6["Modules (Core)"]
        B7["Plugin System"]
        B8["Event Bus (CQRS)"]
        B9["Job Scheduler (Bull/Redis)"]
    end

    subgraph Data["Data Layer"]
        C1["TypeORM"]
        C2["MikroORM"]
        C3["Knex"]
        C4["Redis"]
        C5["OpenSearch"]
        D1["PostgreSQL / MySQL / SQLite"]
        D2["Cache"]
        D3["Search"]
    end

    A1 & A2 & A3 & A4 -- "HTTP / WebSocket" --> Server
    C1 & C2 & C3 --> D1
    C4 --> D2
    C5 --> D3

Architectural Layers

1. Client Layer

The client layer consists of multiple application types, all consuming the same API:

ApplicationTechnologyPackage LocationPurpose
Web UIAngular 19+, Nebular/ngx-adminapps/gauzyPrimary web interface
Desktop AppElectron + Angularapps/desktopAll-in-one desktop application
Desktop TimerElectron + Angularapps/desktop-timerTime tracking & activity monitoring
Desktop ServerElectron + NestJSapps/serverSelf-hosted API server
API Server DesktopElectron + NestJSapps/api-serverAPI-only server deployment
Ever TeamsReact/Next.js + React NativeExternal repoModern PM/Task interface

2. API Layer (NestJS)

The backend is a NestJS application following CQRS (Command Query Responsibility Segregation) patterns:

  • Controllers β€” handle HTTP requests, validate inputs, route to handlers
  • Commands/Queries β€” encapsulate business logic via the CQRS pattern
  • Services β€” core business logic and data access
  • Guards β€” authentication and authorization (JWT, Roles, Permissions, Tenant)
  • Interceptors β€” request/response transformation, logging
  • Pipes β€” input validation and transformation (class-validator)
  • Modules β€” NestJS dependency injection containers

3. Data Layer

The platform uses a Multi-ORM architecture supporting:

  • TypeORM β€” primary ORM with extensive entity definitions, repositories, and migrations
  • MikroORM β€” alternative ORM with its own repositories and entity metadata
  • Knex β€” raw SQL query builder for complex queries and migrations

All three ORMs connect to the same database and share entity definitions through a shared Multi-ORM decorator system.

4. Infrastructure Layer

  • PostgreSQL β€” primary production database
  • SQLite β€” lightweight development/demo database
  • Redis β€” caching, session store, and job queue
  • OpenSearch β€” full-text search indexing
  • MinIO/S3 β€” file and image storage
  • Cube β€” analytics and BI semantic layer
  • Zipkin/OTEL β€” distributed tracing

Key Architecture Patterns

Multi-Tenant Architecture

Every entity in the system is scoped to a tenant. The TenantBaseEntity base class provides:

  • Automatic tenantId injection on create/update
  • Automatic tenantId filtering on read queries
  • Cross-tenant access prevention at the ORM level

See Multi-Tenancy for details.

Plugin Architecture

The platform supports dynamic plugins for extending functionality:

@Module({})
export class PluginModule {
  static forRoot(plugins: Type<any>[]): DynamicModule {
    return {
      module: PluginModule,
      imports: plugins,
    };
  }
}

Plugins can add: entities, controllers, services, commands, and event handlers. See Plugin System.

CQRS Pattern

Business logic is organized into Commands (write) and Queries (read):

Controller β†’ CommandBus/QueryBus β†’ Handler β†’ Service β†’ Repository

This pattern enables:

  • Clear separation of read and write operations
  • Event-driven side effects
  • Easier testing through handler isolation

Event Bus

The platform uses NestJS @nestjs/cqrs events for inter-module communication:

// Publishing an event
this.eventBus.publish(new EmployeeCreatedEvent(employee));

// Handling an event in another module
@EventHandler(EmployeeCreatedEvent)
export class EmployeeCreatedHandler {
  handle(event: EmployeeCreatedEvent) {
    /* ... */
  }
}

Request Context

A RequestContext utility provides access to the current request context throughout the application:

// Access current user, tenant, and organization
const tenantId = RequestContext.currentTenantId();
const userId = RequestContext.currentUserId();
const orgId = RequestContext.currentOrganizationId();

Data Flow

Typical API Request Flow

Diagram; its source is available below
Diagram source
graph LR
    A["Client Request"] --> B["Guard (Auth)"]
    B --> C["Pipe (Validation)"]
    C --> D["Handler (CQRS)"]
    D --> E["Service"]
    E --> F["Repository (ORM)"]
    F --> G["Database"]
  1. Guard: Validates JWT token, checks roles/permissions, resolves tenant
  2. Pipe: Validates request body against DTO (Data Transfer Object) classes
  3. Handler: Executes business logic via CQRS command/query handler
  4. Service: Performs data access, integrations, and business rules
  5. Repository: Issues database queries through the active ORM

Guard Chain

Diagram; its source is available below
Diagram source
graph LR
    A["JWT Auth Guard"] --> B["Tenant Resolve"]
    B --> C["Role Guard"]
    C --> D["Permission Guard"]

Deployment Models

ModelComponentsBest For
SaaSCloud-hosted API + UIMulti-tenant production
Self-HostedDocker or bare metalPrivate infrastructure
Desktop ServerElectron app hosting APISmall teams, individuals
Desktop All-in-OneFull platform in single appPersonal use
Client-ServerSeparate API server + clientsTeams with centralized server

Edit this page

Copyright Β© 2023-Present Ever Co. LTD.Docs by Sourcey