> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nyxeron.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> How NYXERON is split between the browser, two small Go services and BNB Chain, and why value is only ever settled on the server.

<div className="nyx-hero nyx-banner">
  <img src="https://mintcdn.com/nyxeron/i74M9jNT1Ky6CAS9/images/sections/technology.webp?fit=max&auto=format&n=i74M9jNT1Ky6CAS9&q=85&s=cab1743c57e6c9887cc821327b28c4e4" alt="" noZoom width="1200" height="400" data-path="images/sections/technology.webp" />

  <div className="nyx-hero-text">
    <div className="nyx-hero-kicker">Technology</div>
    <div className="nyx-hero-title">One simulation, every client, synced live.</div>
  </div>
</div>

NYXERON is built so that the fun part runs in the browser and the money part runs on the server. The club simulation
is a pure TypeScript library that every browser runs locally; two small Go services connect players and settle
anything of value; BNB Chain is the source of truth for real deposits and real stock.

## System diagram

```mermaid theme={null}
%%{init: {'theme':'base','themeVariables':{'background':'#090319','primaryColor':'#1e0f3b','primaryBorderColor':'#b078ff','primaryTextColor':'#f3e8ff','secondaryColor':'#140a2b','tertiaryColor':'#120826','lineColor':'#914dff','textColor':'#f3e8ff','edgeLabelBackground':'#120826','clusterBkg':'#140a2b','clusterBorder':'#4b2a85','actorBkg':'#1e0f3b','actorBorder':'#b078ff','actorTextColor':'#f3e8ff','signalColor':'#c9a8ff','signalTextColor':'#f3e8ff','noteBkgColor':'#2a1650','noteTextColor':'#f3e8ff','noteBorderColor':'#914dff','fontSize':'15px'}}}%%
flowchart LR
  subgraph Browser["Player's browser (Vercel)"]
    WEB["Game client<br/>React 19 · three.js · Web Audio"]
    CORE["Simulation core<br/>pure, seeded simulation"]
    WEB --- CORE
  end

  RELAY["Relay<br/>Go · no database"]
  API["api<br/>Go · SQLite"]
  DB[("SQLite")]

  PRIVY["Privy<br/>sign-in + embedded wallet"]
  BIN["Binance Web3<br/>RWA stock quotes"]
  BSC["BNB Smart Chain"]

  WEB -- "WebSocket, binary frames" --> RELAY
  WEB -- "HTTPS + Privy JWT" --> API
  API --- DB
  API -- "verify JWT" --> PRIVY
  API -- "stock quotes" --> BIN
  API -- "read receipts & balances" --> BSC
  WEB -- "sign-in, USDC transfer" --> PRIVY
```

## What runs where

| Part | Runs on | Stack | Job |
| - | - | - | - |
| Simulation core | Every browser | Pure TypeScript, seeded PRNG | Every game rule: day actions, the 360-minute night, guests, prices, staff, levels |
| Game client | Vercel, `nyxeron.xyz` | React 19, Vite, Tailwind v4, zustand, three.js, Web Audio, Privy | Screens, HUD, the 3D club, the DJ studio, and the live-session host/guest/DJ logic |
| Relay | Go service on `api.nyxeron.xyz` | Go, WebSockets | Rooms and frame routing for live multiplayer. Never reads game data |
| api | Go service on `api.nyxeron.xyz` | Go standard library, SQLite | Accounts, play wallets, save sync, City venues, stock, top-ups, sales |
| Privy | Third party | JWT + embedded EVM wallet | Email/Google sign-in; every player gets a BNB Chain wallet without installing anything |
| Binance Web3 | Third party | HTTPS | Live prices of tokenized stocks (TSLA, NVDA, index baskets…) |
| BNB Smart Chain | Public chain (chain id 56) | Read by the api | Ground truth for deposits and for the stock the platform actually holds |

A few api endpoints are public: `GET /api/quotes` (stock prices), `GET /api/rooms` (clubs open now) and
`GET /api/city` (the City's venues).

## Trust model

The whole design follows one sentence: **the browser asks, the server settles.**

<CardGroup cols={2}>
  <Card title="The simulation is pure" icon="flask">
    All game logic lives in the simulation core: no DOM, no network, no clock, no `Math.random()`. Randomness comes from a
    seeded deterministic PRNG stored in the game state, so a night replays bit-for-bit.
  </Card>

  <Card title="Value moves only on the server" icon="vault">
    Anything that changes NYX Points, Credits, stock units or access is decided in the api, inside a single SQL
    transaction, with a ledger row written next to the balance change.
  </Card>

  <Card title="The chain is read, not reported" icon="link">
    For a deposit the browser sends only a transaction hash. The api reads amount, sender and recipient from the chain
    itself and waits for BNB Chain to confirm the transfer.
  </Card>

  <Card title="Identity comes from the token" icon="id-card">
    The api verifies the Privy JWT itself (signature, issuer, audience, expiry). The player id is the token's subject,
    never a field in the request body.
  </Card>

  <Card title="The relay is a dumb pipe" icon="route">
    The relay routes binary frames by a 3-byte header and never parses the payload. It stamps the sender id on every
    frame a guest sends, so a guest cannot pretend to be someone else.
  </Card>

  <Card title="The books match the chain" icon="scale-balanced">
    The platform's wallet and stock are reconciled with the chain: Credits owed to players must be covered by the
    stablecoins the platform holds, and stock units in the books by the tokenized stock it holds on-chain.
  </Card>
</CardGroup>

| Who | Decides | Cannot decide |
| - | - | - |
| Browser (any player) | Its own UI, its own practice career, what it *wants* to do | Its balance, a deposit amount, a sale price outside the allowed band |
| CEO browser in a live room | The club's live state for that night: guests, prices, who is on the decks | Anything that is written to an account; the api bounds every result it receives |
| Relay | Which room a socket is in, who is host (by secret token), the sender id of guest frames | The content of any frame |
| api | Balances, ledgers, sales, City leases, access | On-chain facts; it only reads them |

## One night, end to end

<Steps>
  <Step title="Day: prepare in the browser">
    The CEO orders stock, books staff and a DJ, runs promotion. Each action is a pure core function that returns a new
    state or a typed failure. Live stock prices come from `GET /api/quotes` (Binance RWA feed, cached briefly).
  </Step>

  <Step title="Open the club">
    `startNight` begins a 360-minute night at 22:00. If the CEO goes live, the browser opens a relay room and announces it
    to the api every few seconds, so it shows up in "Clubs open now".
  </Step>

  <Step title="Night: the host simulates, everyone watches">
    `tickNight` advances one in-game minute every second (or two or three per second at 2× and 3×). After any change the
    host sends a gzipped snapshot of the club, at most four times per second. Guests and the DJ send only intents
    (`buy`, `mix`); the host applies them and the next snapshot shows the result to everyone.
  </Step>

  <Step title="Close at 04:00">
    `endNight` produces the night report. The career autosaves locally and syncs to the api (newest save wins), so it
    follows the player to any device.
  </Step>

  <Step title="Settle on the server">
    A guest's night is settled by the api inside one transaction: the wallet can only shrink by what was spent, and the
    tokens taken home cannot cost more than that. At City parties, purchases of real tokenized stock are paid in Credits:
    the api holds the Credits and the stock until the party is settled, then pays the club owner their margin.
  </Step>
</Steps>

```mermaid theme={null}
%%{init: {'theme':'base','themeVariables':{'background':'#090319','primaryColor':'#1e0f3b','primaryBorderColor':'#b078ff','primaryTextColor':'#f3e8ff','secondaryColor':'#140a2b','tertiaryColor':'#120826','lineColor':'#914dff','textColor':'#f3e8ff','edgeLabelBackground':'#120826','clusterBkg':'#140a2b','clusterBorder':'#4b2a85','actorBkg':'#1e0f3b','actorBorder':'#b078ff','actorTextColor':'#f3e8ff','signalColor':'#c9a8ff','signalTextColor':'#f3e8ff','noteBkgColor':'#2a1650','noteTextColor':'#f3e8ff','noteBorderColor':'#914dff','fontSize':'15px'}}}%%
sequenceDiagram
  autonumber
  participant C as CEO browser (core sim)
  participant R as Relay
  participant G as Guest browser
  participant A as api
  C->>A: GET /api/quotes
  C->>R: create room
  C->>A: announce room (every 20 s)
  G->>R: join + hello
  R->>C: hello (sender stamped)
  loop each in-game minute
    C->>C: tickNight
    C->>R: state snapshot (≤ 4 Hz, latest wins)
    R-->>G: snapshot
  end
  G->>R: buy intent
  R->>C: buy (sender stamped)
  C->>R: result + next snapshot
  C->>C: endNight → report, autosave
  C->>A: sync save
  G->>A: settle night (bounded, one SQL transaction)
```

Read next: [Live multiplayer](/multiplayer-live) for the wire protocol and DJ sync, and
[Tech stack & quality](/tech-stack) for how all this is tested.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.