Skip to content
Vanilla JS  ·  MIT  ·  no framework

Your activity data.
Beautifully presented.

Streakr renders contribution data from anywhere. You own acquisition, caching and credentials; Streakr owns the responsive heatmap, ring, filters and statistics.

Star on GitHub
Bundle ESM + 1 CSS file
Runtime deps 0
Data contract 1 serializable shape
Layouts heatmap + ring
License MIT
01 — Live demo

Both layouts, side by side

The same component draws a 53-week heatmap in wide containers and a radial year ring under 520px — it switches on container width, not on user agent. Everything here is a real instance: toggle a source chip and the grid, the ring and the records recompute.

Desktop — heatmap container ≥ 520px
Mobile — ring < 520px
9:41 ring
Controls
Your config, as code
02 — Contract

Any data. One shape.

GitHub
Visual preset
Render counts from GitHub when your data uses the github source key.
GitLab
Visual preset
Display GitLab activity from your API, snapshot, database, or build.
Bitbucket
Visual preset
Use the built-in Bitbucket color and icon with data you provide.
Claude
Visual preset
Attribute activity to Claude after your own pipeline classifies it.
Codex
Visual preset
Give Codex its own source count, color, icon, and toggle.
opencode
Visual preset
Present opencode activity without coupling Streakr to your collector.
Copilot
Visual preset
Present Copilot counts from whichever acquisition flow you trust.
01
One explicit contract
Pass YYYY-MM-DD, count, and optional source counts. Streakr validates them before drawing.
02
You own acquisition
Fetch on a server, read a snapshot, query your database, or build the array locally.
03
Recipes when useful
Start from an official recipe, copy it into your app, and change every detail you need.
03 — Records

Four numbers, computed for you

Streaks come out of the validated daily series, so they respect whichever sources are switched on. Select the current year and the card swaps Active Rate for Current Streak.

Total Contributions
Sum of every enabled source across the selected year.
Best Streak
Longest unbroken run of days with at least one contribution.
Current Streak
Counted backwards from today — the card swaps in Active Rate for past years.
Active Days
Days with any contribution from an enabled source.
04 — Install

Data in. Calendar out.

Ships ESM plus one stylesheet with no CSS dependencies. Drop it into a bundler, or pull it straight off a CDN in a plain HTML file.

# install
npm install @rosado-io/streakr
 
// mount
import { createStreakr } from '@rosado-io/streakr'
import '@rosado-io/streakr/styles.css'
 
createStreakr({
  target: document.querySelector('#streakr'),
  theme: 'dark',
  years: [2024, 2025, 2026],
  days: activity,
})
05 — Recipes

Bring your data. Or borrow a recipe.

Recipes show one way to acquire and adapt data, but they stay in your application. Keep them, replace them, or connect your own API—the renderer only cares about its small serializable contract.

fix(grid): pad trailing week columns
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
human 1 claude 1 codex 1
// recipe: adapt a public GitHub calendar response
const response = await fetch(
  'https://github-contributions-api.jogruber.de/v4/octocat?y=2026'
)
const payload = await response.json()
 
const days = payload.contributions.map((day) => ({
  date: day.date,
  count: day.count,
  sources: { github: day.count },
}))
 
createStreakr({
  target: document.querySelector('#streakr'),
  years: [2026],
  days,
})

Put your year on the page.

Free, MIT and framework-free. Read the docs, or clone the repo and run the demo locally.