Date: 2026-04-16
Status: Approved design — ready for implementation planning
Owner: Plutus (coordinator), Apollo (frontend), Proteus (infrastructure)
| Decision | Choice |
|---|---|
| Domain | trading.boas.dev (dedicated subdomain) |
| Frontend hosting | Cloudflare Pages |
| API proxy hosting | VPS (Hostinger) behind Cloudflare Tunnel |
| API domain | api.trading.boas.dev (tunnel route) |
| Demo mode | Single app, data source fallback — bundled demo JSON when API/R2 unreachable |
| TradingView MCP | Not adopted — no Pine scripts. Webhooks remain primary TV integration. |
┌─────────────────────────────────┐
│ Cloudflare Edge │
│ │
Browser ──────────┤ trading.boas.dev ──► CF Pages │
│ api.trading.boas.dev ──► Tunnel │
└──────────┬───────────────────────┘
│ tunnel
┌──────────▼───────────────────────┐
│ Hostinger VPS │
│ │
│ :8100 FastAPI proxy │
│ └── Alpaca Paper API │
│ └── SQLite (trading.db joins) │
│ │
│ :5678 n8n (trading-spoke) │
│ └── R2 writes (pipelines) │
└──────────────────────────────────┘
Data sources:
Static pages ──► R2 JSON (fallback: public/data/demo/*.json)
Live pages ──► FastAPI proxy (fallback: public/data/demo/*.json)
Market page ──► TradingView widgets (always live, no auth)
Already scaffolded at apps/dashboard/:
Apollo's HTML mockups define the visual language. The existing scaffold uses generic Tailwind
classes — this must be replaced with the mockup design system:
--bg-base: #070a0f, etc.)The mockups are the source of truth for visual design. React components must match them
pixel-for-pixel in layout, color, and typography.
Reference mockups:
mockups/portfolio-overview.html (in repo)mockups/trade-journal.html (in repo)~/Library/CloudStorage/Dropbox/_DevSync/mockups/trading-dashboard/positions.html~/Library/CloudStorage/Dropbox/_DevSync/mockups/trading-dashboard/strategy.html~/Library/CloudStorage/Dropbox/_DevSync/mockups/trading-dashboard/analytics.html~/Library/CloudStorage/Dropbox/_DevSync/mockups/trading-dashboard/alerts.html~/Library/CloudStorage/Dropbox/_DevSync/mockups/trading-dashboard/market-context.html| Route | Data Source (live) | Data Source (demo) | Key Components |
|---|---|---|---|
/ | R2: market summary | demo/overview.json | P&L card, position count, thesis, last alert, status indicator |
/positions | API: /api/positions + /api/account | demo/positions.json | Position table, risk badges, account summary bar |
/strategy | R2: thesis JSON | demo/strategy.json | Current thesis, bias assessment, watchlist signals |
/analytics | API: /api/history + R2: performance | demo/analytics.json | Equity curve (Recharts), drawdown chart, metrics cards |
/log | R2: trade log JSON | demo/trade-log.json | Trade list with decision chains, Lightweight Charts |
/alerts | R2: watchdog alerts | demo/alerts.json | Alert feed, L1/L2/L3 classification, filter controls |
/market | TradingView widgets (always live) | Same — widgets need no auth | Embedded TradingView widgets, VIX via VIXY proxy |
Each data-fetching hook follows this pattern:
async function fetchWithFallback<T>(url: string, demoPath: string): Promise<T> {
try {
const res = await fetch(url)
if (!res.ok) throw new Error(res.statusText)
return await res.json()
} catch {
const demo = await fetch(demoPath)
return await demo.json()
}
}
Demo JSON files live in public/data/demo/ and ship with the build. They contain
realistic placeholder data matching the API response schemas.
| Variable | Dev | Production |
|---|---|---|
VITE_API_URL | http://localhost:8100 | https://api.trading.boas.dev |
VITE_R2_URL | (empty — use demo data) | R2 public bucket URL |
cd apps/dashboard
npm install
npm run build # outputs to dist/
# CF Pages picks up dist/ via git push or wrangler pages deploy
CF Pages project name: trading-dashboard
Custom domain: trading.boas.dev
Build command: cd apps/dashboard && npm install && npm run build
Build output directory: apps/dashboard/dist
SPA routing: add _redirects file or [[redirects]] in wrangler.toml:
/* /index.html 200
3 endpoints implemented:
GET /api/health — health checkGET /api/account — equity, buying power, cash, portfolio valueGET /api/positions — all open positions with P&LGET /api/orders — recent orders (50)Per the FastAPI proxy spec (04_launch/fastapi-proxy-spec.md):
1. GET /api/history — equity curve from Alpaca portfolio history API
- Computed fields: P&L, high watermark, max drawdown
- Query params: period, timeframe
2. Computed fields on /positions — stop_level, target_level, risk_badge
- Requires SQLite join against trade_log table
- Currently returns 0 for stop/target
3. Computed fields on /account — daily P&L, exposure %, drawdown status
- Currently returns raw Alpaca data without enrichment
4. CORS update — add https://trading.boas.dev to allowed origins
5. Error handling — per spec (503 for auth failure, 429 passthrough, 502/504)
6. Env var alignment — use ALPACA_API_KEY_ID / ALPACA_API_SECRET_KEY (nono profile names),
not ALPACA_API_KEY / ALPACA_SECRET_KEY (current code)
api.trading.boas.dev → localhost:8100scripts/deploy-trading-war-room-env.sh)1. CF Pages project — create trading-dashboard project, wire trading.boas.dev CNAME
2. Tunnel route — add api.trading.boas.dev → localhost:8100 to existing CF Tunnel config
3. FastAPI systemd service — create unit file, deploy apps/api/ to VPS
4. R2 public access — configure public read for the plutus-trading bucket (or proxy via Worker)
| Agent | Deliverable |
|---|---|
| Apollo | Convert 7 HTML mockups → React components. Match mockup design system exactly. Wire data fetching hooks with demo fallback. |
| Proteus | CF Pages project + DNS. Tunnel route for api.trading.boas.dev. FastAPI systemd service on VPS. R2 public read config. |
| Trading-spoke | Activate R2 writes in Market Data Pipeline + Trade Log Pipeline (currently stubbed). |
| Plutus | Create demo JSON fixtures. Complete FastAPI proxy (history endpoint, computed fields, CORS). Coordinate and verify. |