# cal-heatmap: a calendar heatmap whose stylesheet is an export subpath

> A charting library for time series calendar heatmaps, the shape GitHub uses for contribution graphs. The build is Rollup with Babel, the tests split into unit and BrowserStack end to end, and the newest published version is still a beta from 2024.

**wa0x6e/cal-heatmap** — Cal-Heatmap is a javascript charting library to create a time-series calendar heatmap

- Repository: https://github.com/wa0x6e/cal-heatmap
- Website: http://cal-heatmap.com
- Stars: 3,128 · Forks: 305
- Language: TypeScript
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/wa0x6e-cal-heatmap

## The GitHub contribution graph, with more d3 behind it

The pitch is a chart you already know. Cal-heatmap draws a calendar heatmap for time series data, the same layout as the contribution graph on a GitHub profile, and the stated difference is everything the built in version does not let you change.

The feature list is specific rather than aspirational: animated date navigation, customisation of the time interval, full control over layout and UI, locale and timezone support, a plugins system, broad browser support, and right to left layout. Timezone and locale in the same list is the part worth pausing on for anyone charting events rather than commits, because a heatmap that silently buckets by the viewer's timezone is a different chart from the one you designed.

Documentation lives on its own site at cal-heatmap.com, which is also the declared homepage, and the project describes itself as a javascript module rather than a framework component.

## The exports map ships the stylesheet as a subpath

The package is ESM first and the exports map is where the details live:

```json
  "exports": {
    ".": {
      "import": "./dist/cal-heatmap.esm.js",
      "require": "./dist/cal-heatmap.js",
      "types": "./src/types.d.ts"
    },
    "./package.json": "./package.json",
    "./cal-heatmap.css": "./dist/cal-heatmap.css"
  },
```

Three things follow. There are two built bundles, one ESM and one CommonJS, so an older bundler still resolves. The types come from `src/types.d.ts` rather than from a declaration folder in `dist`, so the published type definitions are read straight out of the source tree. And the stylesheet is its own import path rather than something you dig out of `dist` by hand, which is the difference between a supported import and a fragile one.

The package also declares `"type": "module"` and `"node": ">=14.16"`, and the type definition path is repeated at the top level for tooling that looks there.

## Nine runtime dependencies, one of them a charting library

The dependency set is small and mostly a d3 subset: `d3-color`, `d3-fetch`, `d3-selection` and `d3-transition`, plus `dayjs` for dates, `eventemitter3` for events, `lodash-es` for utilities and `core-js` for polyfills.

The one that stands out is `@observablehq/plot` at `^0.6.0`, which is a charting library of its own and is a runtime dependency rather than a development one. Whatever it is used for, it is the heaviest thing a page pulls in when it loads a calendar heatmap, so it is worth knowing it is there before you optimise bundle size.

`eventemitter3` explains how the plugin system is likely wired, since a plugin needs to hear about events without the chart importing the plugin. Nothing in the visible metadata documents the plugin interface itself; the documentation site is where that lives.

## Browsers are declared, not assumed

Support is stated in the manifest rather than left to a claim in the prose. The browserslist query is `last 2 versions, not dead, > 0.2%`, which is a floor rather than an exhaustive list: it covers the last two versions of every browser that still has meaningful traffic, and excludes anything marked dead or below a fraction of a percent.

Two supporting pieces make that query mean something at runtime. `core-js` is a runtime dependency, so the polyfills ship with the library rather than being left to the application, and `autoprefixer` is a development dependency in the build, so vendor prefixes are resolved when the bundle is produced.

There is also a `browser-support.md` at the top level, which is where the project's own account of coverage lives, and the README's feature list calls out broad browser support as a headline item rather than burying it.

## Rollup and Babel build it, Jest and BrowserStack test it

The build is Rollup, configured in `rollup.config.js`, with a plugin per concern: babel for transpilation, commonjs for interop, json for imports, node-resolve, replace for constants, terser for minification and typescript for the type source. `babel.config.json` holds the transpiler settings, and `index.js` sits at the repository root next to `src/`.

Testing is split into two configurations, `jest.config.mjs` and `jest-e2e.config.mjs`, and the development dependencies explain what the second one needs: `@types/selenium-webdriver` and `browserstack-local` mean the end to end suite drives real browsers through a local tunnel to BrowserStack rather than a headless stub. That is the expensive half of the setup and it is deliberate, because a canvas and SVG library fails in ways a jsdom environment hides.

Lint and format are equally explicit: `.eslintrc.json` with the airbnb base and TypeScript configs through `@typescript-eslint`, plus `.prettierrc`, `.editorconfig` and `.nvmrc`. Release notes are generated by `cz-conventional-changelog` into `CHANGELOG.md`, so commit message prefixes decide the changelog.

## The newest release is a beta from 2024, the tree is not

`package.json` carries version `4.3.0-beta.4`, and the release list agrees with it: 4.3.0-beta.4 published 2024-03-03, 4.3.0-beta.1 on 2024-02-18, and the last stable line, 4.2.4, on 2023-12-29.

The repository's last commit in this snapshot is dated 2026-09-12, on the default branch master. So the npm line has been sitting on a beta for more than two years while development continued. If you depend on it, that gap is the fact to plan around: the beta tag is the newest thing you can install from a registry, and anything newer exists only on master.

Two smaller inconsistencies are worth noting while you are in the metadata. The README links its licence as `./LICENSE` while the top level file is spelled `LICENCE`, so a tool that fetches that path gets nothing. And the keywords include `d3js` even though the manifest imports four individual d3 modules rather than the d3 bundle.

## Conclusion

Use cal-heatmap when you want a contribution style calendar for a date range and want to control the layout, locale and timezone yourself rather than accept a fixed chart. It gives you what the GitHub graph gives you and several things it does not, including animated navigation, custom time intervals, right to left layout and a plugin system. Skip it if you need a maintained stable release trail, because the published line is still a beta and the last tag is more than two years old while commits continue on master. Before you pin a version, check what the exports map gives you, since the stylesheet and the type definitions travel as separate subpaths, and decide whether the browser floor in the browserslist query matches the machines your users have.

## FAQ

### What does cal-heatmap draw?

It draws a time series calendar heatmap, the layout GitHub uses for contribution graphs, and adds animated date navigation, custom time intervals, layout and UI controls, locale and timezone support, a plugins system and right to left layout.

### How do I import the cal-heatmap stylesheet?

The package exports it as a subpath: ./cal-heatmap.css resolves to ./dist/cal-heatmap.css in the exports map, so it is a supported import rather than a file you reach into dist for by hand.

### What Node and browser versions does cal-heatmap support?

The manifest declares node >=14.16 and a browserslist query of last 2 versions, not dead, greater than 0.2 percent. The repository also carries an .nvmrc for contributors and a browser-support.md describing coverage.

### Which charting libraries does cal-heatmap depend on?

The runtime dependencies are four d3 modules, d3-color, d3-fetch, d3-selection and d3-transition, plus @observablehq/plot, dayjs, eventemitter3, lodash-es and core-js. Plot is a charting library in its own right and ships as a runtime dependency.

### Which version of cal-heatmap is published?

The newest is 4.3.0-beta.4, a beta, and the manifest carries the same version. Before it came 4.3.0-beta.1 and the stable 4.2.4, and repository commits continue on master past that line.

## Sources

- [License: MIT](https://github.com/wa0x6e/cal-heatmap/blob/master/LICENSE)
- [Project website](http://cal-heatmap.com)
- [README](https://github.com/wa0x6e/cal-heatmap/blob/master/README.md)
- [Releases](https://github.com/wa0x6e/cal-heatmap/releases)
- [wa0x6e/cal-heatmap on GitHub](https://github.com/wa0x6e/cal-heatmap)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/wa0x6e-cal-heatmap
