SubPilot
A SaaS subscription management dashboard for indie founders tracking MRR, churn, and customer health across multiple products.
The Challenge
The core challenge was designing a dashboard information architecture that communicates revenue health at a glance without overwhelming the user. Most analytics tools either show too much or too little. The naive approach — just listing raw numbers — fails because founders need to understand trends, not snapshots. This required carefully curating which metrics to surface per page and how to visually encode change using color, sparklines, and progress indicators. Building a convincing, fully-typed mock data layer that behaves like a real backend was a deliberate tradeoff. Rather than wiring up a database prematurely, the project defines strict TypeScript interfaces for every domain object (Product, Customer, Subscription, Integration), which means the API contract is established before the backend exists. The visual design challenge was creating a dark-mode-only UI that feels premium rather than gloomy. This required a purposeful palette — deep navy backgrounds, purple accents, cyan highlights, and emerald/red semantics for positive/negative signals — layered with glassmorphism panels and subtle animation utilities.
Architectural Decisions
Mock-first data layer with strict TypeScript interfaces
All data is served from a single src/lib/mock-data.ts file rather than a live API. By defining TypeScript interfaces first (DashboardMetrics, Product, Customer, Subscription), the data contract is established upfront, making future API integration a drop-in replacement.
Next.js App Router with server components by default
The project uses Next.js 16 App Router, with pages rendered server-side by default. Client components are applied only where interactivity is needed — specifically the three pages with tab-based filtering. This keeps the bundle lean and avoids hydration overhead on purely presentational pages.
Single shared DashboardLayout with slot-based content
Rather than repeating sidebar and header markup across six pages, a single DashboardLayout component wraps all routes and renders page-specific content via React children. The sidebar uses usePathname() to highlight the active route without prop drilling.
Custom SVG chart primitives over heavy charting libraries
The revenue chart and MRR bar chart are implemented as hand-authored SVG with gradient fills rather than pulling in Recharts. This avoids 50-80KB of JavaScript for charts that do not require interactivity or dynamic axes.
Tailwind CSS 4 with semantic CSS custom properties
Rather than using Tailwind default color palette directly, the project defines a semantic token layer via CSS custom properties scoped to the dark theme in globals.css. Tailwind v4 PostCSS-first architecture removes the need for a separate config file.