MindMaze: Building a Simple Yet Smart Aptitude Quiz App


MindMaze wasn’t born out of a grand vision. It started with a simple idea:
"Wouldn’t it be cool if there was a clean, offline-friendly quiz app that actually felt nice to use?"
I wanted something that focused on real learning -not leaderboards or gamified fluff. Just category-based MCQs, clean performance tracking, and a UI that didn’t make me cry. So I decided to build it myself.
Spoiler alert: it did not go as smoothly as I thought.
But I learned a ton. From managing quiz state and session tracking to building analytics dashboards and dealing with the mess that is localStorage
.
This blog walks through how I built MindMaze, what went wrong (and right), and why I think projects like this are worth doing, especially if you're trying to grow as a developer.
The Goal
MindMaze had a few core goals:
Let users take quizzes in Quantitative, Logical, and Verbal categories.
Track stats like accuracy, time per question, and performance by category.
Persist everything in the browser i.e. no backend.
Be minimal but nice to look at. Clean UI, smooth transitions, readable font sizes.
Build the whole thing using React + TypeScript + Tailwind CSS (just the stack I’m comfortable with).
The Stack
Here’s what powers MindMaze:
Frontend: React + Vite + TypeScript
Styling: Tailwind CSS + shadcn/ui + custom gradients
Icons:
lucide-react
State: React Context (for user), custom hooks (for quiz logic)
Data: Static
questions.json
file for MCQsStorage: LocalStorage for everything -users, stats, quizzes
No database, no auth, no cloud functions just front-end logic done well.
How It Works (A Walkthrough)
1. Category & Quiz Selection
When the user lands on /quiz
, they’re prompted to choose a category:
Quantitative Aptitude
Logical Reasoning
Verbal Ability
Once selected, they choose how many questions they want and how much time they want to spend. This creates a session object managed by a custom hook called useQuizEngine
.
// QuizSetup.tsx
<QuizSetup
category="logical"
questionCount={10}
timeLimit={600}
/>
We store the selected category in localStorage just to persist context across reloads.
2. Quiz Engine + Timer
The core of the app is in useQuizEngine.ts
. It handles:
Shuffling and selecting questions from
questions.json
Saving user answers
Moving between questions
Submitting the quiz
Tracking total time and per-question time
Everything is stored in memory while the quiz runs. Once submitted, the data is sent to the user context to update stats.
3. Updating Stats
Stats are where things get interesting. Each user has a full stats object: For example-
{
totalQuizzes: 2,
totalQuestions: 15,
correctAnswers: 9,
averageAccuracy: 60,
averageTime: "1:12",
categoryStats: {
verbal: { solved: 5, accuracy: 40, avgTime: "0:09" },
logical: { solved: 10, accuracy: 70, avgTime: "2:55" },
...
}
}
Each quiz submission triggers an updateUserStats()
function. It calculates:
New average accuracy
Weighted average time
Per-category stats
Recently attempted quizzes
To avoid duplicate updates, I track a unique quiz hash (category_numQuestions_numCorrect_totalTime
) and store it in a processedQuizzes Set.
if (processedQuizzes.has(quizId)) {
console.log("Quiz already processed. Skipping.");
return;
}
4. The Aptitude DNA (Analytics Dashboard)
After every quiz, users see a dashboard showing:
Level and XP (based on quizzes completed)
Category-wise performance
Recent quiz history
Achievements (like "First Quiz Completed" or "Perfect Score")
Each panel is powered by reusable components (StatPanel
, MindProfileCard
, etc.) with a soft gradient aesthetic. Simple animations and icons make it more engaging without clutter.
5. Achievements (Yes, I Caved)
At first, I didn’t plan to include achievements. Then I did. Then I broke everything. Then I fixed it.
The final version adds achievements based on:
First quiz
80%+ accuracy overall
Perfect score
50+ correct answers
10+ quizzes completed
If the user has none, we show the criteria instead — so it still feels motivating without being empty.
Example Quiz Flow
Here’s how a typical user flow looks:
User selects “Verbal Ability” → chooses 5 questions, 5 minutes
Quiz begins → questions show one by one, with timer and navigation
User submits → score is calculated
Stats are updated → 40% accuracy, 0:09 avg time
Analytics dashboard shows insights
User goes again — this time Logical, 10 questions
Stats evolve — accuracy increases, XP grows, achievements unlock
User starts seeing patterns in their own aptitude profile
Everything happens on the frontend. No login, no API calls, no server latency. Just a personal learning loop.
What Didn’t Work
This was not a walk in the park.
Stat inflation: I updated user stats every render, which inflated quiz counts until I fixed it with a
hasUpdatedStatsRef
.Achievements crash: One
undefined.includes()
later, the whole app crashed. Lesson learned: always check your types.Offline support: I tried to make it a PWA. It mostly works —- but caching dynamic session data was messy. That’s a story for another day.
What I Learned
Frontend apps can do more than we think — With just React and localStorage, we can create meaningful, persistent learning tools.
State management matters — The difference between a janky and smooth quiz app is often in how you manage transitions, resets, and side effects.
Small projects teach a lot — This project taught me more about polish and UX than any tutorial ever could.
What’s Next?
I’m planning to:
Add more question types (drag/drop, grid logic)
Improve accessibility (keyboard nav, screen reader support)
Enable true offline mode with IndexedDB and SW caching
Add progress sync (in case I do add auth later)
Wrapping Up
MindMaze isn’t perfect. But it’s real. It works. And more than anything — I learned a lot by building it.
I enjoy building full-stack web apps that feel smooth and thoughtful.
I use TypeScript (willingly), and I pay attention to user experience, edge cases, and the little things.
Sometimes that means writing logic for quiz state...
Other times, it means obsessing over a 2px box shadow!
If you’d like to check out the project:
Thanks for reading!!! 💫
Subscribe to my newsletter
Read articles from Maithri Meda directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Maithri Meda
Maithri Meda
I'm Maithri. I'm presently in my final year of my bachelors degree in technology. I enjoy building, making cool tech apps and sites that have a purpose and serve in helping and making our everyday lives a bit more exciting. Other than that, I enjoy travelling, singing, cooking, working out and cycling as well. I love reading novels and watching films. I am particularly a fan of fantasy, horror and scientific fiction books. My interests led me to start a blog and to share about my perspective of things. I do like to write, so, I thought of leading in like-minded individuals into this environment to explore and make sense of our interests.