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

How to Build a Roulette Wheel Feature in Bubble

A roulette wheel in Bubble is built using an HTML element with CSS animation for the spinning wheel and JavaScript for random outcome selection. You define prizes in a Data Type or Option Set, trigger the spin from a Bubble workflow, determine the winner server-side in a backend workflow to prevent cheating, and limit spins per user. This tutorial covers the full implementation from visual wheel to prize assignment.

What you'll learn

  • How to create an animated spinning wheel with CSS in an HTML element
  • How to determine random outcomes server-side to prevent cheating
  • How to assign prizes and limit spins per user
  • How to customize wheel segments with colors and labels
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner6 min read25-30 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

A roulette wheel in Bubble is built using an HTML element with CSS animation for the spinning wheel and JavaScript for random outcome selection. You define prizes in a Data Type or Option Set, trigger the spin from a Bubble workflow, determine the winner server-side in a backend workflow to prevent cheating, and limit spins per user. This tutorial covers the full implementation from visual wheel to prize assignment.

Overview: Building a Roulette Wheel in Bubble

This tutorial shows you how to build a spin-to-win wheel for promotions, gamification, or engagement features. You will create the visual wheel, implement fair random selection, assign prizes, and control spin frequency.

Prerequisites

  • A Bubble app with user authentication
  • Basic understanding of HTML elements in Bubble
  • Familiarity with custom states and backend workflows

Step-by-step guide

1

Define prizes in an Option Set

Create an Option Set called 'WheelPrize' with options for each wheel segment: '10% Off', '20% Off', 'Free Shipping', 'Try Again', '$5 Credit', 'Try Again'. Add attributes: 'color' (text — hex code for the segment), 'weight' (number — probability weight, higher = more likely), 'value' (text — the actual prize code or description). Set 'Try Again' segments with higher weight for business-friendly odds.

Expected result: Prizes are defined with colors, probability weights, and values for each wheel segment.

2

Build the spinning wheel with HTML and CSS

Add a large HTML element (400x400px) to your page. Inside, create an SVG or CSS-based wheel divided into segments matching your prizes. Each segment is a colored slice with the prize label. Use CSS transform: rotate() for the spinning animation with an ease-out timing function for a realistic deceleration effect. Add a fixed pointer/arrow element outside the HTML that indicates the winning segment.

Wheel HTML/CSS structure
1<style>
2.wheel-container { position: relative; width: 350px; height: 350px; }
3.wheel { width: 100%; height: 100%; border-radius: 50%; transition: transform 4s cubic-bezier(0.17, 0.67, 0.12, 0.99); }
4.wheel.spinning { transform: rotate(var(--spin-degrees)); }
5.pointer { position: absolute; top: -20px; left: 50%; transform: translateX(-50%); font-size: 30px; }
6</style>
7<div class="wheel-container">
8 <div class="pointer"></div>
9 <canvas id="wheel" width="350" height="350"></canvas>
10</div>

Expected result: A colorful segmented wheel renders on the page with a pointer arrow indicating the winning position.

3

Determine the outcome server-side

Create a backend workflow 'determine_spin_result' with parameter 'user_id'. In the workflow, generate a random number weighted by the prize probabilities. Use 'Calculate random number' and map it to a prize based on cumulative weights. Return the winning prize option and the rotation angle needed to land on that segment. This prevents client-side cheating since the outcome is decided on the server.

Pro tip: Always determine outcomes server-side. If you calculate the winner in the browser, users can inspect the JavaScript and know the result before spinning.

Expected result: A backend workflow determines the fair random outcome and returns the winning prize and rotation angle.

4

Trigger the spin and animate the result

Add a 'Spin' button. The workflow: Step 1 — check if the user has spins remaining (see next step). Step 2 — call the backend workflow to get the result. Step 3 — set a custom state 'spin_degrees' to the returned rotation angle. Step 4 — use a JavaScript action (via Toolbox plugin or HTML) to apply the CSS rotation. Step 5 — after a 4-second delay (matching the CSS transition), show a popup with the prize result. Step 6 — create a SpinRecord with the user, prize, and date.

Expected result: Clicking Spin triggers a smooth wheel animation that lands on the server-determined prize segment.

5

Limit spins per user

Add a 'spins_remaining' field (number) to the User Data Type, or track spins with a SpinRecord Data Type. Before allowing a spin, check: Search SpinRecords where user = Current User and date is today → count. If count is greater than or equal to your daily limit (e.g., 1), disable the Spin button and show 'Come back tomorrow!' message. Decrement spins_remaining or create a SpinRecord after each spin.

Expected result: Users are limited to a set number of spins per day, with the button disabled when the limit is reached.

6

Display and redeem the prize

After the spin animation completes, show a congratulatory popup with the prize name and a unique redemption code (generate using 'Calculate random string'). Store the code in a 'UserPrize' Data Type with user, prize, code, redeemed (yes/no), and expiry date. On the checkout or redemption page, validate the code against UserPrize records. Show a 'My Prizes' section in the user's profile listing unredeemed prizes.

Expected result: Winners receive unique redemption codes stored in the database, viewable in their profile and redeemable at checkout.

Complete working example

Workflow summary
1ROULETTE WHEEL WORKFLOW SUMMARY
2====================================
3
4OPTION SET: WheelPrize
5 '10% Off' (weight: 20, color: #3B82F6)
6 '20% Off' (weight: 10, color: #8B5CF6)
7 'Free Shipping' (weight: 15, color: #10B981)
8 'Try Again' (weight: 40, color: #6B7280)
9 '$5 Credit' (weight: 15, color: #F59E0B)
10
11DATA TYPES:
12 SpinRecord: user, prize, date, rotation
13 UserPrize: user, prize, code, redeemed, expiry
14
15SPIN WORKFLOW:
16 Step 1: Check daily spin limit
17 Step 2: Backend determine_spin_result
18 Weighted random selection from prizes
19 Returns: prize option + rotation degrees
20 Step 3: Animate wheel to rotation degrees
21 Step 4: Wait 4 seconds (animation duration)
22 Step 5: Show prize popup
23 Step 6: Create SpinRecord + UserPrize
24 Step 7: Generate redemption code
25
26SPIN LIMIT:
27 Search SpinRecords (user + today) count
28 If count >= 1: disable button, show message
29
30REDEMPTION:
31 Checkout: validate code against UserPrize
32 Mark redeemed = yes after use

Common mistakes when building a Roulette Wheel Feature in Bubble

Why it's a problem: Calculating the winning outcome in client-side JavaScript

How to avoid: Always determine the outcome in a server-side backend workflow and send only the rotation angle to the client

Why it's a problem: Making all prizes equally likely regardless of value

How to avoid: Use probability weights — assign higher weights to low-value prizes ('Try Again') and lower weights to high-value ones

Why it's a problem: Not tracking spins per user, allowing unlimited plays

How to avoid: Implement per-user daily spin limits tracked via SpinRecord data type

Best practices

  • Determine outcomes server-side to prevent cheating
  • Use weighted probability to control prize distribution
  • Limit spins per user per day to maintain engagement over time
  • Generate unique redemption codes for each prize won
  • Set expiry dates on prizes to encourage prompt redemption
  • Track all spins for analytics on engagement and prize distribution
  • Make 'Try Again' the most common outcome (40-50% probability) for sustainability

Still stuck?

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

ChatGPT Prompt

I want to build a spin-to-win promotional wheel in Bubble.io with 6 prize segments, weighted probabilities, animated spinning, and one spin per user per day. How do I build this fairly and prevent cheating?

Bubble Prompt

Build a roulette wheel feature. Create a WheelPrize option set with 6 prizes and probability weights. Add an animated wheel in an HTML element. Determine outcomes server-side. Limit users to one spin per day. Generate redemption codes for prizes.

Frequently asked questions

Is the wheel outcome truly random?

Yes, when using Bubble's random number generator in a backend workflow with probability weights. The outcome is determined server-side before the animation starts — the animation is purely visual.

Can I change the prizes without rebuilding the wheel?

Yes. Since prizes are in an Option Set, you can change labels, colors, and weights from the Data tab. The wheel segments should be dynamically generated from the Option Set for full flexibility.

How do I handle mobile users?

The CSS-animated wheel works on mobile browsers. Size the wheel to fit mobile screens (280-320px) and ensure the Spin button is large enough for touch interaction.

Can I add sound effects to the spin?

Yes. Use an HTML5 audio element with a spinning sound that plays when the Spin button is clicked and stops after the animation completes.

Can RapidDev build a custom promotional game for my Bubble app?

Yes. RapidDev can build custom promotional games including spin wheels, scratch cards, slot machines, and other engagement mechanics in Bubble.

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.