Search by

ernestdefoe / cadence

ernestdefoe

Cadence — see a member's rhythm, not just their volume. An activity map on every profile, with the day you click actually opening that day.

Package info

github.com/ernestdefoe/cadence

Forum

Type:flarum-extension

pkg:composer/ernestdefoe/cadence

Fund package maintenance!

Buy Me A Coffee

Statistics

Installs: 68

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.3.0 2026-10-24 13:38 UTC

This package is auto-updated.

Last update: 2026-10-24 14:05:26 UTC


README

See a member's rhythm, not just their volume.

An activity map on every profile — and, if you want it, a compact trace beside every post and on user cards.

Flarum Licence

A member's activity map: a year of squares, darker where they did more, with All, Discussions and Replies above it

Press any square and it tells you what happened that day: 2 things on September 7, 2026 — 1 discussion started · 1 reply.

On a phone the map scrolls sideways inside the profile card, and it opens on the newest weeks:

The map on a phone, opened on the most recent weeks

Why not just copy GitHub's graph

Because GitHub's has six problems, and on a forum they matter more than they do on a code host.

  • It counts one undifferentiated thing. Cadence separates discussions, replies, likes, reactions and best answers, and only offers the kinds a member actually has.
  • Its scale is relative to each person's own busiest day, so someone with two posts all year and someone with two hundred produce similar-looking graphs. Cadence uses an absolute scale with a legend that states real numbers, so two profiles can be compared.
  • It shows a fixed year. Someone who joined last month gets eleven months of grey, which reads as "inactive" when the truth is "new". Cadence starts at the join date.
  • Colour is the only encoding. Cadence's levels differ in lightness as well as hue, and every square carries its real numbers for screen readers.
  • It's decoration. Cadence's squares are buttons: press one and it tells you what happened that day.
  • It can't tell you when someone is around. Cadence stores hourly, so a day is the reader's day rather than the server's.

Where it shows

Placement Default
The full map on member profiles On
A 26-week sparkline beside every post Off
A sparkline on user cards Off

🚨 The sparklines cost no extra requests. They read an attribute that rides along on the user the page had already loaded. A placement that appears once per post cannot fetch its own data — thirty posts would be thirty requests, which is how a shared host runs out of database connections and returns 500 for the whole forum rather than for the decoration that caused it.

Daily streaks

A flame for every member who comes back tomorrow.

The streaks leaderboard: your flame with its tier, rank and the road to the next tier; Current, All-time and Hall of Flames; the board's figures, the bonfire and the tiers

A streak counts the days in a row a member shows up — in their timezone, not the server's — and turns it into a flame: after their name in posts, on their card, in the header and on a leaderboard where the next rival is always within reach.

  • You choose what keeps it alight: contributing (posting, replying, liking or reacting) or simply visiting.
  • It starts with your history. Other streak add-ons start every member at zero; Cadence already holds your forum's activity, so the member who has posted every day for two years gets a two-year flame on day one. A flame after every author's name in a discussion

The header flame open: today's streak, the next tier and the month, with fed days filled in

  • Tiers you design — days, colour, icon, glow — and seasonal flames for the dates you pick. Members with a birthday in Calendar get a golden flame.

  • A missed day is not the end. Milestones earn freezes that melt on their own to save a missed day, and a long flame that goes out leaves embers: post within 48 hours to bring half of it back.

  • The leaderboard: Current, All-time and the Hall of Flames, your rank, the member just ahead of you, and a community bonfire everyone feeds together. A member's Streak tab: their flame, a year of fed days, the month and their journal

  • Alerts members control: milestones, new tiers and records as alerts and a toast on the first page of the day, and an "at risk" email before a flame goes out.

  • Widgets for Bespoke and fof/forum-widgets-core: My flame, Top flames, the Bonfire. The first reply of the seventh day: Milestone reached, You reached Kindled, New personal best

  • Admin: an overview of the whole board and a flame sheet for every member — give freezes, set, revive or reset — with every change journaled.

Admin: key figures, flames by tier, the longest flames alight and recent events

Admin: the tier editor with a live preview of each flame

The leaderboard on a phone

🚨 It costs your forum one query per page, however many flames are on it. The flame rides along on users the page already loaded. The leaderboard, the profile tab and the header menu load their code only when opened.

For the "at risk" and "embers" alerts, Flarum's scheduler must be running (* * * * * php flarum schedule:run). Without it, flames still go out on time — only those two alerts wait.

Don't want streaks? Turn off Daily streaks at the top of Cadence's settings. That one switch removes everything (the flames, header button, Streaks link, leaderboard, profile tab, widgets, alerts and emails) and stops counting, while the activity map keeps working. Nothing is deleted, so turning it back on picks up where you left off.

Only activity the map's audience could see counts toward a streak, and in visit mode a member who hides their online status keeps their visit days to themselves.

Settings

Admin → Cadence:

Cadence's settings: the map on profiles, a sparkline beside posts, and one on user cards

Installation

composer require ernestdefoe/cadence
php flarum cache:clear

Then enable Cadence in the admin. Enabling returns at once: building every member's activity map and flame from your forum's history happens in the background, a slice of members at a time —

  • on your queue, if the forum has one (database, Redis/Horizon);
  • otherwise every minute from the scheduler (php flarum schedule:run in cron, as Flarum recommends);
  • and while the Cadence settings page is open, which shows the progress ("Building streaks: 42%"). Flames appear as they are built.

On a big forum, or to watch it finish, run it yourself:

php flarum cadence:rebuild-streaks

It shows a progress bar, resumes a rebuild that is pending or was interrupted (stop it with Ctrl+C and run it again any time), and with --fresh starts again from the first member. As a guide, 500,000 posts and 15,000 members take about 15 seconds on MySQL.

php flarum cadence:rebuild

Rebuilds the posts and likes buckets from your forum's own tables, then every flame. Safe to re-run.

Only activity a guest could see is counted — or, on a forum guests cannot open, activity an ordinary member could see. Posts in staff-only tags, private discussions and direct messages never reach a map, because the map is one set of counts shown to everyone who can open the profile. Change who can see a tag and run this again, so activity already counted follows the new permissions.

🚨 Reactions and best answers cannot be rebuilt — neither records when it happened, so those two accumulate from the day you install rather than backfilling. Posts and likes rebuild exactly.

Works alongside Calendar

ernestdefoe/calendar has a profile heatmap of its own. When Cadence is installed and showing on profiles, Calendar stands its own one down, so nobody ends up with two. Turn Cadence's profile placement off and Calendar's comes back.

How it stays cheap

Activity is rolled up into one row per member, per hour, per kind. A profile view is an indexed range scan over that member's own rows — it never aggregates over posts, which on a forum of any size is a table scan per profile visit.

Hourly rather than daily is what lets the day boundary be decided when the map is read, in the reader's timezone, instead of being baked into the data forever at the server's.

Requirements

  • Flarum 2.0
  • PHP 8.3+

Support

Licence

MIT.