Free operator sheet · Stays in your browser

Monthly P&L
Snapshot.

A one-page P&L the operator can read in 90 seconds — not the accountant's version. Sales by daypart, COGS, labor, occupancy, marketing.

Pack: Operations & Margin Cadence: Monthly Private — runs in your browser

Fill it in

Monthly P&L Snapshot

Type your numbers — the math runs in your browser. Print it, save it as a CSV, or save it to your Workshop.

Worked example 80-seat dinner-only restaurant, suburban DC See what a Tuesday-morning fill-in looks like
Total sales (April, 30 days)$187,400
COGS — food + beverage$58,300
Total labor (hourly + salary + taxes)$61,500
Variable costs (cc fees + supplies)$11,200
Fixed costs (rent + insurance + utilities)$33,400
Prime cost63.9% · green
Restaurant operating profit$23,000
Operating margin12.3%

Green band on prime cost, double-digit operating margin — a healthy month. The watch-line is fixed costs at 17.8% of sales: their lease renews in October, and a single-digit rent bump tips next quarter into yellow. The conversation is rent before it's anything in the kitchen.

Composite-typical numbers — not a real shop. Use the rhythm, not the figures.

Period
Sales (net of sales tax)
Cost of goods sold
Labor (fully loaded)
Variable costs (other)
Fixed costs
Total sales $0.00
Prime cost (COGS + labor) $0.00
Prime cost % of sales 0.0%
Contribution margin % 0.0%
Operating profit (before tax) $0.00
Breakeven sales / day $0.00

Type the period numbers above. Independent full-service typically targets prime cost in the 55–65% band; profit lives in the gap below 65%.

Try a scenario — what if labor, COGS, or rent shifts?

Slide one or more, the verdict re-runs on top of your typed numbers. Lease-renewal pressure is one-sided — rent goes up or it stays.

Read the long version What the month adds that the week can't see, the three numbers operators conflate (operating profit vs cash flow vs owner's pay), the breakeven sales-per-day number, and what to do when the lease renewal slider goes red. Where the month lands — What the monthly P&L tells you that weekly can't →

+ (Math.round(abs * 100) / 100).toFixed(2); } function fmtPct(v) { return (Math.round(v * 10) / 10).toFixed(1) + '%'; } // D8 · Read what-if slider state. All three are multiplicative // percent deltas applied on top of the typed line items. function whatif() { var f = document.getElementById('sheet-fields'); if (!f || !f.whatif_labor) return { labor: 0, cogs: 0, occ: 0 }; return { labor: n(f.whatif_labor.value), cogs: n(f.whatif_cogs.value), occ: n(f.whatif_occ.value), }; } function recalc() { var f = document.getElementById('sheet-fields'); if (!f) return; var w = whatif(); var sales = n(f.sales_lunch.value) + n(f.sales_dinner.value) + n(f.sales_bar.value) + n(f.sales_togo.value) + n(f.sales_other.value); var rawCogs = n(f.cogs_food.value) + n(f.cogs_bev.value); var rawLabor = n(f.labor_hourly.value) + n(f.labor_salary.value) + n(f.labor_taxes.value); var rawOcc = n(f.fixed_occupancy.value); // D8 — multiplicative deltas on top of the typed line items. var cogs = rawCogs * (1 + w.cogs / 100); var labor = rawLabor * (1 + w.labor / 100); var occ = rawOcc * (1 + w.occ / 100); var prime = cogs + labor; var variable = n(f.var_cc_fees.value) + n(f.var_supplies.value); var fixed = occ + n(f.fixed_utilities.value) + n(f.fixed_insurance.value) + n(f.fixed_marketing.value) + n(f.fixed_other.value); var primePct = sales > 0 ? (prime / sales) * 100 : 0; var contribPct = sales > 0 ? ((sales - prime - variable) / sales) * 100 : 0; var profit = sales - prime - variable - fixed; // Breakeven: sales such that contribution covers fixed. // Contribution rate = (sales - prime - variable) / sales = contribPct/100. var contribRate = contribPct / 100; var breakevenMonth = contribRate > 0 ? fixed / contribRate : 0; var days = Math.max(1, n(f.days.value)); var breakevenDay = breakevenMonth / days; // Update what-if output labels. if (f.whatif_labor_out) f.whatif_labor_out.value = (w.labor >= 0 ? '+' : '') + w.labor.toFixed(0) + '%'; if (f.whatif_cogs_out) f.whatif_cogs_out.value = (w.cogs >= 0 ? '+' : '') + w.cogs.toFixed(1) + '%'; if (f.whatif_occ_out) f.whatif_occ_out.value = '+' + w.occ.toFixed(0) + '%'; document.querySelector('[data-output="total_sales"]').textContent = fmt$(sales); document.querySelector('[data-output="prime_dollars"]').textContent = fmt$(prime); var primeEl = document.querySelector('[data-output="prime_pct"]'); primeEl.textContent = fmtPct(primePct); // D9 — band routes through centralized benchmarks. Same // metric key as weekly-prime-cost-worksheet so the two // sheets agree on what "healthy" means. if (window.Bench && window.Bench.evaluate) { var bp = window.Bench.evaluate('prime_cost_pct', primePct); if (bp && bp.band) primeEl.dataset.band = bp.band; } else { primeEl.dataset.band = primePct < 60 ? 'good' : (primePct < 65 ? 'warn' : 'bad'); } var contribEl = document.querySelector('[data-output="contrib_pct"]'); contribEl.textContent = fmtPct(contribPct); contribEl.dataset.band = contribPct > 30 ? 'good' : (contribPct > 20 ? 'warn' : 'bad'); var profitEl = document.querySelector('[data-output="profit"]'); profitEl.textContent = fmt$(profit); profitEl.dataset.band = profit > 0 ? 'good' : (profit === 0 ? 'idle' : 'bad'); document.querySelector('[data-output="breakeven_per_day"]').textContent = fmt$(breakevenDay); var callout = document.querySelector('[data-output="callout"]'); if (!callout) return; if (sales <= 0) { callout.textContent = 'Type the period numbers above. Independent full-service typically targets prime cost in the 55–65% band; profit lives in the gap below 65%.'; } else if (profit < 0) { callout.textContent = 'This month booked a loss of ' + fmt$(Math.abs(profit)) + '. The fix is almost always in prime cost (' + fmtPct(primePct) + ' here) before fixed costs — labor or food, name the bigger driver and act this month.'; } else if (primePct >= 65) { callout.textContent = 'Prime cost above the 65% ceiling. This month was profitable on the back of low fixed costs; the model breaks the moment rent or utilities tick up.'; } else if (primePct >= 60) { callout.textContent = 'Prime cost in the warning band. Tight discipline next month — small drift here compounds quickly.'; } else { callout.textContent = 'Healthy month. Prime cost ' + fmtPct(primePct) + ', operating profit ' + fmt$(profit) + '. Breakeven sales runs ' + fmt$(breakevenDay) + ' per day.'; } } function collect() { var f = document.getElementById('sheet-fields'); if (!f) return [['Field', 'Value']]; return [ ['Field', 'Value'], ['Period', f.period.value || ''], ['Operating days', f.days.value || ''], [], ['Lunch / brunch', f.sales_lunch.value || '0'], ['Dinner', f.sales_dinner.value || '0'], ['Bar & beverage', f.sales_bar.value || '0'], ['To-go & delivery', f.sales_togo.value || '0'], ['Catering & other', f.sales_other.value || '0'], ['Total sales', document.querySelector('[data-output="total_sales"]').textContent], [], ['COGS — food', f.cogs_food.value || '0'], ['COGS — beverage', f.cogs_bev.value || '0'], [], ['Labor — hourly', f.labor_hourly.value || '0'], ['Labor — salaried', f.labor_salary.value || '0'], ['Labor — taxes & benefits', f.labor_taxes.value || '0'], [], ['CC processing', f.var_cc_fees.value || '0'], ['Supplies / paper', f.var_supplies.value || '0'], [], ['Occupancy', f.fixed_occupancy.value || '0'], ['Utilities', f.fixed_utilities.value || '0'], ['Insurance & licenses', f.fixed_insurance.value || '0'], ['Marketing & subs', f.fixed_marketing.value || '0'], ['Other fixed', f.fixed_other.value || '0'], [], ['Prime cost ($)', document.querySelector('[data-output="prime_dollars"]').textContent], ['Prime cost (%)', document.querySelector('[data-output="prime_pct"]').textContent], ['Contribution margin (%)',document.querySelector('[data-output="contrib_pct"]').textContent], ['Operating profit', document.querySelector('[data-output="profit"]').textContent], ['Breakeven / day', document.querySelector('[data-output="breakeven_per_day"]').textContent], ['Callout', document.querySelector('[data-output="callout"]').textContent], ]; } // D8 · Reset scenario sliders. document.addEventListener('click', function (ev) { if (ev.target && ev.target.matches && ev.target.matches('[data-whatif-reset]')) { ev.preventDefault(); var f = document.getElementById('sheet-fields'); if (!f) return; if (f.whatif_labor) f.whatif_labor.value = 0; if (f.whatif_cogs) f.whatif_cogs.value = 0; if (f.whatif_occ) f.whatif_occ.value = 0; f.dispatchEvent(new Event('input', { bubbles: true })); } }); if (window.SheetPage) { window.SheetPage.register({ slug: 'monthly-pnl-snapshot', collect: collect, recalc: recalc }); } })();

Keyboard: ⌘P print · ⌘S download CSV · ⌘↵ save to Workshop

When to use it

Pull this sheet out when —

  • First week of every month, against the prior month closed by your bookkeeper.
  • Before sitting down with a partner, lender, or landlord about the business.
  • After a menu change, price raise, or labor reset — see what actually moved.
Common mistakes

What operators get wrong

  • Lumping owner draw into labor. Owner pay is a distribution; labor is the line that pays the staff.
  • Forgetting credit-card fees as a variable cost. 2.6% on every dine-in dollar is not rounding error.
  • Counting marketing as fixed when half is platform-promo subsidy. The subsidy ends; the cost stays.
Pairs with

The tools, terms, and articles this sheet sits next to.

Free, no signup. Your numbers never leave this page.