# Calendar heatmap > Daily activity over a year, read for streaks and gaps. - Canonical: https://patterns.konigi.com/dashboards/calendar-heatmap - Group: Visual representation - Level: implementation - Status: published - Updated: September 10, 2026 - Also called: contribution graph, punch card, day grid --- ## Problem A year of daily numbers is 365 points. As a line it is a hairy band where weekends and weekdays average together. The viewer wants to see that Tuesdays are busy, that August was quiet, and that one week in March went strange. ## Solution One cell per day, laid out as a calendar. Weeks as columns, days of the week as rows, colour for magnitude. A year fits in a strip a few centimetres tall and the eye picks out both the weekly rhythm and the seasonal one without being told to look. The layout is the encoding. Because every row is the same weekday, a weekend effect appears as two consistently pale rows across the whole chart, which no line chart shows without being asked. Because columns are consecutive weeks, a quiet fortnight is a pale vertical gap. Both readings come free from the arrangement. GitHub's contribution graph is what made the pattern universally legible, and it also shows the pattern's main weakness. Its cells are bucketed into a handful of intensity levels rather than mapped continuously, so a day with 4 commits and a day with 40 can look similar. That is a deliberate trade: coarse buckets make the rhythm readable and make individual days approximate. It works for that use and fails for any question about magnitude. The variant worth knowing is the punch card: hour of day against day of week, cells sized or coloured by volume. Same idea, different cycle, and usually a better answer for anything with a daily shape rather than a weekly one. ## Use when The data has a genuine calendar rhythm, the period is long enough that a line chart becomes dense, and the question is about pattern rather than value. Deploys, incidents, sales, activity, on-call load. ## Don't use when Exact values matter, or the period is short. A month of data in this layout is four columns and a line chart says more. Also poor for anything without a weekly cycle, where the row structure encodes nothing and only adds work. ## Trade-offs Colour carries all the magnitude, so the scale choice determines what is visible and a poorly chosen ramp can flatten a real seasonal change into uniformity. Outliers dominate: one enormous day pushes everything else to the bottom of the scale unless the range is clamped. The grid is small, so it fails at wallboard distance and on phones. And the pattern is strongly associated with GitHub, which means viewers arrive expecting "activity" semantics and read a gap as someone not working rather than as a metric being low. ## Checklist - Does this data actually have a weekly or seasonal cycle worth showing? - Is the colour scale continuous or bucketed, and does that suit the question? - Is the range clamped so one outlier does not flatten the rest? - Is the scale legend present, with real values on it? - Does a zero-value day look different from a day with no data? - Are weekends or non-working days distinguished where that matters? - Which day does the week start on, and does it match the audience's convention? - Is there a hover giving the date and the exact value? - Does the grid stay legible at the size it renders at? - Would viewers import GitHub's "activity" reading and misinterpret a pale cell? ## Compare **GitHub's contribution graph** is the reference implementation and the reason the pattern needs no explaining, using coarse intensity buckets that make the rhythm legible while making individual days deliberately approximate. **Grafana** has no calendar-layout panel in core, so teams reach for community plugins or reshape data into the standard heatmap, losing the calendar semantics that make the layout worth having. **Datadog** applies the punch-card variant to incident and alert timing, which is the strongest operational use of the idea because on-call load genuinely has an hour-of-day shape. **Observable and D3** are where most bespoke versions get built, which is why the pattern is common in one-off analyses and rare inside monitoring products. ## Related Heatmap is the general form, with continuous axes rather than calendar ones. Cohort grid uses the same cell-grid reading against cohort age. Sequential and diverging scales decides whether the colour ramp reveals or flattens. Status history is the strip version when the value is a state rather than a magnitude. Time series is the alternative when exact values matter more than rhythm. ## Examples ### GitHub (GitHub, Inc.) The contribution graph is the calendar heatmap every other product copied, and its five-step bucketing is the deliberate trade that made it legible. **Profile / contribution graph** — captured September 11, 2026, github.com, signed out (public profile). public, medium density, light theme, desktop-web. The calendar heatmap everyone else copied, and a good demonstration of what it trades away. 3,703 contributions across 365 days is about ten a day, and the scale has five steps, so almost every cell here lands in the middle two and the year reads as one flat field of mid-green. A day with five commits and a day with twenty-five are the same colour. That is the deliberate choice—coarse buckets make the rhythm readable and make any individual day approximate—but on a profile this active there is no rhythm left to read either, because the bucketing has flattened the variation it was meant to reveal. The layout still earns its place: weeks as columns and weekdays as rows means a weekend effect would show as two pale rows across the full width, and here it doesn't, which tells you something true about this person's week. The panel beside it is worse off. It is a four-axis diagram of code review, issues, pull requests and commits, and with 100% commits it collapses to a single straight line. Hotspots in this capture: - [Calendar heatmap](https://patterns.konigi.com/dashboards/calendar-heatmap) *(this pattern)* — Fifty-three columns of weeks, seven rows of weekdays, and only Mon, Wed and Fri labelled to save the space. - [KPI tile](https://patterns.konigi.com/dashboards/kpi-tile) — The total sits above the grid, so the cells have a denominator. Most calendar heatmaps omit this. - [Sequential and diverging scales](https://patterns.konigi.com/dashboards/sequential-and-diverging-scales) — Five discrete steps rather than a continuous ramp, which is why ten commits and thirty share a colour. - [Time-range picker](https://patterns.konigi.com/dashboards/time-range-picker) — Sixteen years as a list. No arbitrary range, no relative window—the only unit on offer is a calendar year. ### Tableau Public (Salesforce) Thousands of dashboards made by people who are not designers, published without a review step. The best available sample of what the pattern language looks like in the wild. **Emergency Department / Clinical Dashboard** — captured September 11, 2026, Tableau Public embed view; emergency department patient flow workbook. analytical, dense density, light theme, desktop-web. Worth recording partly for what it is not. I went looking for a bed map, and what the public web has instead is this: analysis about an emergency department rather than the board the department actually runs on. There is no row per bed, no occupancy, no waiting-for column. Track boards live inside the patient record and never leave it, which is why that pattern has no example here and probably never will. What this does have is the punch card the calendar-heatmap entry names as the better answer for anything with a daily rather than weekly shape: weekday down the side, hour of day across the top, and the busy band from roughly ten to twenty-one is legible instantly without anyone labelling it. Its ramp is the problem—a blue-to-orange diverging scale on a patient count, which has no meaningful centre, so the midpoint sits wherever the data happened to average. The treemap beneath it degenerates into a mosaic of unlabelled slivers about a third of the way across. Hotspots in this capture: - [Calendar heatmap](https://patterns.konigi.com/dashboards/calendar-heatmap) *(this pattern)* — The punch-card variant: hour of day against weekday. The busy band reads in a second, from the layout alone. - [Small multiples](https://patterns.konigi.com/dashboards/small-multiples) — Twelve month panels on one shared y-axis, so the seasonal fall from 265 in May to 52 in December is comparable across all of them. - [Sequential and diverging scales](https://patterns.konigi.com/dashboards/sequential-and-diverging-scales) — A diverging blue-orange ramp on wait time, which has no meaningful centre, so the midpoint is wherever the mean fell. - [Target and progress](https://patterns.konigi.com/dashboards/target-and-progress) — Each unit against a median reference line, green below and red above. A target marker doing the work of a threshold. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) — One dropdown, full width, showing its selected value rather than a count. Everything below is scoped to it. ## Related patterns - [Heatmap](https://patterns.konigi.com/dashboards/heatmap) — Thousands of events per second can't be drawn as points; the viewer needs density. - [Cohort grid](https://patterns.konigi.com/dashboards/cohort-grid) — Retention differs by when people arrived; the viewer needs cohorts side by side over time. - [Sequential and diverging scales](https://patterns.konigi.com/dashboards/sequential-and-diverging-scales) — Magnitude and direction need encoding in color, and the wrong ramp lies. - [Status history](https://patterns.konigi.com/dashboards/status-history) — The viewer needs to see when something was up, down, or degraded, over days, in one row. - [Time series](https://patterns.konigi.com/dashboards/time-series) — The viewer needs to see how a value changed over time and spot the moment it changed. ## Sources - [GitHub, Viewing contributions on your profile](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-settings-on-your-profile/viewing-contributions-on-your-profile) - [Grafana, Heatmap panel](https://grafana.com/docs/grafana/latest/visualizations/panels-visualizations/visualizations/heatmap/) - [Bach et al., Dashboard Design Patterns](https://dashboarddesignpatterns.github.io/patterns.html) --- Screenshots on patterns.konigi.com are reproduced for commentary and criticism. Product names and marks belong to their owners.