AFP
Back to Projects

Case Study

MRT Jakarta Dashboard

Apr–May 2026 · Full-stack · Deployed

React 19Node.jsTypeScriptPostgreSQLPlaywrightSSEDockerJWTGoogle OAuth
Live Dashboard API Docs E2E Report GitHub
01

Overview

PT MRT Jakarta needed a centralized platform to manage 15 stations simultaneously — coordinating incident response, tracking real-time operational data, and enabling different staff roles to act on live information. The existing approach relied on fragmented tools and manual coordination, creating delays in incident escalation and limited visibility across the network.

I designed and built the full platform as a contract engagement: frontend design system, API architecture, authentication, authorization model, real-time data layer, and deployment pipeline — 15 pages shipping as v2.18.0 with 127 Playwright E2E tests passing in CI.

02

Architecture

Frontend on Vercel (Next.js 15 / React 19), API on Fly.io (Express.js / Node.js), PostgreSQL as the persistent store. Real-time station updates are pushed via Server-Sent Events — the frontend maintains a persistent SSE connection to the API, receiving events as station state changes.

VERCEL

Next.js 15 / React 19

FLY.IO

Express.js / Node.js

POSTGRESQL

Database / Persistent

SSE (real-time) · JWT + Google OAuth · Docker (local dev) · GitHub Actions (CI)

03

Design System

Built “Operations Terminal” — a purpose-built dark ops-board design system. No component library. Every token, component, and motion primitive was defined from scratch: CSS custom properties for color, typography, and spacing; a component library including OpsCard, StatTile, TerminalBlock, LEDDot, and MonoChip; and a motion grammar (LED pulse, count-up animation, hover transitions) with full reduced-motion support.

The system is portable — this portfolio was built on a variant of it. Design ownership is the claim; the shared tokens between the dashboard and the portfolio are the proof.

04

Key Challenges

SSE Reconnection Under Load

PROBLEMServer-Sent Events drop silently when the server restarts or the connection times out. Station controllers saw stale data without knowing their connection had dropped.

SOLUTIONImplemented an automatic exponential-backoff reconnection strategy on the client with a visible connection-state indicator in the UI. The API sends a heartbeat event every 15 seconds; the client treats silence beyond 20 seconds as a disconnect and reconnects automatically.

Zero reported stale-data incidents after rollout. Connection health is now visible to the operator at all times.

Multi-role RBAC with Spatie

PROBLEMDifferent staff roles (station controller, supervisor, admin, auditor) needed different views and action sets across the same 15 pages — not just route guards, but per-component permission checks.

SOLUTIONUsed Laravel Spatie Permission on the API to define role-permission pairs, then exposed a permissions payload in the JWT. The Next.js frontend reads the payload on mount and conditionally renders action buttons, form fields, and entire panels based on the decoded permissions — no second round-trip.

Role enforcement is consistent across all 15 pages with a single shared permissions hook. Adding a new role requires one API change and no frontend changes.

Interactive Map with 15+ Concurrent Stations

PROBLEMThe station map needed to show live status for all 15 stations simultaneously — color-coded by incident state — while remaining performant enough to update in real time without full re-renders.

SOLUTIONStation state is held in a Zustand store updated by the SSE stream. The map renders 15 station markers as individual React components keyed by station ID, each subscribing only to its own slice of the store. React renders only the markers whose state changes.

Map updates are immediate and smooth at 60fps. No full page re-renders on station state changes.

05

Testing

127 Playwright E2E tests cover the full application: authentication flows (JWT + Google OAuth), all 15 pages, incident lifecycle (create → escalate → resolve), RBAC (each role's permitted and forbidden actions), and real-time update reception.

E2E was chosen over unit tests for this domain because the critical behaviors are interaction sequences across multiple pages and real API responses — not isolated functions. The test suite runs on every push via GitHub Actions and the HTML report is published to GitHub Pages.

View E2E Report
06

Links

Live Dashboard API Docs E2E Report GitHub
Status: LIVE · v2.18.0 · 260+ commits
Back to Projects