By the creator of DoubleClickTest.com — turning a simple mouse-click toy into a mystical decision engine that never leaves your browser.
In 2025 I got tired of two things:
- Decision fatigue on tiny everyday choices (“Should I order sushi or pizza?”).
- Every “AI oracle” on the internet quietly sending my questions to some server in the cloud.
So I did what any frontend developer with too much coffee would do — I built my own yes or no oracle that runs 100 % in the browser, stores nothing on any server, and still feels magically accurate.
Today it lives at doubleclicktest.com and already answered thousands of secret questions. Here’s exactly how I built it with nothing but vanilla HTML, CSS and JavaScript.
Why This Project Even Exists
My main site — doubleclicktest.com — started as a simple tool to measure double-click speed. People loved it. Then they started asking: “Can you make something fun with the same click tech?”
I thought: “What if the randomness doesn’t come from Math.random() alone, but from the same click-timing entropy I already measure?” That tiny idea became the Yes-No Oracle.
The goal was clear from day one:
- Zero network requests
- Zero cookies (only localStorage for your personal history)
- Zero tracking
- Instant answer with a bit of mystical flair
The Tech Stack (Spoiler: It’s Tiny)
- HTML5 + CSS3 (Tailwind for speed)
- Pure vanilla JavaScript (no frameworks, no build step)
- localStorage for history
- A simple seeded random generator so the oracle feels “consistent yet unpredictable”
That’s literally it. The whole thing is one single HTML file + ~120 lines of JS.
Step 1: The Interface (Clean & Mystical)
I wanted it to feel like an ancient oracle, not another boring web app.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Yes or No Oracle — 100% Private</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-zinc-950 text-white min-h-screen flex items-center justify-center font-mono">
<div class="max-w-md w-full p-8 rounded-3xl border border-amber-500/30 bg-zinc-900">
<h1 class="text-4xl font-bold text-center mb-2 text-amber-400">THE ORACLE</h1>
<p class="text-center text-zinc-400 mb-8">Ask anything. It already knows.</p>
<input id="question"
type="text"
placeholder="Will I get that promotion?"
class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-6 py-4 text-lg focus:outline-none focus:border-amber-400">
<button id="askBtn"
class="mt-6 w-full bg-gradient-to-r from-amber-500 to-orange-500 hover:from-amber-600 hover:to-orange-600 py-5 rounded-2xl text-xl font-bold transition-all active:scale-95">
ASK THE ORACLE (double-click for extra power)
</button>
<div id="answer" class="mt-8 text-7xl font-bold text-center min-h-[120px] flex items-center justify-center"></div>
<div id="history" class="mt-12 text-sm"></div>
</div>
</body>
</html>
Simple, dark, and the button hints at the double-click heritage of the site.
Step 2: The Magic — Seeded Randomness
Pure Math.random() is fine, but it feels too cold. I wanted the answer to feel connected to you.
So I combined two sources of entropy:
- The question text itself (hash)
- The exact timing of your click (performance.now())
Here’s the core function:
function hashString(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash);
}
function getSeededRandom(seed) {
let x = Math.sin(seed) * 10000;
return x - Math.floor(x);
}
document.getElementById('askBtn').addEventListener('click', (e) => {
const question = document.getElementById('question').value.trim();
if (!question) return;
// Extra entropy from click timing + question
const clickTime = performance.now();
const questionHash = hashString(question.toLowerCase());
const finalSeed = questionHash + clickTime;
const randomValue = getSeededRandom(finalSeed);
const answer = randomValue > 0.5 ? 'YES' : 'NO';
// Visual flair
const answerEl = document.getElementById('answer');
answerEl.style.transition = 'none';
answerEl.style.opacity = '0';
setTimeout(() => {
answerEl.textContent = answer;
answerEl.style.color = answer === 'YES' ? '#22c55e' : '#ef4444';
answerEl.style.transition = 'all 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)';
answerEl.style.opacity = '1';
answerEl.style.transform = answer === 'YES' ? 'scale(1.15)' : 'scale(0.9)';
}, 50);
// Save to history
saveToHistory(question, answer);
});
This little trick makes the same question asked twice in a row usually give the same answer — until you change the timing or wording. It feels alive.
Step 3: Private History with localStorage
People love seeing their past questions. Everything stays on their device.
function saveToHistory(question, answer) {
let history = JSON.parse(localStorage.getItem('oracleHistory') || '[]');
history.unshift({
q: question,
a: answer,
time: new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'})
});
// Keep only last 15 entries
if (history.length > 15) history.pop();
localStorage.setItem('oracleHistory', JSON.stringify(history));
renderHistory();
}
function renderHistory() {
const container = document.getElementById('history');
let history = JSON.parse(localStorage.getItem('oracleHistory') || '[]');
container.innerHTML = `
<p class="text-amber-400 mb-3">Your recent consultations:</p>
<div class="space-y-3 max-h-60 overflow-auto">
${history.map(item => `
<div class="flex justify-between text-xs border-l-2 border-zinc-700 pl-3">
<span class="text-zinc-400">${item.q.substring(0, 38)}${item.q.length > 38 ? '...' : ''}</span>
<span class="${item.a === 'YES' ? 'text-green-400' : 'text-red-400'} font-bold">${item.a}</span>
</div>
`).join('')}
</div>
`;
}
Call renderHistory() on load and after every new answer. That’s it — fully private history.
Step 4: Polish & Deploy
I added a few extra touches:
- Tailwind for responsive design
- Subtle particle dots in the background (CSS only)
- “Double-click the button for extra mystical power” — it actually reads the time between clicks and adds it to the seed
- A tiny footer that says: “This oracle never leaves your browser. No data is sent anywhere. Ever.”
The entire project is one static HTML file hosted on the same domain as the original double-click tester. No build tools, no npm, no backend. Just open, edit, upload.
Here’s the live version I deployed: yes or no oracle — try asking it your most secret question.
(Go ahead. I’ll wait.)
What I Learned
- People actually use it for serious decisions. I’ve seen questions about job offers, relationships, and even crypto trades.
- localStorage feels magical to non-technical users — “Wait, it remembers everything but nothing leaves my laptop?”
- Seeded randomness with click entropy is way more fun than pure Math.random().
- HackerNoon readers love this kind of story — pure vanilla JS that solves a real (and fun) problem.
Want the Full Source?
Just right-click → “View Page Source” on the live oracle. Everything is there. No hidden files, no minification. Feel free to fork it, improve it, or turn it into your own side project.
If you build something cool with the same technique (maybe a tarot card reader or magic 8-ball), tag me — I’d love to see it.
