In short
A quiz app looks easy until you handle timers, scores and what happens after the last question. It's great practice for state that changes step by step.
A multiple-choice quiz app with scoring and a results screen — practice for state management, conditional rendering and array iteration in vanilla JS. A quiz app teaches the difference between application state and rendered UI while providing natural practice with arrays, events, scoring, and conditional views.

Think of it like this
Your own KBC
A question, four options, lock the answer, reveal right or wrong, update the winnings, next question. Your app runs that same loop, just without the dramatic background music. Unless you add it, of course.
Watch it happen
One round of the quiz loop
1/6showQuestion renders question 1, "typeof null?", with three option buttons.
The big ideas
What you need to know
Questions are data
Keep questions in an array of objects with the text, options and the right answer's index. Never hardcode them in HTML.
Track a little state
current question index, score, and whether this question has been answered yet.
A timer per question
Use setInterval for the countdown and clearInterval when the user answers or time runs out.
A proper ending
Show the score, which answers were wrong, and a restart button that resets all state.
How it works
Build plan
- 1
Write the data
An array of 5 to 10 questions with options and answer index.
- 2
Show a question
Render the text and one button per option.
- 3
Check the answer
Mark right or wrong, update the score, lock the options.
- 4
Next or finish
Move to the next question, or show results after the last one.
- 5
Add the timer
A countdown per question, plus a restart that clears everything.
See it in code
Walk through the code
1const questions = [2 { q: "typeof null?", options: ["null", "object", "undefined"], answer: 1 },3 { q: "2 + '2'?", options: ["4", "22", "NaN"], answer: 1 },4];5let current = 0;6let score = 0;7 8function choose(index) {9 if (index === questions[current].answer) score++;10 current++;11 if (current < questions.length) showQuestion();12 else showResult(`You scored ${score}/${questions.length}`);13}1/4Questions are data: text, options and the right answer's index.
showQuestion and showResult are yours to write. choose is the heart of the app: check, score, move on or finish.
Save yourself the pain
Common mistakes
Oops
Starting a new setInterval for each question without clearing the old one.
Do this instead
Old timers keep ticking and the countdown speeds up. Store the id and call clearInterval before starting a new one.
Oops
Letting users click several options on the same question.
Do this instead
Disable all option buttons as soon as one is clicked.
Your mission
Milestone 1: three questions, one score
Quick check
You start a new setInterval for every question but never clear the old ones. What will users see?
Go deeper
- 1Store questions as an array of objects and render them dynamically. Validate your understanding by applying it in a small practical example.
- 2Track score and current question index in simple state variables. Validate your understanding by applying it in a small practical example.
- 3Add a results screen summarizing correct vs incorrect answers.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.