How to Build a Subscription Billing Dashboard
Subscription billing is the lifeblood of SaaS businesses. Managing plans, processing payments, handling upgrades and downgrades, and tracking churn requires a robust billing system.
In this guide, we will build a subscription management dashboard with plan creation, customer management, billing automation, and revenue analytics.
Database Schema
model Plan {
id String @id @default(cuid())
name String
slug String @unique
description String?
price Decimal
interval String @default("month")
features String[]
popular Boolean @default(false)
active Boolean @default(true)
subscriptions Subscription[]
}
model Subscription {
id String @id @default(cuid())
planId String
plan Plan @relation(fields: [planId], references: [id])
customerId String
status String @default("active")
currentPeriodStart DateTime
currentPeriodEnd DateTime
cancelAtPeriodEnd Boolean @default(false)
createdAt DateTime @default(now())
}Plan Comparison Component
function PlanCards({ plans, onSelect }: { plans: Plan[]; onSelect: (plan: Plan) => void }) {
return (
<div className="grid grid-cols-3 gap-4">
{plans.map(plan => (
<div key={plan.id} className={`relative rounded-xl p-6 border-2 ${
plan.popular ? 'border-brand-500 bg-gray-900' : 'border-gray-700 bg-gray-900'
}`}>
{plan.popular && (
<span className="absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-brand-600 px-3 py-1 text-xs text-white">
Most Popular
</span>
)}
<h3 className="text-lg font-bold text-white">{plan.name}</h3>
<p className="mt-1 text-sm text-gray-400">{plan.description}</p>
<p className="mt-4">
<span className="text-3xl font-bold text-white">${plan.price}</span>
<span className="text-sm text-gray-400">/{plan.interval}</span>
</p>
<ul className="mt-4 space-y-2">
{plan.features.map((f, i) => (
<li key={i} className="flex items-center gap-2 text-sm text-gray-300">
<CheckCircle className="h-4 w-4 text-green-400" />
{f}
</li>
))}
</ul>
<button onClick={() => onSelect(plan)}
className="mt-6 w-full rounded-lg bg-brand-600 py-2 text-sm font-semibold text-white hover:bg-brand-700"
>
{plan.price === 0 ? 'Get Started' : 'Subscribe'}
</button>
</div>
))}
</div>
)
}Revenue Analytics
async function getRevenueMetrics() {
const activeSubs = await prisma.subscription.count({ where: { status: 'active' } })
const mrr = await prisma.subscription.aggregate({
where: { status: 'active' },
_sum: { plan: { price: true } },
})
const churned = await prisma.subscription.count({
where: { status: 'cancelled', updatedAt: { gte: subDays(new Date(), 30) } }
})
return { mrr: mrr._sum.price || 0, activeSubs, churned, churnRate: churned / activeSubs }
}Cross-Selling: Launch Your Subscription Platform
Our Subscription Manager template provides all of this out of the box — plan creation, billing management, payment history, churn analytics, dunning emails, and revenue reports. It integrates with Stripe for payment processing.
Pair with Invoice Manager for professional invoicing, or Customer Success Platform to track health scores and reduce churn. Together they form a complete billing and success platform.
Related Template
Try this production-ready starter kit to build your project faster.
Subscription Manager
Manage plans, billing, and customers
Ready to Build?
Get started with our production-ready starter kits and ship your project faster.
Browse Starter Kits