đ ī¸ The Ultimate Guide to Building the đ¤Ē Who's Most Likely To...
Get ready for a deep dive! In this extremely descriptive tutorial, we tear down the exact JavaScript code and frameworks used to create our wildly popular đ¤Ē Who's Most Likely To... tool. Grab a coffee, and let's get coding!
đĨ Why Create Utilities for Streamers?
Building small, interactive utilities like this is not only a fantastic way to learn JavaScript, but they are also highly sought after by content creators! Streamers on Twitch and YouTube are always looking for engaging ways to interact with their chat. By building web-based tools that can be embedded in OBS, you create massive value.
We design our tools to be OBS-compatible so streamers can easily integrate them into their overlays. You can check out our dedicated Streamers Page to see how our tools are optimized for broadcasting! Making things interactive builds communities.
đģ Deep Dive: The JavaScript Engine
The đ¤Ē Who's Most Likely To... looks simple on the outside, but underneath the hood lies a robust, reactive state management system powered by vanilla JavaScript. Let's break down the code to understand exactly how it works.
Section 1: Initial State & Properties
return {
soundEnabled: true,
category: 'all', // 'all', 'funny', 'spicy'
currentPrompt: 'Click Next to start!',
suspectInput: '',
secretName: '',
nameHidden: false,
isCountingDown: false,
countdownTime: 10,
revealed: false,
timerInterval: null,
audioCtx: null,
The Breakdown:
This section initializes the Alpine.js reactive state. Everything defined here becomes automatically available in the HTML. By setting sensible default values, we prevent the UI from loading in a broken or empty state.
Section 2: Application Logic Part 1
prompts_funny_en: [
"...forget where they parked their car in a 2-story garage? đ",
"...become a viral meme by tripping on live TV? đē",
"...accidentally order 50 pizzas instead of 5? đ",
"...get locked out of their own house in their underwear? đО",
"...start laughing hysterically at a completely serious moment? đ¤",
"...spend their entire paycheck on a useless online gadget? đĻ",
"...get into a heated argument with an AI customer service bot? đ¤",
"...eat food off the floor past the 5-second rule? đ",
"...accidentally wave back at a stranger who wasn't waving at them? đ",
"...fall asleep in the middle of a loud party? đ´",
"...forget their own best friend's birthday? đ",
"...get stuck in a children's playground swing set? đ ",
"...talk to animals as if they are human roommates? đ",
"...accidentally drop their phone into a public toilet? đŊ",
"...try to unlock their front door with their car remote? đ"
],
The Breakdown:
- This relies on JavaScript's getter syntax (
get), which acts as a computed property in Alpine.js. Whenever a dependency inside it changes, it automatically recalculates without needing manual event listeners.
Section 3: Application Logic Part 2
prompts_spicy_en: [
"...text their ex at 3 AM saying 'I miss you' after one cocktail? đ¸",
"...have a secret crush on someone in this room? đĢŖ",
"...get caught making out in a public bathroom? đ",
"...flirt their way out of a speeding ticket? đ",
"...accidentally send a spicy photo to the family WhatsApp group? đ¸",
"...have the wilder search history on their phone right now? đ¤Ģ",
"...hook up with a stranger on a wild vacation? đī¸",
"...slide into a celebrity's DMs with an awkward pickup line? đ",
"...lie about their relationship status to get free drinks? đš",
"...have a secret second dating profile active right now? đĨ",
"...kiss someone tonight before the party ends? đ",
"...ghost someone after a great first date because of a weird red flag? đŠ",
"...send a risky text to the wrong person by accident? đą",
"...have the most scandalous secrets in their hidden photo album? đŧī¸",
"...be the first person to start a romantic drama in the group? đ"
],
The Breakdown:
- This relies on JavaScript's getter syntax (
get), which acts as a computed property in Alpine.js. Whenever a dependency inside it changes, it automatically recalculates without needing manual event listeners.
Section 4: Application Logic Part 3
prompts_funny_nl: [
"...zijn auto kwijtraken op een parkeerterrein van 2 verdiepingen? đ",
"...viraal gaan als meme door te struikelen op nationale tv? đē",
"...per ongeluk 50 pizza's bestellen in plaats van 5? đ",
"...zichzelf buitensluiten in hun ondergoed? đО",
"...in een deuk liggen op een bloedserieus moment? đ¤",
"...hun hele salaris uitgeven aan een nutteloze TellSell gadget? đĻ",
"...in een felle ruzie belanden met een AI-klantenservice chat-bot? đ¤",
"...eten van de grond eten ver voorbij de 5-seconden-regel? đ",
"...per ongeluk zwaaien naar een vreemde die niet naar hen zwaaide? đ",
"...in slaap vallen in het midden van een luidruchtig feest? đ´",
"...de verjaardag van hun eigen beste vriend vergeten? đ",
"...klem komen te zitten in een kinderschommel in de speeltuin? đ ",
"...tegen huisdieren praten alsof het menselijke huisgenoten zijn? đ",
"...per ongeluk hun telefoon in de wc laten vallen? đŊ",
"...proberen de voordeur te openen met de afstandsbediening van de auto? đ"
],
The Breakdown:
- This function handles specific business logic for the tool. It mutates the state (variables on `this`), which Alpine.js immediately detects, causing the HTML UI to re-render the changes instantly.
Section 5: Application Logic Part 4
prompts_spicy_nl: [
"...zijn ex appen om 3 uur 's nachts na ÊÊn cocktail? đ¸",
"...geheim verliefd zijn op iemand in deze kamer? đĢŖ",
"...betrapt worden op zoenen in een openbaar toilet? đ",
"...zich uit een boete proberen te flirten bij de politie? đ",
"...per ongeluk een pikante foto sturen naar de familie-groepsapp? đ¸",
"...de meest pikante zoekgeschiedenis op hun telefoon hebben staan? đ¤Ģ",
"...op een wilde vakantie zoenen met een wildvreemde? đī¸",
"...in de DM's van een BN'er of celeb slidend met een foute openingszin? đ",
"...liegen over hun relatiestatus om gratis drankjes te krijgen? đš",
"...een geheim actief Tinder/Dating profiel hebben op dit moment? đĨ",
"...vanavond nog iemand zoenen voordat het feestje afgelopen is? đ",
"...iemand ghosten na een geslaagde date om een bizarre red flag? đŠ",
"...per ongeluk een ondeugend berichtje naar de verkeerde persoon sturen? đą",
"...de meest schandalige geheimzinnige foto's in hun verborgen album hebben? đŧī¸",
"...als eerste romantic drama veroorzaken binnen de vriendengroep? đ"
],
The Breakdown:
- This function handles specific business logic for the tool. It mutates the state (variables on `this`), which Alpine.js immediately detects, causing the HTML UI to re-render the changes instantly.
Section 6: Application Logic Part 5
get currentList() {
let isNl = (document.documentElement && document.documentElement.getAttribute('lang')) === 'nl';
let funny = isNl ? this.prompts_funny_nl : this.prompts_funny_en;
let spicy = isNl ? this.prompts_spicy_nl : this.prompts_spicy_en;
if (this.category === 'funny') return funny;
if (this.category === 'spicy') return spicy;
return [...funny, ...spicy];
},
initGame() {
this.nextPrompt();
},
The Breakdown:
- This relies on JavaScript's getter syntax (
get), which acts as a computed property in Alpine.js. Whenever a dependency inside it changes, it automatically recalculates without needing manual event listeners.
Section 7: Application Logic Part 6
setCategory(cat) {
this.category = cat;
this.nextPrompt();
},
nextPrompt() {
let list = this.currentList;
let random = list[Math.floor(Math.random() * list.length)];
this.currentPrompt = random;
this.resetSecretMode();
},
playTickSound() {
if (!this.soundEnabled) return;
try {
if (!this.audioCtx) {
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
if (this.audioCtx.state === 'suspended') this.audioCtx.resume();
const osc = this.audioCtx.createOscillator();
const gain = this.audioCtx.createGain();
osc.type = 'sine';
osc.frequency.setValueAtTime(600, this.audioCtx.currentTime);
gain.gain.setValueAtTime(0.1, this.audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, this.audioCtx.currentTime + 0.05);
osc.connect(gain);
gain.connect(this.audioCtx.destination);
osc.start();
osc.stop(this.audioCtx.currentTime + 0.05);
} catch (e) {}
},
The Breakdown:
- We utilize
Math.random()here to introduce randomization. This is the core engine of the game's unpredictability, allowing us to shuffle arrays or pick random elements. - This part handles the Web Audio API or HTML5 Audio elements, allowing us to play ticking sounds or victory fanfares to gamify the experience.
Section 8: Application Logic Part 7
playFanfareSound() {
if (!this.soundEnabled) return;
try {
if (!this.audioCtx) return;
const notes = [440, 554.37, 659.25, 880];
notes.forEach((freq, i) => {
setTimeout(() => {
try {
const osc = this.audioCtx.createOscillator();
const gain = this.audioCtx.createGain();
osc.type = 'triangle';
osc.frequency.value = freq;
gain.gain.setValueAtTime(0.2, this.audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, this.audioCtx.currentTime + 0.3);
osc.connect(gain);
gain.connect(this.audioCtx.destination);
osc.start();
osc.stop(this.audioCtx.currentTime + 0.3);
} catch (e) {}
}, i * 90);
});
} catch (e) {}
},
The Breakdown:
- Notice the use of
setTimeout. While JavaScript can calculate results instantly, adding a slight artificial delay creates suspense and makes the application feel like a physical game. - This part handles the Web Audio API or HTML5 Audio elements, allowing us to play ticking sounds or victory fanfares to gamify the experience.
Section 9: Application Logic Part 8
startSecretLock() {
if (!this.suspectInput.trim()) return;
this.secretName = this.suspectInput.trim();
this.nameHidden = true;
this.isCountingDown = true;
this.countdownTime = 10;
this.revealed = false;
if (this.timerInterval) clearInterval(this.timerInterval);
this.timerInterval = setInterval(() => {
if (this.countdownTime > 1) {
this.countdownTime--;
this.playTickSound();
} else {
clearInterval(this.timerInterval);
this.isCountingDown = false;
this.revealed = true;
this.playFanfareSound();
}
}, 1000);
},
The Breakdown:
- We use
setIntervalto create a looping animation or countdown effect.
Section 10: Application Logic Part 9
resetSecretMode() {
if (this.timerInterval) clearInterval(this.timerInterval);
this.suspectInput = '';
this.secretName = '';
this.nameHidden = false;
this.isCountingDown = false;
this.countdownTime = 10;
this.revealed = false;
}
}
}
The Breakdown:
- This function handles specific business logic for the tool. It mutates the state (variables on `this`), which Alpine.js immediately detects, causing the HTML UI to re-render the changes instantly.
đ Frameworks Used & How to Link Them
Building modern web apps doesn't always require massive build tools like Webpack or Vite. For standalone utilities like ours, injecting powerful frameworks directly into the HTML via CDN (Content Delivery Network) is the fastest way to get started.
Alpine.js
Alpine is a rugged, minimal tool for composing behavior directly in your markup. It gives you the reactive and declarative nature of big frameworks like Vue or React at a fraction of the cost.
đ External Link: Official Alpine.js Website
How to link in HTML:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
Place this inside your <head> tag. The defer attribute ensures it loads without blocking your HTML rendering.
Tailwind CSS
Tailwind is a utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup.
đ External Link: Official Tailwind CSS Website
How to link in HTML (via CDN for prototyping):
<script src="https://cdn.tailwindcss.com"></script>
Place this in your <head> tag. While great for development and small utilities, for large production sites, you should install Tailwind via Node to purge unused CSS.
đ Suggested Educational Resources
Want to learn more about the JavaScript concepts and frameworks used in this code? Check out these excellent free resources to level up your coding skills!
MDN Web Docs: JavaScript Guide
The ultimate, comprehensive guide to standard Vanilla JavaScript. Learn about variables, arrays, math functions, and DOM manipulation.
The Modern JavaScript Tutorial
A beautifully written, step-by-step tutorial covering modern ES6+ JavaScript concepts, closures, and promises.
freeCodeCamp: JS Algorithms
Get hands-on practice writing JavaScript logic (like our array shufflers and calculators) in this interactive coding curriculum.
â FAQ about the Code
Is it hard to learn Alpine.js if I only know Vanilla JS?
Not at all! Alpine is designed to map directly to standard JavaScript. If you understand how a basic JS object and function work, you can pick up Alpine.js in literally one afternoon.
Why not use a database?
To ensure absolute privacy and lightning-fast speed, everything runs client-side in the browser. A database would add unnecessary overhead for these utility tools.
Can I copy this code for my own site?
Yes! We encourage you to build your own versions. Inspect the source code, see how the `x-data` object is structured, and try making modifications.