Leaderboard

How to create a leaderboard message

Updated 7/12/2026

In this tutorial, you'll learn how to make a slash command that displays a leaderboard!

This tutorial assumes you know the basics of inventor.bot- we recommend doing the Ping Command tutorial if you haven't already.

We'll assume you already have a database you want to make a leaderboard for. It could be xp, points, economy, etc., as long as it has a number column (make sure it's the number type!) and a column with a user ID!

leaderboard 1 db setup

Add a local variable called content. You can access the local variable menu from the three-dot menu by the component's name.

leaderboard 2 local vars

Add a Database Lookup (Iterator) block. Give it a limit of 10 (or anything else as long as you don't hit the message character limit!). Sort by the number column, (points, xp, money, etc.)

leaderboard 3 iterator

Iteration Number starts starts at 0, so we need to add 1 to it.

leaderboard 4 math

Add an Update Local Variable block to the iterator and add variables to compose what each row will look like. In this case, rows will look like "1. @user - 12345"

leaderboard 5 append

The content local variable now contains the leaderboard! You can send it however you'd like. In this example, we'll send it as an ephemeral reply to the user.

leaderboard 6 send

Note that, until Customize allowed mentions is added, you should keep the message ephemeral if it contains user mentions!

Make sure the command is published, then test it out!

basic leaderboard result

You now have a basic leaderboard system. Here are some ideas for improvements you could make!

  • You could change it to a public leaderboard that automatically updates
    • Change the trigger to Schedule and swap to a Send or Edit Text Message block.
    • Wait for it to trigger once and send the message, then copy the message ID and put it into the Edit Message ID field.
  • Try using an Embed Message or Advanced Message for a fancier message!
  • Let the user control the Offset input of the Database Lookup (Iterator) block with a slash command option!
    • If you do this, make sure to handle cases where the user's offset returns no rows!
  • Add nicer number formatting with the Format Number block

Adding Pagination

If you want paginated leaderboard messages, you can follow this guide instead:

Since we need to reuse logic in two components, we'll make a custom block. It'll need an offset input.

paginated leaderboard 01

Now lets add a Database Lookup (Iterator) block with a Sort By and the Offset from the trigger. We'll also set the Limit to the number of rows you want per page plus one.

paginated leaderboard 02

We need to add a few local variables- content and hasNext. Both should have a blank default value.

paginated leaderboard 03
We'll add an If Statement that checks if this is the extra row that we don't need.
paginated leaderboard 04

If it is that extra row, we'll use Update Local Variable to set hasNext to true.

Why do we track hasNext?

We want to disable the Next button if there aren't any more rows, so even though we only display 10 rows, we ask the database for 11. If it returns 11, we know that there's at least one more row that we can display on the next page, so we can enable the Next button. If it returns 10 or less, we leave it disabled since there aren't any more rows.

paginated leaderboard 05

If it's not the last row, we need to figure out what place this row is in. We'll add the offset and the current Iteration Number.

paginated leaderboard 06

We also need to add one more, since Iteration Number starts counting at 0 (but we want the leaderboard to start at 1!)

paginated leaderboard 07

Now we'll update the content variable to add the row. Make sure to use the variable from the last Math Operations block!

paginated leaderboard 08

Great, that's the leaderboard content finished! Let's add a Respond to Interaction with Advanced Message block. Update Original Message and Ephemeral should both be true!

paginated leaderboard 09

We'll add a Message Container, then Text inside of it. That'll be our content variable.

paginated leaderboard 10

Now we'll add an Action Row with an If Statement inside. We'll check if the offset doesn't equal 0.

paginated leaderboard 11

In If True, we'll subtract the number of rows per page from the current offset to figure out the offset of the previous page.

paginated leaderboard 12

Now add the button:

paginated leaderboard 13

Now we'll add the disabled button. It still needs an ID, so we'll put in something random. Make sure to mark it as Disabled! If you want the buttons to disappear when they're disabled, you can skip this.

paginated leaderboard 14

Now we'll do something similar for the Next button. Add another If Statement, this time checking if hasNext is true.

paginated leaderboard 15

If True, we'll find the next page's offset by adding 10 to the current offset.

paginated leaderboard 16

Now add the button:

paginated leaderboard 17

Now we'll add the disabled button. It still needs an ID, so we'll put in something random. Make sure to mark it as Disabled! If you want the buttons to disappear when they're disabled, you can skip this.

paginated leaderboard 18

Save and publish that custom block, we're done with it!

Now let's use the block in two components. This first component will be a slash command that triggers the leaderboard. Add Call Custom Block and select the one we just made. Set offset to 0

paginated leaderboard 19

Now we'll make a Button Click flow. The Custom ID will be leaderboard_*

paginated leaderboard 20

And now we'll call the custom block. The offset is the Wildcard Value output from the trigger.

paginated leaderboard 21

That's it! Make sure both of the new flows are published, then give it a go! You should be able to flip through all the pages (and not go out of bounds!)

paginated leaderboard result