Credence: Mapping the Reddit Mind

We’ve all confidently answered a question, placed a bet, or argued a point, only to discover we were completely wrong. That sting of realization isn't just about lacking information—it's about misjudging the limits of our own knowledge.

My journey began with a simple, math-centric prototype called mathGauge—a 3-round game designed to test players' mental estimation speed and numerical accuracy. But as I built and tested it, I realized I was sitting on a far deeper psychological hook. I decided to evolve the project, shifting the scope from a simple math quiz into a game about metacognition—the ability to accurately gauge the boundaries of your own mind.

Inspiration

The internet is flooded with trivia games, but they all share a basic, binary assumption: you get it right, or you get it wrong. In my early prototype, mathGauge, I tried to break this mold by scoring players based on how close their numerical estimates were to the actual answers.

However, during playtests, I noticed something fascinating: I was highly engaged when debating how sure I was of my own guesses. It wasn’t just about the math; it was about self-belief. I realized the true game wasn't numerical calculation—it was metacognition.

Inspired by forecasting tournaments and decision-making science, I wanted to build a game that acts as a psychological mirror. I asked a simple question: Can we build a game where your score is determined not by how close your guess is, but by how well you calibrate your confidence?

From this, Credence was born.

What it does

Credence is a daily quantitative intuition game built directly for the Reddit feed. Instead of a standard trivia quiz, it structures a daily 5-round experience:

  • Rounds 1–4 (Estimation): Players estimate a numerical trivia answer (e.g., "What is the speed of light in million meters per second?") and then wager their confidence from 1 to 5 stars.
  • Round 5 (Myth or Fact): A final binary true/false statement that tests how players handle absolute claims under pressure.

The core gameplay hook is psychological: If you are highly confident and correct, you score massive points. If you are highly confident but wrong, your score is devastated. If you admit your uncertainty, you mitigate your losses.

At the end of the game, players see their daily score and a rolling profile tracking their Calibration Score (how well confidence aligns with reality) and Overconfidence Index (OCI) (whether they trend towards over- or under-confidence) over a sliding window of the last 6 days of play.

How we built it

I chose every technology in Credence to solve a specific product experience goal: keeping load times negligible inside a scrolling Reddit feed while still delivering a high-fidelity visual payoff.

During the early development of mathGauge, I faced a major architectural debate: should I build the frontend using Vanilla JS for absolute maximum performance and instant load times, or React for structured state management? I initially leaned toward Vanilla JS, believing that raw performance was paramount in a fast-paced Reddit feed.

However, as the game evolved from a 3-round math quiz into a 5-round multi-category metacognitive experience, the complexity of state synchronization (tracking wagers, round-by-round score validation, state lockouts, and dynamic Phaser scene orchestration) exploded. Managing this state in Vanilla JS quickly became error-prone and hard to scale. When I pivoted to Credence, I settled on React. The structured state lifecycle, component reusability, and clean state hooks allowed me to manage the intricate game states safely, while offloading the heavy rendering to Phaser at the very end to keep feed loads fast.

To balance these two conflicting goals, I split the application into two distinct phases:

  1. The Gameplay Loop (React): The first 5 rounds are built entirely in React. This keeps the initial footprint of the app incredibly lightweight. When a Redditor encounters the game in their feed, it loads instantly, preventing them from scrolling away before they get hooked.
  2. The Grand Reveal (Phaser): Once the player submits their final round, the interface dynamically mounts a transparent Phaser (v3) canvas. I concentrated my visual polish here—using fluid animations for score tallying and an active community bell curve—to give players a satisfying visual reward at the exact moment they finish.

The Stack

  • Backend: Node.js v22 serverless environment hosted inside Devvit, structured using a Hono router and type-safe tRPC communication.
  • Database: Devvit's native Redis instance to manage leaderboard sorted sets (zAdd/zRange), player daily states, and temporary verification keys to block score tampering.
  • Frontend UI: React managed the gameplay loop, text wagers, and round feedback.
  • Graphics Engine: Phaser (v3) loaded dynamically at the end to render the final reveal animations.

The Mathematics of Calibration

We developed a robust scoring engine to mathematically calculate a player's calibration.

Per-Round Score

The confidence multiplier is defined as: $$ M_c = \frac{\text{stars}}{5} $$

If a player's accuracy \(A\) is high (\(A \ge 70\%\)): $$ \text{Score} = A \times M_c $$

If their accuracy is low (\(A < 70\%\)): $$ \text{Score} = -(100 - A) \times M_c $$

Overconfidence Index (OCI)

To measure bias, we calculate the Overconfidence Index over a sliding window of the last 30 rounds (6 days of gameplay). Let \(C_i\) be the confidence (normalized to \([0, 1]\)) and \(A_i\) be the actual accuracy (normalized to \([0, 1]\)): $$ \text{OCI} = \frac{1}{N} \sum_{i=1}^{N} (C_i - A_i) $$

  • A positive OCI means the player is systematically overconfident.
  • A negative OCI means the player is underconfident.

Calibration Score

To measure how well their confidence aligns with reality (regardless of bias), we take the average absolute error: $$ \text{Calibration} = 100 \times \left(1 - \frac{1}{N} \sum_{i=1}^{N} |C_i - A_i|\right) $$

Challenges we ran into

Challenge 1: Preventing Score Spoofing

  • Why it matters: Since Reddit games execute inside the user's browser, trusting client-submitted scores would allow anyone to top the leaderboard by simply editing values in the developer console, ruining the competitive integrity of the community.
  • The Solution: I built a round-by-round verification pipeline. The client never submits a final total score. Instead, guesses are verified and scored server-side in real-time, caching them securely in Redis under user:round-results:${today}:${userId}. At the end, the server tallies only these verified records from Redis.

Challenge 2: The Double-Click State Race Condition

  • Why it matters: During playtests, clicking the final "Show Reveal Sequence" button rapidly triggered the server submission twice in rapid succession. The first request successfully finalized the session and cleaned up Redis keys. The second request arrived milliseconds later, found no verification keys, threw an error, and crashed the UI to a zero-score screen.
  • The Solution: I implemented a strict lock system. I introduced a savingFinalScore state guard in React. I disabled the UI button immediately upon the first tap (disabled={savingFinalScore}) and added an early return on the submission function to completely eliminate duplicate API executions.

Challenge 3: Merging Phaser & React in a Sandbox

  • Why it matters: Because Devvit runs inside a restricted sandboxed iframe, managing a full Phaser canvas inside React's layout engine was prone to rendering offsets, page scroll issues, and layout clipping.
  • The Solution: I configured the Phaser container with transparent: true to let the game blend seamlessly with the underlying React CSS grid, and built an event listener bridge (phaserManager.ts) to let React and Phaser coordinate transition timings smoothly.

Accomplishments that we're proud of

  • A Bulletproof Serverless Security Pipeline: Successfully implementing an airtight, state-verified, round-by-round submission system using Devvit Redis. Even with full access to the client console, there is no way for a player to inject a spoofed score.
  • Frictionless React & Phaser Symbiosis: Getting React's DOM state and Phaser's WebGL canvas to load, overlay, and hand off events to one another seamlessly inside a sandboxed iframe.
  • A Meaningful Metric Hook: Translating abstract calibration math into simple, engaging, and readable player metrics (Calibration Score and OCI) that players can immediately understand.

What we learned

Developing and playtesting Credence myself forced me to rethink the mechanics of digital engagement. Since the game was built as a solo development effort, my own play sessions became the primary feedback loop. This led to several key design hypotheses and insights about player psychology:

  • Confidence is More Interesting than Correctness: During my own test runs, I noticed that getting an estimate completely wrong didn't feel frustrating if I had correctly wagered 1 star. It felt like a triumph of self-awareness. This convinced me that player engagement could be driven by the satisfaction of precise risk management rather than raw factual recall.
  • Self-Discovery Trumps Traditional Leaderboards: I realized that watching my own Calibration Score and Overconfidence Index shift over a rolling 6-day profile was far more fascinating than simply grinding for a static leaderboard rank. It turns the game from a trivia test into a tool for active self-reflection.
  • Designing for the Reddit Comments: The share card was deliberately designed to display the OCI because I predict this will spark debates in the comments. Discussing why we are overconfident on history but underconfident on science is a natural conversation starter for a community like Reddit.
  • Pacing and Visual Tension: Consolidating all Phaser animations at the very end rather than per-round created a deliberate build-up of tension during gameplay. The delayed payoff made completing the daily game feel like a genuine event.

What's next for Credence

  • Sandbox / Practice Mode: Currently, once players finish their daily 5 rounds, they are locked out for 24 hours. I plan to add a practice mode where users can play infinite unranked sessions to test their calibration on custom categories.
  • Dynamic Question Bank Expansion: Implementing an automated scheduler to regularly rotate questions and categories, expanding the database to hundreds of verified historical, geographical, and scientific intuition questions.
  • Subreddit-Specific Leaderboards: Allowing different subreddits to host custom daily challenges, creating community-specific calibration curves (e.g., r/science having a science-focused curve).
  • Calibration Duels: A real-time or turn-based multiplayer mode where two players face the same questions and try to out-calibrate each other.

Credence is more than a game—it's a mirror for your mind.

Built With

Share this project:

Updates

Submission history