Overview
Dashboard is a private admin panel built to monitor all three ProjectLabs SaaS products from one place. Rather than logging into each app separately, it aggregates data across BukuBengkel, Open Loyalty, and MabarVIP into a single interface — KPI cards, charts, alerts, and a live queue monitor.
The Problem
Running three live products on the same VPS means context-switching constantly — open Bengkel to check tenant activity, switch to Loyalty to check expiring points, switch to Mabar to see if any sessions are live. There was no single view of what was happening across the stack.
What Was Built
A Next.js dashboard with five sections:
- — Overview — cross-app KPI grid: active Bengkel tenants, customers, visits; Loyalty programs, members, points in circulation; Mabar streamers, sessions, active sessions now. Plus a recent activity feed merged from all three apps
- — BukuBengkel section — tenant list with per-tenant deep analytics: inventory value, transaction trends, customer stats, loyalty integration status, and low-stock alerts
- — Open Loyalty section — program and member analytics: enrollment trends, tier distribution, points flow (earned vs redeemed vs expired), top members, and expiring points forecast
- — MabarVIP section — session analytics: streamer list, session trends, lane usage ratio (Fast Track vs Regular), peak hours heatmap, and a real-time live monitor showing active queues
- — System page — health check for each app (API ping, DB file size, uptime), so infrastructure issues surface immediately
Architecture
Dashboard is purely a read-only proxy — it never touches app databases directly. Each app exposes protected /api/admin/stats/* endpoints behind a shared API key. Dashboard calls these via HTTP from server components, with Next.js ISR caching (60s for most pages, no cache for the live Mabar monitor). If one app is down, its section shows an error state while the others render normally.
Technical Notes
- — Stack — Next.js 16 (App Router), TypeScript, Tailwind CSS v4, Recharts, better-auth, SQLite (auth sessions only)
- — Data access — API-based, not direct DB access. Each app owns its data; dashboard only reads what each app explicitly exposes
- — Caching — Next.js
revalidateper fetch: 60s overview, 30s detail pages, 0 for real-time live monitor - — Auth — single admin account, not public. better-auth with email/password, session stored in a dedicated
auth.db - — Self-hosted — co-deployed on the same VPS via PM2 + Caddy, port 5004