ext-apps/examples/scenario-modeler-server/src/lib/calculations.ts
Jonathan Hefner 79fa10097b Add scenario-modeler-server example
Demo MCP App for SaaS financial planning with:
- Interactive sliders for MRR, growth, churn, margin, and costs
- 12-month projection charts (MRR, Gross Profit, Net Profit)
- 5 pre-built scenario templates (Bootstrapped, VC Rocketship, etc.)
- Template comparison overlay for strategy analysis
- Light/dark theme support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:33:07 -06:00

72 lines
1.7 KiB
TypeScript

import type {
ScenarioInputs,
MonthlyProjection,
ScenarioSummary,
} from "../types.ts";
export function calculateProjections(
inputs: ScenarioInputs,
): MonthlyProjection[] {
const {
startingMRR,
monthlyGrowthRate,
monthlyChurnRate,
grossMargin,
fixedCosts,
} = inputs;
// Net growth rate (can be negative if churn > growth)
const netGrowthRate = (monthlyGrowthRate - monthlyChurnRate) / 100;
const projections: MonthlyProjection[] = [];
let cumulativeRevenue = 0;
for (let month = 1; month <= 12; month++) {
// MRR with compound growth
const mrr = startingMRR * Math.pow(1 + netGrowthRate, month);
// Profit calculations
const grossProfit = mrr * (grossMargin / 100);
const netProfit = grossProfit - fixedCosts;
// Cumulative revenue
cumulativeRevenue += mrr;
projections.push({
month,
mrr,
grossProfit,
netProfit,
cumulativeRevenue,
});
}
return projections;
}
export function calculateSummary(
projections: MonthlyProjection[],
inputs: ScenarioInputs,
): ScenarioSummary {
const endingMRR = projections[11].mrr;
const arr = endingMRR * 12;
const totalRevenue = projections.reduce((sum, p) => sum + p.mrr, 0);
const totalProfit = projections.reduce((sum, p) => sum + p.netProfit, 0);
const mrrGrowthPct =
((endingMRR - inputs.startingMRR) / inputs.startingMRR) * 100;
const avgMargin = (totalProfit / totalRevenue) * 100;
// Find first month where netProfit >= 0
const breakEvenProjection = projections.find((p) => p.netProfit >= 0);
const breakEvenMonth = breakEvenProjection?.month ?? null;
return {
endingMRR,
arr,
totalRevenue,
totalProfit,
mrrGrowthPct,
avgMargin,
breakEvenMonth,
};
}