A MagicMirror² module that displays habit tracking data as heatmaps using Heat.js. Reads a defined json and dynamically updates if values change.
cd ~/MagicMirror/modules
git clone https://github.com/your-username/MMM-HeatMaps.gitNo npm install needed — zero dependencies.
- Add the module to your
config.js:
{
module: "MMM-HeatMaps",
position: "bottom_left",
header: "Exercise",
config: {
dataFile: "habits/exercise.json",
},
},- Create a JSON file at
modules/MMM-HeatMaps/habits/exercise.json:
{
"2026-01-15": 3,
"2026-01-16": 1,
"2026-01-18": 4
}Keys are dates (YYYY-MM-DD), values are counts. Days with 0 or missing entries stay blank. Edits to the file are picked up automatically — no restart needed.
Add a separate module entry for each habit. Place them in the same position to stack them vertically:
{
module: "MMM-HeatMaps",
position: "bottom_left",
header: "Exercise",
config: {
dataFile: "habits/exercise.json",
},
},
{
module: "MMM-HeatMaps",
position: "bottom_left",
header: "Putting Practice",
config: {
dataFile: "habits/putting.json",
},
},All options are set inside the config block. The heatJsOptions object is passed directly to Heat.js, so every Heat.js binding option is supported. Options are deep-merged with the module's defaults — you only need to specify what you want to change.
| Option | Type | Default | Description |
|---|---|---|---|
dataFile |
string or string[] |
"habits/exercise.json" |
Path to the JSON data file, relative to the module directory. Pass an array for fallback paths. |
lastNMonths |
number |
0 |
Only show the last N months. 0 shows the full year. |
heatJsOptions.defaultView |
string |
"map" |
View shown on load: "map", "chart", "line", "days", "months", or "color-ranges". |
heatJsOptions.guide.enabled |
boolean |
true |
Show the "Less / More" legend bar beneath the heatmap. |
heatJsOptions.title.showText |
boolean |
true |
Show a title above the heatmap. |
heatJsOptions.title.text |
string |
"" |
Title text. |
heatJsOptions.title.showYearSelector |
boolean |
true |
Show year navigation arrows. |
heatJsOptions.title.showTitleDropDownButton |
boolean |
true |
Show the dropdown arrow next to the title. |
heatJsOptions.title.showSectionText |
boolean |
true |
Show the "Map" / "Chart" label in the title bar. |
heatJsOptions.views.map.highlightCurrentDay |
boolean |
false |
Outline today's cell. |
heatJsOptions.views.map.showMonthDayGaps |
boolean |
true |
Add spacing between months. |
heatJsOptions.views.chart.enabled |
boolean |
true |
Enable the chart view. |
heatJsOptions.views.line.enabled |
boolean |
true |
Enable the line view. |
heatJsOptions.views.days.enabled |
boolean |
true |
Enable the days view. |
heatJsOptions.views.months.enabled |
boolean |
true |
Enable the months view. |
heatJsOptions.views.colorRanges.enabled |
boolean |
true |
Enable the color-ranges view. |
heatJsOptions.colorRanges |
array |
(4-tier green) | Custom color thresholds — see Color Themes. |
These are the most useful options. For the complete list, see the Heat.js documentation.
A minimal, clean heatmap that shows the last 4 months of exercise. Only the map view is enabled — no charts, no legend, no extra UI chrome. Days you exercised light up in blue.
{
module: "MMM-HeatMaps",
position: "bottom_left",
config: {
dataFile: "habits/exercise.json",
lastNMonths: 4,
heatJsOptions: {
defaultView: "map",
guide: {
enabled: false,
},
title: {
showText: true,
text: "Exercise",
showYearSelector: false,
showTitleDropDownButton: false,
showSectionText: false,
},
views: {
map: {
highlightCurrentDay: true,
showMonthDayGaps: false,
},
chart: { enabled: false },
line: { enabled: false },
days: { enabled: false },
months: { enabled: false },
colorRanges: { enabled: false },
},
colorRanges: [
{ id: "1", name: "Practiced", minimum: 1, cssClassName: "day-color-blue-4" },
],
},
},
},The module ships with four color themes. Each has four intensity tiers you can reference in colorRanges:
| Theme | CSS Classes |
|---|---|
| Green (default) | day-color-1 through day-color-4 |
| Baby Blue | day-color-blue-1 through day-color-blue-4 |
| Pink | day-color-pink-1 through day-color-pink-4 |
| Purple | day-color-purple-1 through day-color-purple-4 |
Example — multi-tier green (the default behavior):
colorRanges: [
{ id: "1", name: "Light", minimum: 1, cssClassName: "day-color-1" },
{ id: "2", name: "Medium", minimum: 2, cssClassName: "day-color-2" },
{ id: "3", name: "Strong", minimum: 3, cssClassName: "day-color-3" },
{ id: "4", name: "Max", minimum: 4, cssClassName: "day-color-4" },
],Example — single-color completion tracking:
colorRanges: [
{ id: "1", name: "Done", minimum: 1, cssClassName: "day-color-blue-3" },
],If you run the same config on multiple machines (e.g., local dev and a Raspberry Pi), pass an array of paths for dataFile. The module uses the first file that exists:
dataFile: [
"/home/admin/Documents/MM/modules/MMM-HeatMaps/habits/exercise.json",
"habits/exercise.json",
],MIT
