Skip to content
Case study · 09 / 09← All work

Trading analytics dashboard

A private dashboard to watch and control my trading bots across several broker accounts.

Role
Internal tool: designed and built for my own trading bots
Stack
Next.js 15, React 19, TypeScript, Recharts, Tailwind CSS 4
Overview
OverviewStatic export, all data fetched in the browser
(01) The problem

The bots run on their own and trade on several cTrader accounts. Checking them meant reading logs. I needed equity, daily P&L and bot state in one screen. I also needed to pause a bot without opening a terminal.

My roleI designed and built the dashboard as my own tool, on top of the bots' API.
(02) ResultsCounted in the code
4private screens: overview, engines, calendar, report
6live event types pushed over SSE
52typed endpoint calls in one API client
(03) Architecture

Three decisions that shaped it.

  1. 01

    Static export, all data fetched in the browser

    Why. The dashboard ships as plain files with no Node server to run. Every request carries the session cookie to the bots' API.

    Trade-off. The auth guard is a client-side redirect. The API has to enforce every check, and each screen starts with a skeleton.

  2. 02

    SSE events trigger refetches, polling is the fallback

    Why. A closed trade or new snapshot refreshes the right card at once. Polling every 15 to 60 seconds covers a dropped stream.

    Trade-off. Each component that listens opens its own EventSource. The overview holds three at once.

  3. 03

    The monthly report is a print stylesheet

    Why. The report renders as a normal page. An A4 landscape @page rule and window.print() turn it into a PDF.

    Trade-off. No automated PDF. Someone has to open the page and print it.

(04) GalleryKeep scrolling →
Overview
Overview · Six KPI tiles across all accounts and a seven-day equity curve for the selected one.
P&L calendar
P&L calendar · A month grid shaded by daily P&L. Click a day for its detail, or export the month to CSV.
Engines
Engines · Turn each engine on or off, reload them, and pick the active cTrader account.
Monthly report
Monthly report · One page per month and account, laid out to print as A4 landscape.
(05) What I'd do next
01Share one EventSource through a context, and let components subscribe to the events they need.
02Move the hand-written fetch, interval and alive-flag code to SWR. It is already a dependency, but unused.
03Give the virtualized trades table and the trade detail dialog a route. Both are built but not linked.
Next project · 01 / 09
Vimo →A multi-product SaaS platform where one account moves across every product
Case study · 09 / 09

Trading analytics dashboard

A private dashboard to watch and control my trading bots across several broker accounts.

Role
Internal tool: designed and built for my own trading bots
Stack
Next.js 15, React 19, TypeScript, Recharts, Tailwind CSS 4
Trading analytics dashboard
(01) The problem

The bots run on their own and trade on several cTrader accounts. Checking them meant reading logs. I needed equity, daily P&L and bot state in one screen. I also needed to pause a bot without opening a terminal.

My roleI designed and built the dashboard as my own tool, on top of the bots' API.
(02) Results
4private screens: overview, engines, calendar, report
6live event types pushed over SSE
52typed endpoint calls in one API client
(03) Architecture

Three decisions that shaped it.

01

Static export, all data fetched in the browser

Why. The dashboard ships as plain files with no Node server to run. Every request carries the session cookie to the bots' API.

Trade-off. The auth guard is a client-side redirect. The API has to enforce every check, and each screen starts with a skeleton.

02

SSE events trigger refetches, polling is the fallback

Why. A closed trade or new snapshot refreshes the right card at once. Polling every 15 to 60 seconds covers a dropped stream.

Trade-off. Each component that listens opens its own EventSource. The overview holds three at once.

03

The monthly report is a print stylesheet

Why. The report renders as a normal page. An A4 landscape @page rule and window.print() turn it into a PDF.

Trade-off. No automated PDF. Someone has to open the page and print it.

(04) Gallery
Overview
Overview · Six KPI tiles across all accounts and a seven-day equity curve for the selected one.
P&L calendar
P&L calendar · A month grid shaded by daily P&L. Click a day for its detail, or export the month to CSV.
Engines
Engines · Turn each engine on or off, reload them, and pick the active cTrader account.
Monthly report
Monthly report · One page per month and account, laid out to print as A4 landscape.
(05) What I'd do next
01Share one EventSource through a context, and let components subscribe to the events they need.
02Move the hand-written fetch, interval and alive-flag code to SWR. It is already a dependency, but unused.
03Give the virtualized trades table and the trade detail dialog a route. Both are built but not linked.
Next projectVimo →
Nahuel SantillánEN