A live supply-chain tracking control room. Track products and suppliers, watch
shipments move through an ordered → shipped → in_transit → delivered pipeline in
real time, and get alerted the moment a shipment breaches its ETA.
SupplyTrack Chain ships as a single self-contained Go binary — the React control room is embedded directly into the executable. No database server, no Node runtime at runtime, no external services. Clone, build, run.
┌─ ordered ─────── shipped ─────── in_transit ─────── delivered ─┐
│ ●━━━━━━━━━━━━━━━●━━━━━━━━━━━━━━━━●━━━━━━━━━━━━━━━━━━━○ │
│ PO raised picked up on the lane signed │
└────────────────────────────────────────────────────────────────┘
- Live shipment tracking over Server-Sent Events (SSE) — the board, KPIs, charts, and activity feed update in real time as a logistics simulator advances shipments.
- Delay alerting — a shipment that passes its ETA by more than the configured grace window is automatically flagged, raised as a critical alert, and (optionally) pushed to a Slack webhook.
- Status pipeline — every shipment moves through a four-stage pipeline with a live progress bar; the dashboard shows the whole fleet's distribution as a freight stepper.
- Products & suppliers — full CRUD with supplier reliability scores, lead times, and per-supplier on-time volume.
- Operational dashboard — manifest-style KPI chips, a pipeline-distribution hero, status-mix and 7-day-flow bar charts, top-supplier rankings, and a streaming activity feed.
- Self-contained storage — an in-memory store with JSON persistence (
data/db.json). No external database required. - AES-256-GCM vault — the Slack alert webhook is encrypted at rest; the plaintext is never written to disk.
- Polished UX — light + dark themes, resizable table columns, an in-app live log monitor, confirm/prompt modals, and a collapsible "lever" sidebar.
| Layer | Choice |
|---|---|
| Backend | Go (pure standard library — no external modules, no CGO) |
| HTTP routing | Go 1.22+ net/http ServeMux (method + path patterns) |
| Live updates | Server-Sent Events (text/event-stream + http.Flusher) |
| Storage | In-memory store + JSON file persistence |
| Auth | Passcode (HMAC-SHA256) + HMAC-signed session cookie |
| Crypto | AES-256-GCM vault (crypto/aes, crypto/cipher) |
| Frontend | React 18 + TypeScript + Vite 6, embedded via //go:embed |
| Charts | Chart.js 4 (bar-based) |
| Fonts | Saira (display) · Albert Sans (UI) · Red Hat Mono (numerics) |
The compiled frontend (web/dist) is embedded into the Go binary, so the production
artifact is a single executable.
An operational logistics board: navy ink on a cool paper surface with a hi-vis
safety-orange primary (#ee6c00) and a full status palette (order blue, shipped
violet, in-transit amber, delivered green, delayed red). The signature elements are the
status-pipeline stepper, the manifest shipping-label KPI chips (barcode top
strips), and the live SSE activity feed. The sidebar collapses via a physical
breaker-style lever switch.
- Go 1.24+ to build the server.
- Node 18+ only if you want to rebuild the frontend (the built SPA is committed).
# 1. (optional) rebuild the embedded SPA
cd web
npm install
npm run build
cd ..
# 2. build and run the single binary
go build -o supplytrack.exe .
./supplytrack.exeThen open http://localhost:7300 and sign in with the demo passcode:
track-the-chain
On first boot the store seeds 8 suppliers, 16 products, and 30 shipments, then the live simulator takes over — advancing shipments, raising delay alerts, and continuously re-ordering to keep the board in motion.
Run the Go API and the Vite dev server side by side — Vite proxies /api and /events
to the Go process:
# terminal 1 — API on :7300
go run .
# terminal 2 — Vite dev server with HMR
cd web && npm run devAll configuration is via environment variables (or a .env file — see .env.example):
| Variable | Default | Purpose |
|---|---|---|
PORT |
7300 |
HTTP listen port |
ADMIN_PASSCODE |
track-the-chain |
Control-room passcode |
APP_SECRET |
(dev default) | Signs the session cookie — set in production |
SIM_TICK_SECONDS |
5 |
Logistics simulator tick interval |
DATA_DIR |
data |
Where db.json and .vault-key live |
VAULT_KEY |
(auto-generated) | base64 32-byte AES key; auto-created if unset |
data/ and .env are gitignored and never committed.
All /api/* routes (except auth) require the st_session cookie.
| Method & path | Description |
|---|---|
POST /api/login |
Exchange passcode for a session cookie |
POST /api/logout |
Clear the session |
GET /api/session |
Check auth state |
GET /api/dashboard |
Metrics + recent shipments + activity feed |
GET /api/shipments?status= |
List shipments (filter by status / delayed) |
POST /api/shipments |
Create a purchase order |
GET /api/shipments/{id} |
Shipment detail + tracking events |
POST /api/shipments/{id}/advance |
Push a shipment to its next status |
DELETE /api/shipments/{id} |
Delete a shipment |
GET/POST/PUT/DELETE /api/suppliers |
Supplier CRUD |
GET/POST/PUT/DELETE /api/products |
Product CRUD |
GET /api/alerts |
List delay alerts |
POST /api/alerts/{id}/ack |
Acknowledge one alert |
POST /api/alerts/ack-all |
Acknowledge all open alerts |
GET /api/logs?after= |
Poll the in-app activity log |
GET/PUT /api/settings |
Read / update grace window + Slack webhook |
POST /api/settings/test-slack |
Send a test ping to the configured webhook |
GET /events |
SSE stream (event, alert, metrics, rev) |
A background goroutine ticks every SIM_TICK_SECONDS and, for each non-delivered
shipment:
- Advances progress within the current leg; on completion it moves to the next pipeline status and appends a tracking event.
- Injects disruptions — occasionally pushes the ETA back (customs, weather, carrier reschedules) and records a delay event.
- Detects delays — once a shipment passes
ETA + grace, it is flagged delayed and a critical alert is raised (and pushed to Slack if configured). - Re-orders — when in-flight volume runs low, fresh purchase orders are injected so the board stays continuously live; delivered shipments are pruned to stay bounded.
Every change is broadcast over SSE so connected control rooms update instantly.
supplytrack-chain/
├── main.go # wires config, vault, auth, store, SSE, simulator; embeds SPA
├── internal/
│ ├── config/ # env + .env loading
│ ├── models/ # Supplier, Product, Shipment, Event, Alert, Settings
│ ├── store/ # in-memory store + JSON persistence + CRUD
│ ├── metrics/ # dashboard metric computation
│ ├── sim/ # live logistics simulation engine
│ ├── sse/ # Server-Sent Events hub
│ ├── auth/ # passcode + HMAC session cookie
│ ├── vault/ # AES-256-GCM secret vault
│ ├── logbus/ # in-memory ring buffer for the live log monitor
│ ├── seed/ # first-boot demo dataset
│ └── web/ # HTTP server, routing, handlers, dashboard
└── web/ # React + TypeScript + Vite control room
├── src/
│ ├── AppShell.tsx # sidebar + topbar live KPI ticker + theme + logout
│ ├── live.ts # EventSource store + useLive() hook
│ ├── charts.tsx # Chart.js bar charts
│ ├── pages/ # Login, Dashboard, Shipments, Suppliers, Products, Alerts, Logs, Settings
│ └── styles.css # "Freightline" design system
└── dist/ # built SPA (embedded into the binary)
- Provider secrets (Slack webhook) are encrypted with AES-256-GCM before being
written to
data/db.json; the plaintext never touches disk. - The session cookie is HMAC-signed and
HttpOnly; tampering invalidates it. - The passcode is compared in constant time via HMAC.
- All
/api/*and/eventsroutes are guarded by the session middleware. data/,.env, and*.vault-keyare gitignored.
Apache License 2.0 — see LICENSE.