diff --git a/padelnomics/src/padelnomics/public/templates/landing.html b/padelnomics/src/padelnomics/public/templates/landing.html
index 730d016..a367c7b 100644
--- a/padelnomics/src/padelnomics/public/templates/landing.html
+++ b/padelnomics/src/padelnomics/public/templates/landing.html
@@ -3,9 +3,9 @@
{% block title %}Padelnomics - Padel Court Business Plan & ROI Calculator{% endblock %}
{% block head %}
-
+
-
+
@@ -122,7 +122,7 @@
Plan Your Padel Business in Minutes, Not Months
- Model your padel court investment with 60+ variables, sensitivity analysis, and professional-grade projections. 100% free.
+ Model your padel court investment with 60+ variables, sensitivity analysis, and professional-grade projections.
@@ -147,16 +147,18 @@
40%
- Rent / m²
-
- €4/m²
+ Build Cost / Court
+
+ €30K
- Exit Multiple
-
- 6.0x
+ Equity %
+
+ 25%
+ Assumes €8/m² rent, 5% interest, 10-year loan, 300 m² per court
+
Total Investment
@@ -169,23 +171,23 @@
After debt service
-
Annual Revenue
-
—
-
Net of booking fees
+
Payback Period
+
—
+
Years to recover equity
-
Equity IRR
-
—
-
5-year hold
+
Cash-on-Cash
+
—
+
Annual return on equity
-
This is a simplified estimate. The full planner models 60+ variables with monthly cash flows, sensitivity analysis, and more.
+
Want the full picture? The planner models 60+ variables with monthly projections, sensitivity analysis, and connects you with court suppliers.
{% if user %}
-
Open Full Planner
+
Start Planning
{% else %}
-
Unlock the Full Planner — Free
+
Create Your Plan
{% endif %}
@@ -197,7 +199,7 @@
- Model your padel hall investment with our free financial planner. CAPEX, operating costs, cash flow, returns, sensitivity analysis.
+ Model your padel hall investment with our financial planner. CAPEX, operating costs, cash flow, returns, sensitivity analysis.
@@ -261,11 +263,11 @@
@@ -277,72 +279,53 @@ function tCalc() {
var courts = +document.getElementById('tc-courts').value;
var rate = +document.getElementById('tc-rate').value;
var util = +document.getElementById('tc-util').value;
- var rentSqm = +document.getElementById('tc-rent').value;
- var exitMult = +document.getElementById('tc-exit').value;
+ var buildCost = +document.getElementById('tc-buildcost').value;
+ var equityPct = +document.getElementById('tc-equity').value;
// Display slider values
document.getElementById('tv-courts').textContent = courts;
document.getElementById('tv-rate').innerHTML = '€' + rate + '/hr';
document.getElementById('tv-util').textContent = util + '%';
- document.getElementById('tv-rent').innerHTML = '€' + rentSqm + '/m\u00B2';
- document.getElementById('tv-exit').textContent = exitMult.toFixed(1) + 'x';
+ document.getElementById('tv-buildcost').innerHTML = '€' + Math.round(buildCost / 1000) + 'K';
+ document.getElementById('tv-equity').textContent = equityPct + '%';
- // Simplified model (rent model, indoor, all double courts)
- var sqmPerCourt = 300; // court + shared space
- var totalSqm = courts * sqmPerCourt;
- var courtCost = courts * 25000;
- var capex = courtCost + 60000 + 80000 + 40000 + 100000 + 50000; // elec + sanitary + fitout + planning + parking
+ // CAPEX: build cost per court is the main driver
+ var capex = courts * buildCost;
+
+ // Financing: equity % from slider, remainder is debt
+ // Assumes 5% interest, 10-year amortizing loan
+ var iRate = 0.05, term = 10;
+ var equity = capex * (equityPct / 100);
+ var debt = capex - equity;
+ var mRate = iRate / 12;
+ var nPay = term * 12;
+ var pmt = debt > 0 ? debt * mRate / (1 - Math.pow(1 + mRate, -nPay)) : 0;
// Revenue
+ // Assumes 16 bookable hours/day, 29 days/month, off-peak rate = 65% of peak
var hoursDay = 16, daysMonth = 29;
var availHours = courts * hoursDay * daysMonth;
var bookedHours = availHours * (util / 100);
- var offPeakRate = rate * 0.65;
- var wRate = rate * 0.4 + offPeakRate * 0.6;
- var courtRev = bookedHours * wRate;
- var netRev = courtRev * 0.9; // 10% booking fee
+ var peakShare = 0.4;
+ var wRate = rate * peakShare + rate * 0.65 * (1 - peakShare);
+ var grossRev = bookedHours * wRate;
+ var netRev = grossRev * 0.9; // 10% booking platform fee
// Operating costs
- var rent = totalSqm * rentSqm;
- var opex = rent + courts * 400 + 350; // utilities/maint per court + marketing
+ // Assumes €8/m² rent (300 m² per court), €400/court utilities, €350 marketing
+ var rent = courts * 300 * 8;
+ var opex = rent + courts * 400 + 350;
- // EBITDA
+ // Monthly cash flow after debt service
var ebitda = netRev - opex;
-
- // Financing (85% LTV, 5%, 10yr)
- var loanPct = 0.85, iRate = 0.05, term = 10;
- var debt = capex * loanPct;
- var equity = capex - debt;
- var mRate = iRate / 12;
- var nPay = term * 12;
- var pmt = debt * mRate / (1 - Math.pow(1 + mRate, -nPay));
var netCF = ebitda - pmt;
- // Annual figures
- var annualRev = netRev * 12;
+ // Payback period: years to recover equity from annual net cash flow
var annualCF = netCF * 12;
+ var payback = annualCF > 0 ? equity / annualCF : Infinity;
- // IRR approximation (Newton's method, 5yr hold)
- var hold = 5;
- var y3ebitda = ebitda * 12;
- var exitVal = y3ebitda * exitMult;
- var cfs = [-equity];
- for (var y = 1; y <= hold; y++) {
- var cf = annualCF;
- if (y === hold) cf += exitVal - debt * Math.pow((1 + mRate), 12 * hold - 12 * hold); // simplified: remaining debt ~ original for short holds
- // Simplified: remaining debt after Y years
- var remDebt = 0;
- if (y === hold) {
- // Outstanding balance after hold*12 payments
- var paid = hold * 12;
- remDebt = debt * Math.pow(1 + mRate, paid) - pmt * (Math.pow(1 + mRate, paid) - 1) / mRate;
- if (remDebt < 0) remDebt = 0;
- cf = annualCF + exitVal - remDebt;
- }
- cfs.push(cf);
- }
-
- var irr = calcIRR(cfs);
+ // Cash-on-cash return: annual net CF / equity invested
+ var coc = equity > 0 ? annualCF / equity : 0;
// Format outputs
var fmt = function(n) { return (n >= 0 ? '' : '-') + '\u20AC' + Math.abs(Math.round(n)).toLocaleString('de-DE'); };
@@ -353,35 +336,23 @@ function tCalc() {
cfEl.innerHTML = fmt(netCF);
cfEl.className = 'tm-value ' + (netCF >= 0 ? 'tm-green' : 'tm-red');
- document.getElementById('tr-rev').innerHTML = fmt(annualRev);
-
- var irrEl = document.getElementById('tr-irr');
- if (irr !== null && isFinite(irr)) {
- irrEl.textContent = (irr * 100).toFixed(1) + '%';
- irrEl.className = 'tm-value ' + (irr >= 0 ? 'tm-green' : 'tm-red');
+ var pbEl = document.getElementById('tr-payback');
+ if (payback > 0 && payback <= 30) {
+ pbEl.textContent = payback.toFixed(1) + 'yr';
+ pbEl.className = 'tm-value ' + (payback <= 5 ? 'tm-blue' : 'tm-navy');
} else {
- irrEl.innerHTML = '—';
- irrEl.className = 'tm-value tm-navy';
+ pbEl.innerHTML = '—';
+ pbEl.className = 'tm-value tm-red';
}
-}
-function calcIRR(cfs) {
- // Newton-Raphson IRR solver
- var guess = 0.15;
- for (var i = 0; i < 100; i++) {
- var npv = 0, dnpv = 0;
- for (var t = 0; t < cfs.length; t++) {
- var f = Math.pow(1 + guess, t);
- npv += cfs[t] / f;
- if (t > 0) dnpv -= t * cfs[t] / (f * (1 + guess));
- }
- if (Math.abs(dnpv) < 1e-10) break;
- var next = guess - npv / dnpv;
- if (Math.abs(next - guess) < 1e-7) return next;
- guess = next;
- if (guess < -0.99 || guess > 10) return null;
+ var cocEl = document.getElementById('tr-coc');
+ if (isFinite(coc)) {
+ cocEl.textContent = (coc * 100).toFixed(1) + '%';
+ cocEl.className = 'tm-value ' + (coc >= 0 ? 'tm-green' : 'tm-red');
+ } else {
+ cocEl.innerHTML = '—';
+ cocEl.className = 'tm-value tm-navy';
}
- return guess;
}
// Run on load