Skip to main content

Architecture Overview

True Life uses a modern, modular architecture inspired by Angular's patterns, adapted for the FiveM runtime environment.

High-Level Architecture

Core Concepts

Modules

Modules are the primary organizational unit. Each module encapsulates:

  • Services - Business logic with RPC decorators
  • Repositories - Database operations
  • UI Features - HUDs and pages
  • Types - Shared type definitions
  • Configuration - Module-specific settings

See Module System for details.

Runtime Environments

The framework operates across three distinct runtime environments:

RuntimeBuild TargetDescription
serverFiveM ServerNode.js runtime, database access
clientFiveM ClientGame natives, entity control
webReact UIBrowser runtime, observable state

See Environment Directives for details.

RPC Communication

Services use decorators for type-safe client/server communication:

export class MyService {
	@Server
	async fetchData(ctx: EventContext<[id: string]>): Promise<Data> {
		const [id] = ctx.args;
		return await repository.findById(id);
	}
 
	@Client
	async showNotification(ctx: EventContext<[message: string]>): Promise<void> {
		const [message] = ctx.args;
		showUI(message);
	}
}

See RPC Decorators for details.

Dependency Injection

Angular-style dependency injection for service dependencies:

export class BankingService {
	private characterService = inject(CharacterService);
 
	@Server
	async getBalance(ctx: EventContext<[]>): Promise<number> {
		const character = this.characterService.getActiveCharacter(ctx.source);
		return character?.data.balance ?? 0;
	}
}

See Dependency Injection for details.

Observable State

Reactive observables for cross-environment state synchronization:

const playerNeeds = serverOwned({
	id: "player:needs",
	initialValue: { hunger: 100, thirst: 100 },
	perPlayer: true,
});

See Observables for details.

Data Flow

Client → Server (Request)

  1. Client calls a @Server decorated method
  2. RPC system serializes arguments to tuple
  3. Network event sent to server
  4. Server handler deserializes and executes
  5. Response sent back to client
  6. Client receives typed response

Server → Client (Push)

  1. Server calls a @Client decorated method
  2. RPC system serializes arguments
  3. Network event sent to specific client(s)
  4. Client handler deserializes and executes
  5. Optional response sent back

Client → UI (Observable Sync)

  1. Client updates a webOwned observable via observable.set()
  2. Observable system syncs state to web runtime
  3. React component subscribed via useObservable() hook
  4. React Compiler automatically optimizes re-renders
  5. Component updates when observable value changes

Build Pipeline

The framework uses parallel build pipelines for each runtime environment:

Key transformations:

PluginPurpose
swc-plugin-modulesTransforms RPC decorators into event handlers
swc-plugin-joaatCompiles joaat() calls to static hashes
swc-plugin-native-inlinerInlines FiveM native function calls
rollup-plugin-use-directiveStubs out code for wrong runtime
vite-plugin-use-directiveStubs out code for wrong runtime (web build)
@vitejs/plugin-reactReact JSX transformation with Babel
babel-plugin-react-compilerReact Compiler for automatic memoization

Observability

The framework includes comprehensive observability:

  • Distributed Tracing - OpenTelemetry spans across all runtimes
  • Structured Logging - W3C trace context propagation
  • Metrics - Prometheus metrics with Grafana dashboards
  • Live Map - Real-time player position visualization

See Telemetry for details.