Skip to content

Architecture Overview

DraftForge follows a modern full-stack architecture with clear separation of concerns.

High-Level Architecture

flowchart TD
    Client([Client Browser])

    Client --> Nginx

    subgraph Docker["Docker Environment"]
        Nginx[Nginx<br/>:80, :443]

        Nginx -->|/api/*| Backend
        Nginx -->|/*| Frontend

        Frontend[Frontend<br/>React + TypeScript<br/>:3000]
        Backend[Backend<br/>Django REST<br/>:8000]

        Backend --> Redis[(Redis<br/>Cache<br/>:6379)]
        Backend --> SQLite[(SQLite<br/>Database)]
    end
Hold "Alt" / "Option" to enable pan & zoom

Request Flow

sequenceDiagram
    participant C as Client
    participant N as Nginx
    participant F as Frontend
    participant B as Backend
    participant R as Redis
    participant DB as SQLite

    C->>N: HTTPS Request

    alt Static/SPA Route (/*)
        N->>F: Proxy Request
        F-->>N: React SPA
        N-->>C: HTML/JS/CSS
    else API Route (/api/*)
        N->>B: Proxy Request
        B->>R: Check Cache
        alt Cache Hit
            R-->>B: Cached Data
        else Cache Miss
            B->>DB: Query
            DB-->>B: Result
            B->>R: Store in Cache
        end
        B-->>N: JSON Response
        N-->>C: API Response
    end
Hold "Alt" / "Option" to enable pan & zoom

Data Flow

flowchart LR
    subgraph Frontend["Frontend (React)"]
        UI[UI Components]
        Zustand[(Zustand Store)]
        Zod{Zod Validation}

        UI --> Zustand
        Zustand --> UI
    end

    subgraph Backend["Backend (Django)"]
        DRF[DRF ViewSets]
        Serializers[Serializers]
        Models[Models]
        Cacheops[django-cacheops]
    end

    subgraph Data["Data Layer"]
        Redis[(Redis Cache)]
        SQLite[(SQLite DB)]
    end

    subgraph External["External APIs"]
        Discord[Discord OAuth]
        Steam[Steam API]
    end

    UI -->|fetch /api/*| DRF
    DRF --> Serializers
    Serializers --> Models
    Models --> Cacheops
    Cacheops --> Redis
    Cacheops --> SQLite
    DRF -->|JSON| Zod
    Zod -->|Validated Data| Zustand

    DRF <--> Discord
    DRF <--> Steam
Hold "Alt" / "Option" to enable pan & zoom

Service Responsibilities

Nginx

  • SSL termination
  • Reverse proxy routing
  • Static file serving
  • Load balancing (future)

Frontend

  • Server-Side Rendering (SSR) with React Router 7
  • User interface rendering
  • Client-side state management
  • API consumption

SSR API Configuration

The frontend uses SSR (Server-Side Rendering) for improved performance and SEO. During SSR, API requests are made from the Node.js server inside the Docker container, not from the browser.

How it works:

  • Client-side (browser): Uses /api - proxied by Nginx to the backend
  • Server-side (SSR): Uses SSR_API_URL environment variable

Configuration:

The SSR_API_URL environment variable controls where the frontend server makes API requests during SSR:

Deployment SSR_API_URL
Docker Compose (default) http://backend:8000/api
Kubernetes http://backend-service:8000/api
External backend https://api.example.com/api
Local dev (no Docker) http://localhost:8000/api

Set in your environment file (e.g., docker/.env.dev):

SSR_API_URL=http://backend:8000/api

Docker Service Names

In Docker Compose, services can reach each other by service name. The backend in the URL refers to the backend service defined in docker-compose.yaml.

Backend

  • REST API endpoints
  • Business logic
  • Authentication (Discord OAuth)
  • Database operations
  • Steam API integration

Redis

  • Session storage
  • Query caching (django-cacheops)
  • Rate limiting data