Skip to content

zr00t-1001/crypto-dashboard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Crypto·Watch Terminal

A real-time cryptocurrency price dashboard with a Bloomberg-terminal aesthetic. Live prices, high/low ranges, interactive charts, relative-performance overlays, multi-timezone clocks, and CSV/JSON export — built on a clean-architecture Rust backend and an Astro + React frontend.

🚧 Work in progress. The core feature set is complete and functional, but this project is not finished. More cryptocurrencies will be added (currently Bitcoin, Litecoin, Solana, and Ethereum), along with further enhancements. See Roadmap.


Features

  • Live spot prices for BTC, LTC, SOL, ETH in USD & EUR
  • Real-time updates over WebSockets — prices flash green/red as they move, no refresh
  • 24h percent change indicators on each price
  • High / Low range with day / week / month tabs and a computed spread %
  • Per-coin price charts — a 2×2 grid, each auto-scaled
  • Relative performance overlay — all coins normalized to % change on one axis
  • Multi-timezone clocks — New York, London, Tokyo, Madrid, ticking live
  • Data export — download any coin's price series as CSV or JSON
  • Dark / light theme toggle with an amber accent, persisted across sessions

Tech Stack

Backend

  • Rust with Axum (web framework)
  • SQLx with PostgreSQL, over TLS 1.3 (rustls)
  • Tokio async runtime
  • Price data from the CoinGecko API
  • Clean / hexagonal architecture (domain · application · infrastructure · presentation)

Frontend


Architecture

Both backend and frontend follow the same hexagonal pattern — inner layers know nothing of outer ones; dependencies point inward through interfaces ("ports").

Backend (Rust)

src/
├── domain/             # entities — Coin, Currency, Price, Period
├── application/        # ports (traits) + use cases
├── infrastructure/
│   ├── persistence/    # PostgreSQL via sqlx (TLS)
│   ├── external/       # CoinGecko HTTP client
│   └── scheduler/      # polling loop + broadcast
└── presentation/       # Axum handlers, router, WebSocket, DTOs

Frontend (TypeScript)

frontend/src/
├── domain/             # types mirroring the backend
├── application/        # ports + use cases
├── infrastructure/
│   ├── http/           # fetch-based gateway
│   ├── websocket/      # live price stream
│   └── container.ts    # composition root (singleton)
└── presentation/       # React components + hooks + Astro layouts

The backend polls CoinGecko on an interval, stores snapshots in PostgreSQL, and broadcasts each batch to WebSocket subscribers. The frontend reads via REST for the initial load and subscribes to the WebSocket for live updates — components depend only on use cases, never on fetch or the API URL directly.

Pipeline & data flow

The system runs as three containers behind a single origin: nginx serves the static frontend and reverse-proxies /api (REST and WebSocket) to the Rust backend, which polls CoinGecko and persists to PostgreSQL.

flowchart LR
    CG["CoinGecko API"]
    Browser(["User's browser"])
    subgraph host["Docker host — docker compose"]
      direction LR
      subgraph FE["frontend · nginx :3000"]
        STATIC["Astro static build"]
        PROXY["nginx /api proxy"]
      end
      subgraph BE["backend · Rust + Axum :8080"]
        POLL["polling loop"]
        BCAST["broadcast channel"]
        HTTP["REST + WebSocket"]
      end
      DB[("PostgreSQL :5432 · TLS")]
    end
    CG -->|HTTPS poll| POLL
    POLL -->|save prices| DB
    POLL -->|price batch| BCAST
    BCAST -->|push| HTTP
    HTTP -->|queries| DB
    Browser -->|load page| STATIC
    Browser -->|api calls| PROXY
    PROXY -->|proxy to backend| HTTP
Loading

And the runtime flow of a single live update, from poll to browser:

sequenceDiagram
    autonumber
    actor U as Browser
    participant N as nginx
    participant API as Backend
    participant DB as PostgreSQL
    participant CG as CoinGecko
    Note over U,DB: Initial load (REST)
    U->>N: GET /api/prices/latest
    N->>API: proxy_pass
    API->>DB: SELECT latest
    DB-->>API: rows
    API-->>U: prices (JSON)
    Note over U,API: Live updates (WebSocket)
    U->>N: connect /api/ws
    N->>API: upgrade
    loop every POLL_INTERVAL_SECONDS
        API->>CG: fetch quotes
        CG-->>API: JSON
        API->>DB: INSERT prices
        API-->>U: broadcast over WS
    end
Loading

API Endpoints

Method Endpoint Description
GET /api/health Liveness check
GET /api/prices/latest Latest price for every coin/currency
GET /api/prices/extremes?coin=&currency=&period= Highest & lowest over a period
GET /api/prices/series?coin=&currency=&period= Time-series for charts
GET /api/prices/export?coin=&currency=&period= Download price series as CSV
WS /api/ws Real-time price broadcast

coinBTC, LTC, SOL, ETH · currencyUSD, EUR · periodday, week, month


Run with Docker

The fastest way to run the whole stack — PostgreSQL (TLS), the Rust backend, and the Astro frontend — together.

Prerequisites

  • Docker with the Compose plugin (Docker Desktop includes both)

Clone and run

git clone https://github.com/zr00t-1001/crypto-dashboard.git
cd crypto-dashboard
docker compose up --build

Then open http://localhost:3000.

flowchart TD
    A["git clone the repo"] --> B["cd crypto-dashboard"]
    B --> C["docker compose up --build"]
    C --> D["containers start<br/>db · backend · frontend"]
    D --> E["open localhost:3000"]
Loading

That one command:

  1. builds a TLS-enabled PostgreSQL image and creates the schema on first run,
  2. compiles the Rust backend in release mode and starts polling CoinGecko,
  3. builds the static frontend and serves it via nginx, which reverse-proxies /api (REST and WebSocket) to the backend — so the browser uses a single origin, with no CORS and no hardcoded backend host.

Stop with Ctrl+C. To remove the containers and wipe the database volume:

docker compose down -v

Configuration

Defaults run out of the box. To override secrets or ports, copy the example and pass it explicitly:

cp .env.docker.example .env.docker
# edit .env.docker — at minimum set a real POSTGRES_PASSWORD
docker compose --env-file .env.docker up --build
Variable Description Default
POSTGRES_PASSWORD Database password changeme_dev_password
POSTGRES_USER Database user postgres
POSTGRES_DB Database name crypto_dashboard
POLL_INTERVAL_SECONDS CoinGecko poll interval 60
FRONTEND_PORT Host port for the dashboard 3000
BACKEND_PORT Host port for the API 8080
RUST_LOG Backend log level info

TLS note: the bundled Postgres image uses a self-signed certificate and the backend connects with DB_SSL_MODE=require (encrypted, certificate not verified). For production, supply a CA-signed certificate and switch to verify-full.

Services

Service What it is Host port
frontend nginx serving the Astro build + /api proxy 3000 → 80
backend Rust / Axum API, poller, WebSocket 8080
db PostgreSQL 17 with TLS internal

Getting Started

Prerequisites

1. Database setup

Create the database and enable SSL on your PostgreSQL server (generate a self-signed cert for local development and set ssl = on in postgresql.conf).

CREATE DATABASE crypto_dashboard;

2. Backend

Create a .env file in the project root:

DATABASE_URL=postgres://postgres:yourpassword@localhost:5432/crypto_dashboard
DB_MAX_CONNECTIONS=5
DB_SSL_MODE=require
DB_CA_CERT_PATH=
POLL_INTERVAL_SECONDS=60

Run the migrations and start the server:

sqlx migrate run
cargo run

The backend starts on http://127.0.0.1:8080, begins polling CoinGecko, and serves the API.

3. Frontend

cd frontend
npm install
npm run dev

The dashboard is available at http://localhost:4321.

Run both the backend and frontend simultaneously. CORS is configured to allow the frontend's dev origin.


Configuration

Variable Description Default
DATABASE_URL PostgreSQL connection string — (required)
DB_MAX_CONNECTIONS Connection pool size 5
DB_SSL_MODE require or verify-full require
DB_CA_CERT_PATH CA cert path (required for verify-full)
POLL_INTERVAL_SECONDS How often to poll CoinGecko 300

TLS: The backend connects to PostgreSQL over TLS. require encrypts the connection; verify-full additionally verifies the server certificate against a CA (set DB_CA_CERT_PATH). Switching modes is a .env change — no code edits.


Roadmap

This project is actively being developed. Planned additions:

  • More cryptocurrencies — expand beyond the current four coins
  • 24h volume and market-cap indicators
  • Configurable / user-selectable coins
  • Excel (.xlsx) export
  • verify-full TLS in production
  • Deployment guide
  • Additional timezones / configurable clocks

License

This project is provided as-is for educational and personal use.


Acknowledgements

Price data provided by CoinGecko. Built with Rust, Axum, Astro, and Recharts.

About

A real-time cryptocurrency market terminal inspired by professional trading platforms. Crypto·Watch combines a Rust backend, WebSocket streaming, PostgreSQL persistence, and a modern Astro + React frontend to provide live cryptocurrency prices, market analytics, historical charts, multi-currency conversions, and data export capabilities.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors