Skip to main content
Leaderboards turn accumulated XP (or challenge completions, streaks, custom events) into competitive rankings. Members see where they stand; admins configure what gets ranked and how.

Creating a leaderboard

Top nav -> + New -> Leaderboard.

Basic info

Name, description, icon. Rendering was stabilised in #781 so multi-column layouts don’t flicker.

Ranking criteria

Pick the metric that ranks members:
  • XP earned (total or in a window)
  • Challenges completed
  • Streak length
  • Custom event count

Window

Rolling window for the ranking:
  • All time — cumulative forever.
  • Monthly / weekly / daily — resets automatically.
  • Custom range — fixed start/end.

Distribution (rewards)

Attach rewards to top N positions. Distribution configs let you tier — different rewards for #1, #2-5, #6-10 etc. Avoids reward-save duplication bug (#1070).Bonus XP defaults to 0 (#688) — set it explicitly if you want it to fire.

Visibility

  • Language — per-locale titles/descriptions (#1062).
  • Disabled state — disabled leaderboards still show in admin lists (#1650) so you can re-enable without hunting.

Excluding members

Open a leaderboard’s rankings and choose Excluded users. You can add a member with the picker or upload a CSV with user_id, start_date, and end_date columns. Blank dates leave that side of the window unbounded. Dates use your organisation’s timezone, and end_date includes that whole day. Before confirming, check the preview for usable rows, duplicate entries and errors. Exact repeated windows within the file or already stored on the leaderboard are skipped. The import checks available capacity before sending any writes. If the file needs more space than remains, nothing is written in that attempt. Splitting the file does not increase the leaderboard’s stored-entry limit. Uploads save in batches. The result reports entries saved and skipped, which can differ from the number of members. If a later batch fails, earlier batches stay saved. The preview keeps rows without a confirmed result so you can retry them safely. An unconfirmed request may already have saved its rows; retrying those exact windows skips them rather than creating duplicates. Another admin’s changes can use capacity after your initial check, so a later batch can still be refused. If all rows are confirmed but refreshing the list fails, reload to refresh the list. If rows remain unconfirmed, keep the dialog open and retry from its preview. Import feedback and retry rows remain visible when the list refresh fails.

Language support

Leaderboards fully support multi-language (#1062). Edit the title, description, and reward copy per locale. Members see the leaderboard in their chosen language.

Dynamic count

The leaderboard row count is not hardcoded (#1376) — configure how many positions display (top 10, 25, 50, 100). Members outside the displayed range still accumulate rank, they just don’t render in the list.

Name input focus

The name input field retains focus properly (#2230) — you can type the full name without re-clicking after each keystroke (this used to be a pain point on longer names).

Disabled leaderboards

Turn off a leaderboard without deleting it — the disabled state keeps the config safe but hides it from members. Disabled boards still show in the admin list (#1650) so you can flip them back on.

Patterns

Metric: total XP, window: monthly. Rewards: tiered (big for #1, medium for #2-5, small for #6-10). Resets on the 1st of each month.
Metric: longest streak, window: all-time. Rewards: one big badge for #1, smaller badges for #2-10.
Metric: challenges completed, window: weekly. Rewards: reward entries (giveaway tickets) for top 20.
Separate leaderboards per loyalty tier so Bronze members compete with Bronze, Gold with Gold — healthier competition than a single mixed board.

Leaderboard studio sidebar was previously broken (#2239). If you’re on a very old admin build and see rendering issues, force-refresh or clear the Turbopack cache.

API

  • GET /admin/leaderboards — list
  • POST /admin/leaderboards — create
  • PATCH /admin/leaderboards/:id — update
  • GET /admin/leaderboards/:id/distribution-events — distribution configs
See the Admin API reference.