Skip to main content

Overview

Autonome is an AI-powered autonomous cryptocurrency trading platform built with a split architecture for optimal deployment and scalability. The application separates the frontend and backend into independently deployable units while maintaining real-time synchronization through oRPC and Server-Sent Events (SSE).

Split Deployment Architecture

The application is divided into two distinct deployable units:

Frontend (Vercel)

  • Location: src/
  • Framework: TanStack Start (React 19 with SSR)
  • Deployment: Vercel (via Nitro preset)
  • Responsibilities:
    • Server-side rendering (SSR) for fast initial page loads
    • Client-side hydration and interactivity
    • Real-time UI updates via SSE subscriptions
    • State management with TanStack Query

Backend (VPS)

  • Location: api/src/index.ts
  • Framework: Hono (lightweight HTTP server)
  • Runtime: Bun
  • Deployment: Virtual Private Server (VPS)
  • Responsibilities:
    • oRPC procedure handlers
    • SSE event broadcasting
    • Trading schedulers (AI agents, price tracking)
    • Exchange simulator lifecycle
    • Database operations (PostgreSQL + Drizzle ORM)
The split architecture allows the frontend to scale independently on Vercel’s edge network while the backend runs stateful schedulers on a persistent VPS.

Communication Layer

oRPC over HTTP

The primary communication protocol between frontend and backend:

Server-Sent Events (SSE)

Real-time updates from backend to frontend:
  • /api/events/positions - Position updates
  • /api/events/trades - Trade execution feed
  • /api/events/conversations - AI chat events
  • /api/events/portfolio - Portfolio snapshots
  • /api/events/workflow - Trading workflow events
See Data Flow for detailed SSE architecture.

Core Components

Frontend Components

1. TanStack Router

File-based routing with type-safe navigation:

2. TanStack Query + oRPC Integration

Type-safe data fetching with automatic caching and refetching:

3. SSE Event Subscriptions

Components subscribe to real-time updates via EventSource:

Backend Components

1. oRPC Router

Organized by domain feature:
Each procedure follows a standard pattern:

2. Event Broadcasting System

Centralized EventEmitter-based SSE broadcasting:

3. Scheduler Bootstrap

Schedulers initialize once per server process:
Called from API server startup:

4. ExchangeSimulator Lifecycle

The simulator maintains in-memory state for sandbox trading:
Key behaviors:
  • Singleton pattern: One simulator instance per process
  • DB restoration: Rehydrates positions from Orders table on startup
  • Auto-close triggers: Monitors stop-loss and take-profit conditions
  • EventEmitter: Broadcasts trade executions and account updates

Data Flow Summary

  1. Client requests data via orpc.*.*.queryOptions() → TanStack Query
  2. Hono receives request at /api/rpc/* → routes to oRPC handler
  3. oRPC Router executes procedure → reads from DB via Drizzle
  4. Response flows back → TanStack Query caches result
  5. Schedulers emit events (trades, positions, portfolio)
  6. SSE Endpoints broadcast events → clients update UI

Port Configuration

Development and production use different port configurations:

Development (.env.local)

Production

Vite Proxy (Development)

Vite proxies /api/* requests to the backend:

Database Architecture

Schema (Drizzle ORM)

Key tables with quoted capitalized identifiers:
  • "Models" - AI trading agents with variant configuration
  • "Orders" - Single source of truth for positions (OPEN) and trades (CLOSED)
  • "Invocations" - AI model execution history
  • "ToolCalls" - Trade decisions (CREATE_POSITION, CLOSE_POSITION, HOLDING)
  • "PortfolioSize" - Time-series snapshots of portfolio value

Orders Table Design

The "Orders" table serves dual purposes:
Key fields:
  • status: OPEN | CLOSED
  • exitPlan: JSONB with stop/target/confidence
  • realizedPnl: Populated when closed
  • closeTrigger: null (manual) | "STOP" | "TARGET" (auto)
Unrealized P&L is calculated live from current prices, never stored. This ensures accuracy and avoids staleness.

Environment Management

All environment variables are typed via src/env.ts using T3Env:
Server-side variables:
  • DATABASE_URL, PORT, CORS_ORIGINS
  • NIM_API_KEY, OPENROUTER_API_KEY, etc.
  • LIGHTER_API_KEY_INDEX, LIGHTER_BASE_URL
  • TRADING_MODE: live | simulated
Client-side variables (must have VITE_ prefix):
  • VITE_API_URL - API endpoint for browser
  • VITE_APP_TITLE - Optional UI title override

Next Steps

  • Tech Stack - Detailed breakdown of technologies and versions
  • Data Flow - Request/response flow, SSE streaming, and state management