The Busy Hours report answers "when are you busy?" — literally; that's the page's own heading. It's a heat map of completed appointments broken out by day of week and hour of day, meant to inform staffing, slot-duration settings, and which quiet windows are worth opening up to walk-ins or promos.
Finding the report
The main Reports hub (/app/reports) has a card labeled "Busy Hours," filed under the Operations category — click it and it routes straight to this report at /app/reports/busy-hours. (Before 2026-07-29 that card opened a smaller heat map inline, right on the catalog page: fixed to the last 90 days, business hours only, no peak-hour summary or day totals. That inline version has been removed — the card now takes you straight to the full report described below, so there's no separate "mini" version to worry about anymore.) You can also reach the page via the command palette (Cmd+Shift+K on Mac, Ctrl+Shift+K on Windows — note the Shift; plain Cmd/Ctrl+K is reserved for the AI Help bar and won't open this — search "busy hours," "heatmap," "demand," or "traffic," and pick "Reports · Busy hours" from the Pages section) or by typing the URL directly.
Reading the page
At the top right, four buttons let you pick the lookback window: 30, 60, 90, or 180 days — it opens on 90 days by default. When there's a clear busiest slot in the data, a highlighted callout card appears above the grid naming the exact day and hour (e.g., "Wed at 2p — 14 appointments over 90 days"); if the shop has too little completed-appointment history for a peak to make sense, that card simply doesn't render rather than showing a zero. Below it, the full grid runs all seven days (Sun–Sat) down the side against all 24 hours (12a–11p) across the top, with the exact count in each cell and a hover tooltip spelling out the day, hour, and appointment count for that cell. The day-of-week totals card underneath is a simple horizontal bar chart — one bar per weekday, each bar's width scaled against whichever day had the most completed appointments, with the raw total printed at the right edge.
Gotchas
The grid's color scale is relative, not absolute — the card description even says so ("scale calibrated to your peak cell"). Red doesn't mean "objectively slammed," it means "busiest cell relative to your own selected date range's peak." That has a real consequence: switching the day-range buttons from 30 to 180 days changes the max the whole grid is normalized against, so cells that read hot at 30 days can shift color, and the peak-hour callout can change day/hour entirely once a longer window is pulled in. Also worth remembering: this counts completed appointments only, per the page's own logic — a week that's fully booked out on the calendar won't show up as busy here until those appointments actually get marked complete, so don't read a quiet-looking grid as "we have nothing on the books."
Who can pull it up
Busy Hours is gated behind the shop-level "View financial reports" permission (shop.viewFinancialReports) — confirmed both in the page's own access check and in the server-side procedure it calls. That's also the permission the Reports hub checks before it'll even show the "Busy Hours" card — a teammate without it won't see the card in the catalog at all. If someone without that permission lands on the page anyway (a bookmarked or shared URL, say), they don't see a raw error — they get a dedicated screen: "You don't have permission to view this report," with the note that Busy Hours requires the "View financial reports" permission and a shop owner or admin needs to grant it in Settings → Team → Permissions. Note that the command palette entry itself isn't permission-filtered — it still shows up in a teammate's search results even without the permission — so if a teammate can't see the card in the Reports hub, they can still find and click "Reports · Busy hours" in the palette; they'll just land on that same "You don't have permission" screen instead of the report. Either way, the fix is the same permission toggle.