Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to build a leaderboard in Bubble

Build a leaderboard in Bubble by creating a Score data type, sorting users by points in a Repeating Group, calculating ranks with the :sorted and :item # operators, and adding time-based resets using scheduled backend workflows. This gives your app a competitive element that drives engagement without writing any code.

What you'll learn

  • How to create a Score data type for tracking user points
  • How to display a sorted leaderboard in a Repeating Group
  • How to calculate and show rank numbers dynamically
  • How to implement weekly or monthly leaderboard resets
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read15-20 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

Build a leaderboard in Bubble by creating a Score data type, sorting users by points in a Repeating Group, calculating ranks with the :sorted and :item # operators, and adding time-based resets using scheduled backend workflows. This gives your app a competitive element that drives engagement without writing any code.

Overview: Building a Leaderboard in Bubble

This tutorial walks you through building a leaderboard system in Bubble. You will create the data structure for tracking scores, display a ranked list of top users in a Repeating Group, add rank numbers, implement top-N filtering, and set up scheduled resets for time-based competitions. This is ideal for gamified apps, quiz platforms, or any app with competitive features.

Prerequisites

  • A Bubble account with an existing app
  • A mechanism in your app that awards points (e.g., completing a quiz or task)
  • Basic understanding of Bubble data types and Repeating Groups
  • Familiarity with Bubble workflows

Step-by-step guide

1

Create the Score data type

Go to the Data tab and click New type. Name it Score and add fields: user (type: User), points (type: number), period (text, e.g., 2026-W13 for week 13 or 2026-03 for March), and last_updated (date). Alternatively, you can add a total_points field directly on the User data type for a simpler approach. The separate Score type is better if you want time-based leaderboards with historical data.

Pro tip: Using a period field lets you run weekly and monthly leaderboards simultaneously by filtering on different period formats.

Expected result: A Score data type exists with user, points, period, and last_updated fields.

2

Build the leaderboard Repeating Group

Go to the Design tab and create a new page called leaderboard. Click the + icon, search for Repeating Group, and drag it onto the page. Set the data type to Score and the data source to: Do a search for Scores where period = Current period value, sorted by points in descending order. Inside each cell, add Text elements to display: the user's name (Current cell's Score's user's name), the score (Current cell's Score's points), and a profile image if available.

Expected result: A Repeating Group displays scores sorted from highest to lowest for the current period.

3

Add rank numbers to each row

In each Repeating Group cell, add a Text element at the left side for the rank number. Set its content to: Current cell's index. This gives you 1, 2, 3, etc. based on the position in the sorted list. For visual emphasis, add conditionals: When Current cell's index is 1, change the background to gold. When Current cell's index is 2, change to silver. When Current cell's index is 3, change to bronze. Limit the Repeating Group to show the top 10 or 25 entries by setting the number of rows.

Pro tip: For tie-breaking, add a secondary sort by last_updated (ascending) so the user who reached the score first ranks higher.

Expected result: Each leaderboard row shows a rank number (1, 2, 3...) with gold, silver, and bronze highlights for the top three.

4

Create the score update workflow

When a user earns points in your app (e.g., completes a quiz), add a workflow step to update their score. Search for an existing Score where user = Current User and period = the current period string. If it exists (count > 0), use Make changes to a thing to add the earned points to the existing record. If it does not exist (count is 0), Create a new Score with user = Current User, points = earned amount, and period = current period. Always set last_updated = Current date/time.

Expected result: User scores are created or incremented in the Score data type whenever they earn points.

5

Set up weekly or monthly resets with backend workflows

Go to the Workflow tab and access Backend workflows from the Pages dropdown. Create a backend workflow called reset_leaderboard. In Settings tab, go to API and enable Workflow API. The reset workflow does not need to delete old scores — since each Score has a period field, simply changing the current period value starts a fresh leaderboard. To calculate the current period, use Current date/time formatted as YYYY-[W]ww for weekly or YYYY-MM for monthly. Old periods remain in the database as historical records.

Pro tip: Schedule the reset workflow to run at midnight on Monday (weekly) or the 1st of the month using the Schedule API workflow action with a calculated date.

Expected result: The leaderboard automatically starts fresh each week or month while preserving historical scores.

6

Add a current user highlight and personal rank

In the Repeating Group, add a conditional on each cell: When Current cell's Score's user is Current User, change the background color to a highlight color (e.g., light blue). Below or above the leaderboard, add a section showing the current user's rank. Display: Search for Scores (period = current, sorted by points descending):find this Score's index where this Score's user is Current User. Show their points and rank even if they are not in the top 10 visible list.

Expected result: The current user's row is highlighted in the leaderboard, and their rank and score are always visible even if they are not in the top entries.

Complete working example

Workflow summary
1LEADERBOARD SYSTEM WORKFLOW SUMMARY
2======================================
3
4DATA TYPES:
5 Score
6 - user (User)
7 - points (number)
8 - period (text) e.g. "2026-W13" or "2026-03"
9 - last_updated (date)
10
11OPTION SET: Leaderboard Period Type
12 - Weekly (format: YYYY-[W]ww)
13 - Monthly (format: YYYY-MM)
14
15PAGE: leaderboard
16 Elements:
17 - Dropdown: Period selector (This week / This month / All time)
18 - Repeating Group (type: Score, rows: 10)
19 Data source: Do a search for Scores
20 period = Current period string
21 Sort: points descending, last_updated ascending
22 Cell contents:
23 - Text: Current cell's index (rank)
24 - Image: Current cell's Score's user's photo
25 - Text: Current cell's Score's user's name
26 - Text: Current cell's Score's points
27 - Group: Current User Stats
28 - Text: Your Rank calculated index
29 - Text: Your Points current user's score
30
31CONDITIONALS:
32 Repeating Group cell:
33 When Current cell's index is 1 background gold
34 When Current cell's index is 2 background silver
35 When Current cell's index is 3 background bronze
36 When Current cell's Score's user is Current User
37 background light blue
38
39WORKFLOW 1: Award points
40 Event: Quiz completed / Task finished
41 Step 1: Search for Score
42 (user = Current User, period = current period)
43 Step 2 (Only when count > 0): Make changes
44 points = existing points + earned points
45 last_updated = Current date/time
46 Step 3 (Only when count is 0): Create new Score
47 user = Current User
48 points = earned points
49 period = current period string
50 last_updated = Current date/time
51
52WORKFLOW 2: Period calculation
53 Weekly: Current date/time formatted as YYYY-[W]ww
54 Monthly: Current date/time formatted as YYYY-MM
55 All time: fixed string "all-time"
56
57BACKEND WORKFLOW: archive_period (optional)
58 Runs on schedule (Monday 00:00 or 1st of month)
59 Step 1: Create LeaderboardArchive record
60 period = previous period
61 winner = top Score's user
62 top_score = top Score's points

Common mistakes when building a leaderboard in Bubble

Why it's a problem: Deleting old scores when resetting the leaderboard

How to avoid: Use a period field on Score records so old periods are preserved. Filter the leaderboard by the current period to show fresh results.

Why it's a problem: Using a search inside each Repeating Group cell to calculate rank

How to avoid: Use Current cell's index which gives the position in the already-sorted Repeating Group list without additional queries.

Why it's a problem: Not handling ties in the leaderboard

How to avoid: Add a secondary sort by last_updated (ascending) so the user who reached the score first ranks higher.

Best practices

  • Use a period field on Score records to support weekly, monthly, and all-time leaderboards simultaneously
  • Sort by points descending with a secondary sort by last_updated ascending for tie-breaking
  • Limit the Repeating Group to 10-25 rows to keep page load fast
  • Highlight the current user's row for quick identification
  • Show the current user's rank separately so they can see their position even if outside the top entries
  • Archive leaderboard winners at the end of each period for historical records
  • Use conditionals to style the top three positions with gold, silver, and bronze colors

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a Bubble.io app with a gamified leaderboard. I need to track user scores, display a ranked top-10 list, reset weekly, and handle ties. How should I structure the data types, Repeating Group, and backend workflows?

Bubble Prompt

Build a leaderboard page for my app. Create a Score data type with user, points, and period fields. Display the top 10 users sorted by score in a Repeating Group with rank numbers and gold/silver/bronze styling for the top three. Add a current user rank display.

Frequently asked questions

Can I show an all-time leaderboard alongside weekly?

Yes. Create a separate Score record with period set to all-time that accumulates points across all periods. Display it in a second Repeating Group or toggle between views with a dropdown.

How do I handle hundreds of users on the leaderboard?

Limit the displayed Repeating Group to the top 10-25. For the current user's rank, do a single search sorted by points and find their index. This keeps the page fast regardless of total user count.

Can I add different leaderboard categories?

Yes. Add a category field (text or Option Set) to the Score data type and filter the Repeating Group by the selected category. This lets you run separate leaderboards for different activities.

Will the leaderboard update in real time?

Yes. Bubble's database searches on page elements auto-update via WebSocket when data changes. New scores will appear on the leaderboard without a page refresh.

How do I reset scores automatically?

You do not need to delete scores. Simply change the period value (e.g., from 2026-W12 to 2026-W13) and the leaderboard search automatically shows only the new period's results.

Can RapidDev help build a gamification system?

Yes. RapidDev specializes in Bubble development and can help you build complete gamification systems including leaderboards, badges, streaks, achievements, and reward tiers.

Should I store scores on the User data type or a separate Score type?

A separate Score type is better for time-based leaderboards because it preserves historical data. If you only need an all-time cumulative score, a field on the User type is simpler.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.