Ibnovate Course 2 · The Rising Builders
⏱ 75 minLive session

Session 17 — Build a Real App

Duration: 75 min · Format: live online

What you'll learn: by the end, you'll have built a complete, working quiz app in CodePen — questions, answer buttons, score tracking, and a final result — combining all three layers.

Soft skill focus — Creativity

Today you'll also grow Creativity. Everyone builds the same quiz engine, but the questions, topic, and look are wide open — that is where your version becomes yours and not a copy of the demo.

Try this: when you reach the "make it theirs" step, take two minutes to brainstorm a topic you actually care about before you change a single question. Go for the boldest, most personal choice over a safe copy of the sample.

Think about: what did you change to make this quiz unmistakably yours?

What you'll need


Hook

Think about these questions:

Here's the idea: an app is just the three layers working together, plus a bit of memory — state — that changes as you use it. Today you build a full quiz: it asks questions, checks answers, keeps score, and shows a result. Same skills as any app you've used.


Teach — Plan the app and store the questions

Plan before you type. Sketch the app out:

Picture the quiz-app flow: show a question, pick an answer, score it, loop to the next, then show the result.

Flowchart of the quiz app: show a question, pick an answer, update the score, loop back for the next question, then display the final result

Instead of writing each question into the HTML by hand, we store them as data — an array (an ordered list) of objects (each a question with its answer). This is the same idea as a dataset from Unit 1.

Type and run this in CodePen (in the JS panel):

const questions = [
  { text: "What does HTML build?", options: ["Structure", "Coffee"], answer: "Structure" },
  { text: "What does CSS add?", options: ["Style", "Sound"], answer: "Style" },
  { text: "What makes a page interactive?", options: ["JavaScript", "Magic"], answer: "JavaScript" }
];

let current = 0;
let score = 0;

console.log("Total questions:", questions.length);

Look at the shape: questions is an array (square brackets [ ]); each item is an object (curly braces { }) with a text, an options list, and the correct answer. current tracks which question you're on; score counts correct answers. These two variables are the app's state.

⚠ Watch for the #1 confusion: arrays are counted from 0, not 1. questions[0] is the first question. current starts at 0 for exactly this reason.


Teach — Show a question and react to a click

You need one function that draws the current question, and a click handler that checks the answer. First the HTML shell and some style:

Type and run this in CodePen (HTML):

<div id="quiz">
  <h1 id="question">Question goes here</h1>
  <div id="options"></div>
  <p id="score">Score: 0</p>
</div>
#quiz {
  max-width: 400px;
  margin: 40px auto;
  font-family: sans-serif;
  text-align: center;
}

button {
  display: block;
  width: 100%;
  margin: 8px 0;
  padding: 12px;
  border: none;
  border-radius: 8px;
  background-color: #16233A;
  color: white;
  font-size: 16px;
  cursor: pointer;
}

Now the function that shows a question (JS):

const questionEl = document.getElementById("question");
const optionsEl = document.getElementById("options");
const scoreEl = document.getElementById("score");

function showQuestion() {
  const q = questions[current];
  questionEl.textContent = q.text;
  optionsEl.innerHTML = "";
  for (const option of q.options) {
    const btn = document.createElement("button");
    btn.textContent = option;
    btn.addEventListener("click", function () {
      checkAnswer(option);
    });
    optionsEl.appendChild(btn);
  }
}

Read it slowly: you read the current question, set its text, clear the old buttons, then loop over the options and build a fresh button for each — wiring each one to checkAnswer.

Ask yourself: why do we clear optionsEl.innerHTML before adding buttons? (Otherwise the previous question's buttons pile up on screen.)


Activity — Build the quiz end to end

Work in your own Pen. Add the two remaining functions, then start the quiz.

Type and run this in CodePen (JS — add below showQuestion):

function checkAnswer(choice) {
  if (choice === questions[current].answer) {
    score = score + 1;
  }
  current = current + 1;
  if (current < questions.length) {
    scoreEl.textContent = "Score: " + score;
    showQuestion();
  } else {
    showResult();
  }
}

function showResult() {
  questionEl.textContent = "Done! You scored " + score + " / " + questions.length;
  optionsEl.innerHTML = "";
  scoreEl.textContent = "";
}

showQuestion();

Run the whole quiz — click through all three questions to the result screen. Notice the final line: showQuestion() starts everything by drawing the first question.

Then make it theirs: change the questions to your own topic (football, music, science), add a fourth question to the array, and restyle the buttons with your colours from Session 15.

Watch out for the two errors nearly everyone hits — forgetting the final showQuestion(); call (so the app loads blank), and comparing with = instead of === inside the if.

Debug Game. Here's a broken check — can you spot two mistakes before you read the fix?

function checkAnswer(choice) {
  if (choice = questions[current].answer) {
    score + 1;
  }
  current = current + 1;
}

The score never goes up and the answer always counts as right — why? Here's the fix:

  1. if (choice = ...) uses a single = (which assigns, always truthy). Use === to compare: if (choice === questions[current].answer).
  2. score + 1 computes a value but throws it away — you must store it: score = score + 1;.

Check yourself

Can you answer these? The answer follows each arrow.

  1. What is "state" in this app, and which variables hold it? → The app's changing memory — current (which question) and score (how many right).
  2. Why do we use === and not = inside an if?=== compares two values; a single = assigns and would always run the branch.
  3. What does questions.length give, and why do we compare current to it? → The number of questions (here 3); when current reaches it, there are no questions left, so we show the result.

Wrap-up


Tips & extra challenges

function restart() {
  current = 0;
  score = 0;
  scoreEl.textContent = "Score: 0";
  showQuestion();
}

Vocabulary

Term Meaning
Array An ordered list of values, in [ ], counted from 0
Object A bundle of named values, in { } (like a record)
State The app's changing memory, e.g. current and score
Loop (for … of) Repeats an action once per item in a list
=== Compares two values for exact equality

Resources

Practice set

Practise on your own — these reinforce arrays, loops, comparisons, and state, from easy to hard.

1. Predict the output: what prints? → 3. length counts the items in the array.

const fruits = ["apple", "banana", "mango"];
console.log(fruits.length);

2. Predict the output: what is fruits[0] and fruits[2]? → "apple" and "mango" — arrays count from 0, so index 2 is the third item.

3. Predict the output: how many lines print, and what are they? → Three lines: apple, banana, mango — the loop runs once per item.

for (const f of fruits) {
  console.log(f);
}

4. Fix the bug: the score never increases. Find the two problems. → Use === to compare, and store the result: if (choice === answer) { score = score + 1; }.

if (choice = answer) {
  score + 1;
}

5. Write it: write an array colors holding "red", "green", "blue", then log how many there are. → const colors = ["red", "green", "blue"]; then console.log(colors.length);.

6. Write it: write an object for one quiz question with a text, an options array, and the correct answer. → e.g. { text: "2 + 2?", options: ["4", "5"], answer: "4" }.

7. Trace it (hard): with current = 0 and score = 0, the user answers Q1 right and Q2 wrong (2 questions total). Trace score and current after each answer, and what showResult prints. → After Q1: score = 1, current = 1. After Q2: score stays 1, current = 2; since 2 === length, it shows "Done! You scored 1 / 2".

Going deeper (optional)

Ready for more? The questions could come from outside the app — the first step toward a data-driven app. Real apps fetch their data instead of hard-coding it. Here's the shape of that idea safely, with a local array plus a shuffle:

function shuffle(list) {
  for (let i = list.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [list[i], list[j]] = [list[j], list[i]];  // swap
  }
}

shuffle(questions);
showQuestion();

Here's the idea: because the questions are data, not hard-coded HTML, you can shuffle them, add more, or one day load them from a file — without touching the quiz logic at all. This "separate the data from the code" habit is what makes an app easy to grow. Challenge yourself to also shuffle each question's options so the right answer isn't always in the same spot.

Common mistakes & fixes

If it's not working, check these:

What's next

Session 18 — Ship It: you'll put this quiz app on the live internet with free hosting, then present it — the unit's build project.

Ibnovate · Build · Innovate
Type to search · Esc to close
Welcome back
Sign in to continue building.
Accounts are created by Ibnovate — ask your instructor for your login.
🔒