Ibnovate Course 2 · The Rising Builders
⏱ 75 minLive session · ages 12–15

Session 17 — Build a Real App

Duration: 75 min · Format: live online · Ages: 12–15

Session goal: by the end, students have built a complete, working quiz app in CodePen — questions, answer buttons, score tracking, and a final result — combining all three layers.

Before class — prep (5 min)

Agenda

Time Segment
0:00 Hook — what's the smallest "real app"? (5 min)
0:05 Teach — plan the app and store the questions (13 min)
0:18 Teach — show a question and react to a click (17 min)
0:35 Activity — build the quiz end to end (23 min)
0:58 Check for understanding (10 min)
1:08 Wrap-up + homework (7 min)

0:00 · Hook (5 min)

Ask the class and take a few answers (chat or unmute):

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


0:05 · Teach — Plan the app and store the questions (13 min)

Explain first, code second. A good developer plans before typing. Sketch the app out loud: - Show a question and some answer buttons. - When an answer is clicked, check if it's right, update the score, and move to the next question. - At the end, show the final score.

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

Explain the data. 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/run this together 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);

Point out 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 we'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.


0:18 · Teach — Show a question and react to a click (17 min)

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

Type/run this together 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);
  }
}

Walk through it slowly: we 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: "Why do we clear optionsEl.innerHTML before adding buttons?" (Answer: otherwise the previous question's buttons pile up on screen.)


0:35 · Activity — Build the quiz end to end (23 min)

Have students work in their own Pen alongside you. Add the two remaining functions, then start the quiz. Screen-share as a model.

Type/run this together 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 live — click through all three questions to the result screen. Point out the final line: showQuestion() starts everything by drawing the first question.

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

Circulate for (or watch the chat 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.

Demo the Debug Game. Share this broken check and ask students to spot two mistakes before you fix it:

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

Ask: "The score never goes up and the answer always counts as right — why?" Then fix it live: 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;.


0:58 · Check for understanding (10 min)

Ask these aloud or drop them in the chat. Answer key (for you):

  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.

1:08 · Wrap-up + homework (7 min)


Teaching notes

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

Extra exercises reinforcing arrays, loops, comparisons, and state — easy to hard. Great for lab time or homework.

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)

For a class that's flying, show that the questions could come from outside the app — the first step toward a data-driven app. Explain that real apps fetch their data instead of hard-coding it, then show 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();

Land 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 them to also shuffle each question's options so the right answer isn't always in the same spot.

Common mistakes & fixes

Next session

Session 18 — Ship It: students 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.
🔒