Leaderboard Providers
Register custom leaderboards, ranking algorithms, and unit formatters.
Modules can declare custom leaderboard providers that automatically integrate with Discord's /leaderboard slash command and the web dashboard's Leaderboards view.
Leaderboard providers reside in resources/leaderboards/ and load from every *.js file located directly in that directory.
Base Class Definition
import { Leaderboards } from "#medusa/modules";
export class ActivityLeaderboard extends Leaderboards {
constructor(medusa) {
super(medusa, {
name: "activity_score",
label: "Activity Score",
group: "Community",
format: "number",
emoji: "⭐",
unit: "Points",
singular: "Point",
order: 1
});
}
async list(guild) {
const model = this.medusa.modules.models.get(this.module, "user_scores");
if (!model) return [];
const records = await model.list({ guildId: guild.id });
return records
.sort((a, b) => b.score - a.score)
.slice(0, 100)
.map(record => ({
userId: String(record.userId),
value: record.score,
sub: `Level ${record.level} • Streak: ${record.streak} days`,
stats: [
{ label: "Level", value: record.level },
{ label: "Streak", value: `${record.streak}d` }
]
}));
}
}Constructor Options
The configuration object passed to super(medusa, meta) accepts the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
name | string | Required | Unique leaderboard identifier. |
label | string | name | Display title shown in menus, embeds, and dashboard tables. |
group | string | "General" | Categorization group used to organize multiple leaderboards. |
format | string | "number" | Value formatting style: "number", "currency", or "duration". |
type | string | "card" | Default presentation mode: "card" or "embed". |
emoji | string | "" | Emoji prefix displayed next to values. |
unit | string | "" | Plural unit name appended to values (e.g. "Credits", "Messages"). |
singular | string | unit | Singular unit name used when value is 1 (e.g. "Credit", "Message"). |
order | number | 0 | Sort priority among leaderboards within the same group. |
Supported Formatting Modes
The format property determines how Medusa renders values in Discord embeds and dashboard widgets:
| Format Mode | Sample Output | Formatting Rules |
|---|---|---|
"number" | 1,250 Points | Localized integer formatting with unit suffix. |
"currency" | $ 5,000 Coins | Prepends emoji or currency symbol and appends unit label. |
"duration" | 4h 12m | Converts numeric seconds into human-readable hours and minutes. |
The list(guild) Method
Every provider must implement async list(guild) which receives the active Discord.js Guild instance and returns an array of ranked participant objects.
Return Item Schema
| Property | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | Discord snowflake ID of the member. Used to resolve usernames and avatars. |
value | number | Yes | Raw numeric value used for ranking calculations and sorting. |
display | string | No | Optional pre-formatted text override replacing automatic numeric formatting. |
sub | string | No | Subtitle text displayed below the user's name in list items. |
stats | Array<object> | No | Array of supplementary metric objects containing label and value (string or number) rendered as badges. |
Leaderboard Manager Methods
The root this.medusa.leaderboards service provides methods used across Discord commands and web views:
const allTypes = this.medusa.leaderboards.types();
const rows = await this.medusa.leaderboards.list("activity_score", guild);
const page = this.medusa.leaderboards.paginate(rows, 0, 10);
const position = this.medusa.leaderboards.position(rows, interaction.user.id);Leaderboard Presentation Types
Medusa supports two presentation formats for leaderboards in Discord:
- Card (
"card"): Renders a 1024x750 canvas graphic with rank indicators, compact scores, server branding, and member position. - Embed (
"embed"): Sends a standard Discord embed with medal emojis and mentionable member strings.
The /leaderboard slash command includes an optional format option with choices Card and Embed. When omitted, the command defaults to the server's configured presentation mode (defaultType in Core leaderboard configuration), falling back to the provider's descriptor type or "card".
Server administrators can configure the default presentation type directly from the top bar of the Leaderboard page in the web dashboard or under Configs > Core > Leaderboard.