How EduGenius's Compete Mode Turns Practice Into a Timed Challenge
Compete is EduGenius's student-only feature that turns quiz practice into a timed, cohort-scoped leaderboard: ten AI-generated multiple-choice questions, a per-question time limit set by difficulty, and a shared ranking everyone in the cohort can see. What makes it worth a closer look isn't the leaderboard itself — it's what's running underneath it. The scoring, timer, and answer key are all verified server-side, in ways most "quiz leaderboard" features don't bother with.
Quick Answer: Compete (
app/compete/page.js,hooks/useCompete.js,lib/compete-server.js) is a student-only timed leaderboard: a cohort takes the same 10-question AI-generated MCQ challenge at Easy, Medium, Hard, or Mixed difficulty (45, 60, or 75 seconds per question), and rankings are server-computed by best score. The real engineering story is integrity: the answer key is embedded server-side at attempt start and never trusted from the client, the attempt token is HMAC-SHA256 signed and checked with a constant-time comparison, and elapsed time comes from the server clock, not the browser. Suspiciously fast completions are flagged, though not auto-rejected. It costs 1 credit per attempt for paid or credit-funded users (unlimited-credit plans play free), and non-subscribers need a 250-credit balance to unlock it at all.
This article covers:
- What a Compete challenge looks like, mechanically, from cohort to leaderboard
- The three server-side mechanics that keep scores and timing trustworthy
- What Compete's anti-cheat system does and doesn't do today — stated plainly
- The gamification layer that's inert or demo-only, and why that's worth knowing
- What it costs to play, and where Compete sits relative to the rest of EduGenius
What a Compete Challenge Actually Is
Compete is a timed, cohort-scoped multiple-choice challenge — not a general quiz generator and not a teacher tool. A student joins a cohort, starts a 10-question challenge at a difficulty they pick, and lands on a shared leaderboard the moment they submit.
Cohorts Are the Unit Everything Else Sits On
A cohort is a group tied to something like a grade level and subject — a "Grade 8 Math League" or a "Grade 6 Science Challenge." If a student's profile doesn't match any existing cohort, EduGenius auto-seeds starter cohorts scoped to that student's class standard and curriculum, so nobody lands on an empty screen with nothing to join.
Every member of a cohort competes on the same challenge and sees the same leaderboard — the ranking only means something because everyone in the room took the same test.
Ten Questions, Difficulty-Scaled Time
Each challenge is a fixed 10-question AI-generated multiple-choice set. Difficulty controls both question complexity and the clock:
| Difficulty | Time per question | What the question set emphasizes |
|---|---|---|
| Easy | 45 seconds | Foundational concepts, direct recall |
| Medium | 60 seconds | Application-based and analytical questions |
| Hard | 75 seconds | Multi-step reasoning and higher-order thinking |
| Mixed | Uses the Medium window | Roughly 30% easy, 40% medium, 30% hard, blended |
The total time budget scales with difficulty — a Hard challenge gives a student meaningfully more room per question than an Easy one, rather than penalizing harder questions with the same short clock.
Questions Are Cached, Not Static and Not Regenerated Per Student
Questions come from Gemini and are cached per cohort, challenge, and difficulty for seven days rather than generated fresh for every single attempt — a middle ground between a fixed, reused-forever bank and a unique test per student. Everyone attempting the same challenge and difficulty within that window sees the same question set, which is exactly why the ranking is meaningful in the first place.
The Leaderboard Ranks by Best Score, With a Real Tiebreak Rule
The leaderboard sorts by each student's best score first. When two students land on the exact same best score, the code breaks the tie by attempt timestamp, ordered earliest first — so between two students tied on score, the one who reached it earlier keeps the higher rank rather than a later challenger automatically jumping ahead by matching it.
The Real Problem: Can a Leaderboard Actually Trust the Client?
Any online leaderboard has one structural problem before it has a single feature: the device answering the questions is not a trustworthy witness to its own performance. A browser tab can be paused, its clock can be spoofed, and its network requests can be edited — none of that requires exotic tools, just patience.
Why "It's Just a Quiz Leaderboard" Undersells the Risk
It's tempting to treat a practice leaderboard as low-stakes enough that shortcuts don't matter. But the moment a ranking is visible to a peer group, it becomes a status signal — and status signals attract exactly the kind of gaming a private, unranked quiz never would.
Academic-integrity researchers have made a related point about assessment generally, not just online tools. James Lang's book Cheating Lessons argues that dishonesty tracks environmental opportunity as much as character — a system that structurally removes the chance to cheat does more real work than a policy that just asks students not to. Donald McCabe, a founder of the International Center for Academic Integrity, made a related case across decades of research: assessment design shapes honest behavior more reliably than an honor code alone.
The Three Places a Client-Trusted Quiz Usually Breaks
A naive online quiz typically makes three mistakes, any one of which makes a leaderboard meaningless:
- Sends the answer key to the browser so the quiz can grade itself locally, leaving correct answers visible in network traffic.
- Trusts a client-reported score with no independent server-side check against what was actually asked.
- Trusts a client-reported duration, which a browser can simply misreport.
Compete's server-side design closes all three at once, rather than patching one and leaving the others open.
How Compete Actually Verifies Integrity — Three Real Mechanics
Compete's anti-cheat approach isn't a single feature; it's three separate server-side checks that each close one of the gaps above. Together, this is an uncommon level of engineering rigor for what's ultimately a practice-quiz leaderboard.
1. The Answer Key Is Embedded Server-Side, Never Sent to the Browser
When a student starts an attempt, startAttempt() in lib/compete-server.js writes the full question set and the correct-answer key into a private attempt document under that student's own account on the server. The code comment on that write explains why: scoring should always run against the exact question set a student actually received, even if the shared challenge gets regenerated in the background before they submit.
The questions sent back to the browser are stripped down first — question text and answer options only. The correct answer for each question never reaches the client, so there's no answer key sitting in a network response for a student to inspect mid-attempt.
2. The Attempt Token Is HMAC-Signed and Checked in Constant Time
Starting an attempt returns a random attempt token plus a cryptographic signature over it, generated with HMAC-SHA256 — a standard method for proving data hasn't been altered since a trusted party, EduGenius's own server, produced it. When the student submits, the server recomputes the expected signature and compares it against the one that came back.
That comparison uses crypto.timingSafeEqual(), a constant-time comparison, rather than a normal string equality check. The distinction is invisible to a student but matters for security design: an ordinary comparison can return fractionally faster the moment it hits the first wrong character — a narrow side channel an attacker could theoretically use to guess a valid signature byte by byte. A constant-time comparison always takes the same time regardless of where a mismatch occurs, closing that channel outright.
3. Elapsed Time Comes From the Server Clock, Not the Browser
The server never asks the browser how long an attempt took. It calculates duration from timestamps it controls itself — when the attempt started and when the submission arrived — with a small five-second grace window added to absorb ordinary network latency rather than punish a student for a slow connection.
That single design choice removes an entire category of exploit: a client-reported duration can be edited before it's sent, but a server-computed one can't be, because the browser never gets asked for it in the first place.
The Full Verification Chain, End to End
| Step | What the server checks | What it prevents |
|---|---|---|
| Attempt start | Answer key + full question set written server-side only | Answers never appear in client-visible traffic |
| Submission | HMAC signature recomputed and compared via timingSafeEqual | A forged or tampered attempt token being accepted |
| Submission | Attempt status must still be "pending" | Resubmitting the same attempt to try again |
| Submission | Server-computed elapsed time vs. time limit + 5s grace | A client claiming a faster time than actually elapsed |
| Scoring | Correct count computed against the embedded key, not a client-sent score | A forged or self-reported score reaching the leaderboard |
What Gets Flagged — and What Doesn't, Yet
Here's the honest part of the story: Compete's integrity system detects unusually fast completions, but today it only flags them — it doesn't reject or penalize a submission automatically. That distinction is worth stating plainly rather than letting "rigorous anti-cheat engineering" imply more than what's shipped.
How the Speed Check Works
When a submission comes in, the server checks the computed duration against a simple floor: if the whole attempt finished in under roughly half a second per question on average, it gets tagged with an integrityFlags entry — specifically, suspiciously_fast. That flag is written into the attempt record and nowhere else in the codebase; nothing currently reads it back to block a score, cap a rank, or notify anyone.
In practical terms, an implausibly fast attempt can still land on the leaderboard today. What the system guarantees is that the score itself can't be forged by editing client-side answers or a reported time — the flag exists as a data layer for future moderation, not an active gate.
Why That Nuance Is Worth Stating Directly
It would be easy to describe Compete as actively catching cheaters. That's not quite accurate — the precise claim is narrower, and arguably more interesting:
- The scoring and timing pipeline isn't gameable through the client.
- A signal for reviewing outlier attempts already exists in the data — but automatic rejection isn't wired up yet.
That's a reasonable phase for a feature to be in. Plenty of systems ship the detection layer before the enforcement layer, so enforcement can be tuned against real flagged data instead of guessed at in advance.
The Gamification Layer: Real Leaderboard, Thin Rewards
Underneath the leaderboard, Compete's data model includes streak and XP fields — but they're never actually incremented anywhere in the code. They exist as columns in the leaderboard document, initialized to zero when a student's first entry is created, and then never touched again by any function in the codebase.
Streaks and XP Are Present in the Schema, Not in the Product
This is a subtler kind of honesty than "the feature doesn't exist" — the fields are genuinely there, ready to be wired up, and a student's leaderboard document literally contains a streakDays and an xp value. But no code path anywhere increments either one. They're inert scaffolding for a gamification layer that hasn't been built out yet, not a working system operating quietly in the background.
The Achievements Panel Is Demo-Mode Only, by Design
Compete also ships an Achievements panel in its UI — but the component's own code comment states directly that there's no real achievement or badge source yet, so the panel only renders sample badge data in demo mode. That's a deliberate choice, not an oversight: it means no student using a real account ever sees a fabricated badge they didn't actually earn, because the panel simply doesn't populate outside the demo experience.
Why This Contrast Is the Actually Interesting Story
Gamification researcher Karl Kapp defines gamification as using game-based mechanics and aesthetics to engage people and motivate action — leaderboards being one of the most direct mechanics for that. Compete implements exactly that piece: real-time, verified competitive ranking. What it hasn't built out yet is the reward layer that self-determination theory (Deci and Ryan's long-standing framework for motivation) would predict matters just as much — a sense of progress over time, not just where you rank today.
Put plainly: Compete is a rigorously verified competitive leaderboard wrapped around a thin, partly-inert gamification layer. The part that's hard to fake — score and timing — is fully built. The part that's easy to fake — badges and streaks — isn't implemented or is explicitly demo-only. That's arguably the right order to build these two pieces in.
What It Costs to Play
Compete isn't free for every account type: paid or credit-funded attempts cost 1 credit each, unlimited-credit plans play at no per-attempt cost, and non-subscribers need a meaningful credit cushion just to unlock the feature at all.
The Access Rule, Broken Down
| Account state | Can start a Compete attempt? | Cost per attempt |
|---|---|---|
| Unlimited-credit plan | Yes | Free |
| Paid plan (limited credits) | Yes | 1 credit |
| Non-subscriber with 250+ credit balance | Yes | 1 credit |
| Non-subscriber under 250 credits | No | — |
The 250-credit floor for non-subscribers isn't a per-attempt price — it's a qualifying balance a student needs on hand before Compete unlocks, after which each attempt still only draws down 1 credit. It's a gate against a near-empty balance bouncing in and out of a feature it can't sustain, not a cost of roughly 250 credits per game.
Where Compete Fits in EduGenius, and Where It Doesn't
Compete is shipped entirely on the learner side of EduGenius — there is no teacher-facing entry point into it. The persona navigation simply doesn't surface a Compete link for a teacher account, which lines up with how EduGenius adapts the whole app to a student's, teacher's, homeschooler's, or tutor's role from the moment someone signs up.
A Practice Surface, Not a Grading Surface
Compete produces a ranking, not a grade — a teacher looking for gradebook data or assignment tracking is working in a different part of the product, closer to what Teaching Spaces or an actual assignment flow is built for. Compete's job is giving a student a reason to practice retrieval under real time pressure, alongside peers in the same cohort.
Trying It Before Committing an Account
For anyone who wants to see a populated Compete leaderboard before creating a real account, Demo Mode fills the cohort list and leaderboard with sample entries instead of an empty "pick a cohort" screen — the same substitution pattern Demo Mode uses across the learner experience.
The Practice Question Format Behind the Challenge
The multiple-choice format Compete builds its challenges from is the same core question type used elsewhere in EduGenius's content tools — the kind of quiz a student might also generate directly for untimed review, or export as a Google Form for a different context. Compete's contribution isn't a new question format; it's the timed, ranked, server-verified wrapper around one that already exists across the product.
A Worked Example
Picture a student named Maya in an 8th-grade science cohort. She joins the "Grade 8 Science Challenge," picks Medium difficulty, and starts a 10-question attempt on a 60-second-per-question clock. She finishes in just under 7 minutes and submits, and the server recomputes her score against the answer key it embedded when she started — independent of anything her browser reported — before posting her result to the shared leaderboard.
Pro Tips
- Pick a difficulty that matches your actual pace, not your ambition. Hard gives 75 seconds a question; Easy's 45-second window rewards recall speed more than depth.
- Don't refresh or leave the tab mid-attempt expecting a clean restart. The active-attempt check blocks a second attempt on the same challenge while one is still pending.
- Treat a tie on the leaderboard as more art than mystery. If your score matches a classmate's, the earlier of your two attempt timestamps decides who ranks above the other.
- Join more than one cohort if more than one fits your grade and subjects. Auto-seeded starter cohorts cover multiple subjects at once.
What to Avoid
- Don't assume a fast finish is being actively blocked. Unusually quick attempts are flagged in the data today, not rejected — scores and timing can't be forged, but speed alone doesn't disqualify a result.
- Don't expect streaks or XP to be tracking anything yet. Those fields exist in the data model but aren't incremented by any current code path.
- Don't mistake the Achievements panel for real badges outside demo mode. It has no live badge source yet, by the component's own code comment.
- Don't look for Compete inside a teacher account. It's a student-only surface with no parallel teacher entry point.
Key Takeaways
- Compete is a real, shipped, student-only feature — a cohort-scoped, timed, 10-question AI-generated MCQ leaderboard with no teacher-facing entry point.
- Difficulty controls question style and time budget: 45 seconds a question for Easy, 60 for Medium, 75 for Hard, with Mixed blending difficulty on the Medium clock.
- The real engineering story is server-side integrity: the answer key is embedded at start time and never sent to the browser, the attempt token is HMAC-SHA256 signed and verified with a constant-time comparison, and elapsed time comes from the server clock, not a client-reported duration.
- Suspiciously fast completions are flagged, not blocked — the
suspiciously_fastflag is written into the attempt data but isn't currently read anywhere to reject or penalize a submission. - The gamification layer is honestly thin: streak and XP fields exist in the schema but are never incremented, and the Achievements panel is explicitly demo-mode-only in the code.
- Access has real, published economics: 1 credit per attempt for paid or credit-funded users, free for unlimited-credit plans, and a 250-credit minimum balance for non-subscribers to unlock the feature at all.
- The leaderboard's tiebreak rewards being first, not most recent — when two students share a best score, the earlier attempt timestamp ranks higher.
Frequently Asked Questions
What is Compete Mode in EduGenius?
A student-only feature where a cohort of learners takes the same timed, 10-question AI-generated multiple-choice challenge and lands on a shared, server-computed leaderboard ranked by best score.
Can teachers use Compete Mode?
No. Compete's shipped scope is entirely student-facing — the persona navigation gives teacher accounts no entry point into it.
How does Compete stop students from cheating on the timer or the score?
Three server-side mechanics work together: the answer key is embedded in the attempt record at start time and never sent to the browser, the attempt token is HMAC-SHA256 signed and checked with a constant-time comparison, and elapsed time is calculated from the server clock rather than trusting a client-reported duration.
Does Compete actually block students who finish suspiciously fast?
Not currently. Attempts finishing in well under half a second per question on average get tagged with a suspiciously_fast flag in the data, but nothing in the codebase reads that flag to reject or penalize the score automatically.
Do streaks and XP actually work in Compete?
Not yet. Both fields exist in the leaderboard data model and initialize to zero, but no function anywhere in the codebase increments either one — inert scaffolding rather than a working system.
Is the Achievements panel showing real badges?
Not for a live account. The panel's own code comment states there's no real badge source built yet, so it only displays sample badges in demo mode.
How much does it cost to play Compete?
1 credit per attempt for paid or credit-funded accounts; free for unlimited-credit plans. Non-subscribers need at least a 250-credit balance on hand before the feature unlocks at all.
How are questions generated for a Compete challenge?
By Gemini, cached per cohort, challenge, and difficulty for seven days — not a single static bank reused indefinitely, and not freshly generated for every individual attempt.
What happens if two students tie on the leaderboard?
The tie is broken by attempt timestamp, earliest first — whoever reached that score first keeps the higher rank.
Related Reading
- How EduGenius Adapts to Your Role: Teacher, Homeschooler, Tutor, or Student
- How EduGenius's Demo Mode Lets You Explore the App Before You Create Anything
- How EduGenius's AI Coach Balances Chat With Actual Practice
- What Are Teaching Spaces in EduGenius? Organizing Classes, Sections, and Rosters
- How to Export an AI-Generated Quiz to Google Forms With EduGenius
- How to Save and Reuse Content Recipes in EduGenius