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>
This commit is contained in:
parent
f81d17f385
commit
79fa10097b
1 changed files with 1743 additions and 0 deletions
72
examples/scenario-modeler-server/src/lib/calculations.ts
Normal file
72
examples/scenario-modeler-server/src/lib/calculations.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
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,
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue