Skip to content

Architecture

shr0x edited this page Mar 25, 2026 · 1 revision

Architecture

This page explains how the project is structured, how the different layers communicate, and how data flows through the framework.


Overview

The framework is built around a clear separation of concerns:

  • source/server handles server-side game logic
  • source/client handles client-side RAGE:MP logic
  • source/shared contains code shared between layers
  • frontend contains the CEF user interface built separately from the game logic

Main Layers

Server

The server layer is responsible for authoritative game logic.

Typical responsibilities include:

  • authentication and character handling
  • database access
  • game rules
  • command handling
  • persistence
  • deciding what data should be sent to players

The server should be treated as the source of truth for persistent and gameplay-critical data.


Client

The client layer is responsible for local in-game behavior inside RAGE:MP.

Typical responsibilities include:

  • reacting to server events
  • playing animations
  • handling local GTA functions
  • showing or hiding UI
  • forwarding UI actions back toward the game logic

The client is the bridge between the game engine and the frontend UI.


Shared

The shared layer exists to prevent duplication between server and client.

Typical responsibilities include:

  • shared types
  • shared enums
  • shared constants
  • shared event names
  • data contracts used by multiple layers

This layer is important because it keeps communication predictable and typed.


Frontend

The frontend is the CEF UI layer.

Typical responsibilities include:

  • HUD rendering
  • menus
  • overlays
  • notifications
  • interaction pages
  • user-facing interface state

The frontend should focus on presentation and user interaction, not core game authority.


High-Level Structure

Project Root
├── source/
│   ├── server/   -> Server-side logic
│   ├── client/   -> Client-side logic
│   └── shared/   -> Shared contracts, types, utilities
├── frontend/     -> React-based CEF UI
├── client_packages/
├── config/
└── docs/

Core Design Idea

The framework is not meant to be a single monolithic gamemode file.

Instead, it is designed like a base framework:

  • each layer has a clear responsibility
  • systems can be extended without mixing everything together
  • shared code reduces duplication
  • the frontend is isolated from low-level game logic

Communication Model

The project can be understood as four connected parts:

  1. Server
  2. Client
  3. CEF Frontend
  4. Database

The most important thing to understand is that these parts do not all talk to each other directly.

Basic direction of communication

  • Server ⇄ Client
  • Client ⇄ Frontend
  • Server ⇄ Database

In most cases:

  • the server does not talk directly to the frontend
  • the frontend does not talk directly to the database
  • the client acts as the bridge between game logic and UI

Data Flow Diagram

flowchart LR
    DB[(PostgreSQL)]
    S[Server]
    C[Client]
    F[Frontend / CEF]

    DB <--> S
    S <--> C
    C <--> F
Loading

Responsibility Boundaries

Server owns

  • persistence
  • validation
  • permissions
  • gameplay decisions
  • authoritative state

Client owns

  • local GTA execution
  • local rendering behavior
  • in-game event reception
  • CEF visibility and bridging

Frontend owns

  • user interface
  • visual state
  • page rendering
  • user actions inside CEF

Shared owns

  • contracts and reusable definitions between layers

These boundaries are what keep the framework scalable.


Typical Runtime Flow

A common flow in this framework looks like this:

  1. A player performs an action
  2. The action reaches the server or client
  3. The server validates and processes it if needed
  4. The client receives the result
  5. The client opens or updates the CEF UI
  6. The frontend renders the new state
  7. If the player clicks something in the UI, that action goes back through the client and then to the server if required

Example Flow: Opening a UI Page

sequenceDiagram
    participant P as Player
    participant S as Server
    participant C as Client
    participant F as Frontend

    P->>S: Triggers gameplay action
    S->>C: Sends event / data
    C->>F: Opens page and passes data
    F->>P: Renders interface
Loading

This is the general pattern for server-driven UI.


Example Flow: UI Button Action

sequenceDiagram
    participant P as Player
    participant F as Frontend
    participant C as Client
    participant S as Server
    participant DB as Database

    P->>F: Clicks button in UI
    F->>C: Sends UI event
    C->>S: Forwards action to server
    S->>DB: Reads or updates data
    DB-->>S: Returns result
    S-->>C: Sends updated state
    C-->>F: Pushes new data
    F-->>P: Updates UI
Loading

This is the general pattern for UI actions that require validation or persistence.


Why the Client Is the Bridge

The client exists between the server and the frontend because the frontend is not the game engine.

The frontend can render pages and collect user input, but it cannot directly perform GTA-native gameplay behavior the same way the client can.

That is why the client layer is so important:

  • it receives gameplay events from the server
  • it opens and updates CEF
  • it translates UI actions back into game events

This bridge role is one of the core architectural ideas of the framework.


Shared Layer Purpose

The shared layer is one of the most important parts of the architecture.

Without it, projects usually end up with:

  • duplicated event names
  • mismatched payloads
  • inconsistent enums
  • hardcoded strings spread everywhere

By keeping contracts inside source/shared, both client and server can rely on the same definitions.

That makes the framework:

  • easier to extend
  • easier to refactor
  • less error-prone

Why This Structure Matters

Many RAGE:MP projects become hard to maintain because:

  • logic is mixed together
  • UI and gameplay responsibilities overlap
  • events are scattered
  • feature code leaks into unrelated systems

This project avoids that by separating:

  • game authority
  • local game execution
  • frontend rendering
  • shared contracts

That is one of the strongest parts of the framework’s design.


Recommended Mental Model

When working on the project, think like this:

If it changes saved game state

It probably belongs to the server.

If it uses local GTA or RAGE:MP client behavior

It probably belongs to the client.

If it renders menus, HUD, or interface state

It probably belongs to the frontend.

If both server and client need to know about it

It probably belongs to shared.

This mental model helps keep features clean.


Feature Placement Strategy

When adding a new system, try to keep its logic split by responsibility:

Server side

  • validation
  • persistence
  • authority
  • business logic

Client side

  • event handling
  • visual local actions
  • CEF bridge calls

Frontend side

  • page components
  • UI state
  • buttons and interface logic

Shared side

  • event names
  • DTOs
  • enums
  • interfaces

This is how features stay modular instead of becoming tightly coupled.


Example: Inventory as an Architectural Feature

A system like inventory usually touches all layers:

Server

  • loads items
  • validates usage
  • updates persistent inventory data

Client

  • receives inventory updates
  • opens inventory UI
  • forwards interaction requests

Frontend

  • displays slots, icons, quantities, actions

Shared

  • item data shape
  • inventory-related types
  • event contracts

This is a good example of why the architecture is split the way it is.


Scalability Benefits

This architecture gives several practical advantages:

  • easier onboarding
  • less duplication
  • clearer feature ownership
  • safer refactors
  • better long-term maintainability
  • easier UI expansion
  • easier addition of new systems

Summary

The framework is built around four main parts:

  • Server for authority and persistence
  • Client for game-side execution and bridging
  • Frontend for CEF UI
  • Shared for common contracts and reusable definitions

The key rule is simple:

The server owns the truth, the client connects the game to the UI, the frontend renders the interface, and shared keeps communication consistent.

Once this is understood, the rest of the framework becomes much easier to work with.

🚀 Getting Started

🧠 Architecture

🎮 Features

🛠 Development

❗ Help

Clone this wiki locally