# How to Create an Interactive Quiz Platform with Leaderboard in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 30-40 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

Build a full quiz platform with timed questions using PageView navigation, RadioButton answer selection, and a countdown timer. Scores are calculated and validated server-side via a Cloud Function that compares submitted answers against correct answers stored in Firestore. A leaderboard page queries quiz_results ordered by score descending and time taken ascending, displaying ranked entries with gold, silver, and bronze styling for the top three players.

## Building a Competitive Quiz Platform in FlutterFlow

This tutorial walks you through creating a quiz platform where users answer timed multiple-choice questions and compete on a leaderboard. Unlike a simple quiz widget, this is a full platform with multiple quizzes, server-validated scoring to prevent cheating, and a ranked leaderboard that breaks ties by time taken. It is ideal for e-learning apps, trivia games, and employee training tools.

## Before you start

- A FlutterFlow project with Firestore configured
- Basic understanding of PageView and Component State in FlutterFlow
- A Firebase project with Cloud Functions enabled (Blaze plan)
- Familiarity with creating Firestore collections and documents

## Step-by-step guide

### 1. Set up the Firestore data model for quizzes, questions, and results

Create a quizzes collection with fields: title (String), description (String), category (String), questionCount (int), timeLimit (int, seconds). Under each quiz document, create a questions subcollection with fields: questionText (String), options (String array of 4 items), correctIndex (int, 0-3), order (int). Create a top-level quiz_results collection with fields: userId (String), quizId (String), score (int), totalQuestions (int), timeTaken (int, seconds), completedAt (Timestamp). Add 5-10 test questions for at least one quiz.

**Expected result:** Firestore has quizzes with a questions subcollection and a quiz_results collection ready for score storage.

### 2. Build the quiz page with timed PageView navigation

Create a QuizPage with Route Parameter quizId (String). Add a Backend Query for the questions subcollection ordered by order ascending. Add Component State: currentIndex (int, default 0), selectedAnswerIndex (int, default -1), selectedAnswers (int List, empty), startTime (Timestamp, set on page load). Place a Row at the top with a LinearPercentIndicator for question progress and a Text widget showing the countdown timer. Use a Periodic Action (every 1 second) that decrements the remaining time from the quiz timeLimit. Below, add a PageView with NeverScrollableScrollPhysics containing one question per page.

**Expected result:** A quiz page loads questions from Firestore with a visible countdown timer and progress bar.

### 3. Display questions with RadioButton answer selection

Inside each PageView page, add a Column with the questionText in Headline Small style, a SizedBox for spacing, and a RadioButton group bound to the options array. When the user taps an option, update Component State selectedAnswerIndex. Below the options, add a Next button that is disabled when selectedAnswerIndex equals -1. On Next tap: append selectedAnswerIndex to the selectedAnswers list, reset selectedAnswerIndex to -1, increment currentIndex, and call Animate to Next Page. On the last question, change button text to Submit.

**Expected result:** Each question displays with four selectable options, and the Next button advances through questions one at a time.

### 4. Calculate and validate the score via a Cloud Function

Create a Cloud Function called calculateQuizScore that accepts userId, quizId, and selectedAnswers array. The function reads the questions subcollection server-side, compares each submitted answer to the correctIndex, tallies the score, calculates timeTaken from startTime to now, and writes a quiz_results document with userId, quizId, score, totalQuestions, timeTaken, and completedAt. On the Submit button tap in FlutterFlow, call this Cloud Function via an API Call action, passing the Component State data. This prevents client-side score manipulation.

```
// Cloud Function: calculateQuizScore
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.calculateQuizScore = functions.https.onCall(async (data, context) => {
  const { quizId, selectedAnswers } = data;
  const userId = context.auth.uid;
  const questionsSnap = await admin.firestore()
    .collection('quizzes').doc(quizId)
    .collection('questions').orderBy('order').get();

  let score = 0;
  questionsSnap.docs.forEach((doc, i) => {
    if (doc.data().correctIndex === selectedAnswers[i]) score++;
  });

  const result = {
    userId,
    quizId,
    score,
    totalQuestions: questionsSnap.size,
    timeTaken: Math.floor((Date.now() - data.startTime) / 1000),
    completedAt: admin.firestore.FieldValue.serverTimestamp(),
  };
  await admin.firestore().collection('quiz_results').add(result);
  return result;
});
```

**Expected result:** Score is calculated server-side and saved to quiz_results, preventing any client-side cheating.

### 5. Display the results page with score breakdown

After the Cloud Function returns, navigate to a ResultsPage passing score, totalQuestions, and timeTaken as Route Parameters. Display a CircularPercentIndicator showing the percentage score, a Text with the fraction (e.g., 8 out of 10), and the time taken. Add a Lottie animation for celebration if score is above 70 percent, or encouragement if below. Include a Retake Quiz button that navigates back to QuizPage and a View Leaderboard button.

**Expected result:** A results screen shows the score with visual feedback, time taken, and navigation options.

### 6. Build the leaderboard page with ranked entries

Create a LeaderboardPage with Route Parameter quizId. Add a Backend Query on quiz_results filtered by quizId, ordered by score descending then timeTaken ascending (Firestore composite index required). Display the top 3 entries in a special Row with gold, silver, and bronze Container styling using CircleImage avatars and score Text. Below, show remaining entries in a ListView with rank numbers, display names, scores, and time taken. Highlight the current user's row with a distinct background color. Add ChoiceChips for filtering by Today, This Week, or All Time using completedAt date ranges.

**Expected result:** A ranked leaderboard displays quiz results with the top three highlighted and the current user's position visible.

## Complete code example

File: `FlutterFlow Quiz Platform Setup`

```text
FIRESTORE DATA MODEL:
  quizzes/{quizId}
    title: String
    description: String
    category: String
    questionCount: int
    timeLimit: int (seconds)
    └── questions/{questionId}
          questionText: String
          options: ["A", "B", "C", "D"]
          correctIndex: int (0-3)
          order: int

  quiz_results/{resultId}
    userId: String
    quizId: String
    score: int
    totalQuestions: int
    timeTaken: int (seconds)
    completedAt: Timestamp

PAGE: QuizPage
  Route Parameter: quizId (String)
  Backend Query: questions subcollection, order by order asc
  Periodic Action: every 1s, decrement timer

COMPONENT STATE:
  currentIndex: int = 0
  selectedAnswerIndex: int = -1
  selectedAnswers: List<int> = []
  remainingSeconds: int = quiz.timeLimit
  startTime: int = DateTime.now().millisecondsSinceEpoch

WIDGET TREE (QuizPage):
  Column
    ├── Row
    │     ├── LinearPercentIndicator (currentIndex / totalQuestions)
    │     └── Text (remainingSeconds formatted as mm:ss)
    ├── PageView (NeverScrollableScrollPhysics)
    │     └── Per question:
    │           Column
    │             ├── Text (questionText, Headline Small)
    │             └── RadioButtonGroup (options, selectedAnswerIndex)
    └── Button ("Next" / "Submit")
          On Tap: append answer → next page or call Cloud Function

PAGE: ResultsPage
  Route Params: score, totalQuestions, timeTaken
  Column
    ├── CircularPercentIndicator (score / totalQuestions)
    ├── Text ("score out of totalQuestions")
    ├── Text (timeTaken formatted)
    ├── Lottie (celebration or try-again)
    ├── Button ("Retake Quiz")
    └── Button ("View Leaderboard")

PAGE: LeaderboardPage
  Route Parameter: quizId
  Backend Query: quiz_results where quizId, orderBy score desc + timeTaken asc
  Column
    ├── Row (Top 3: gold / silver / bronze cards)
    ├── ChoiceChips (Today / Week / All Time)
    └── ListView (remaining entries with rank + avatar + score + time)
```

## Common mistakes

- **Calculating the score on the client and trusting the result** — Users can inspect network requests or manipulate Component State to submit a fake perfect score. Client-side calculation has zero integrity. Fix: Send only the selectedAnswers array to a Cloud Function. The function reads correct answers server-side and calculates the score itself.
- **Using App State for quiz answers instead of Component State** — App State persists to disk. If the user exits mid-quiz and returns, stale answers from the previous attempt corrupt the current session. Fix: Use Component State or Page State for in-progress quiz data. These reset when the page is left.
- **Not creating the Firestore composite index for leaderboard queries** — Querying quiz_results ordered by both score and timeTaken requires a composite index. Without it, Firestore returns an error or empty results. Fix: Create a composite index on quiz_results: quizId (ascending), score (descending), timeTaken (ascending) in the Firebase Console.
- **Allowing users to swipe between PageView questions freely** — Users skip ahead to preview questions or go back to change answers after seeing later ones, undermining quiz integrity. Fix: Set PageView physics to NeverScrollableScrollPhysics so navigation only occurs via the Next button.

## Best practices

- Validate scores server-side in a Cloud Function to prevent cheating
- Use NeverScrollableScrollPhysics on the PageView to enforce sequential question flow
- Show a countdown timer and auto-submit when time expires
- Store quiz results with timeTaken for meaningful leaderboard tiebreaking
- Display the current user's rank even if they are not in the top entries
- Disable the Next button until an answer is selected to prevent blank submissions
- Create Firestore composite indexes proactively for leaderboard sort queries

## Frequently asked questions

### Can I randomize the question order for each quiz attempt?

Firestore does not support random ordering in queries. Fetch all questions, shuffle the list in a Custom Function before binding to the PageView, and use the shuffled list for display and answer tracking.

### How do I prevent users from retaking a quiz?

On page load, query quiz_results for the current userId and quizId. If a document exists, redirect to the results page showing their previous score instead of starting the quiz.

### Can I add different difficulty levels to quizzes?

Yes. Add a difficulty field to each quiz document. On the quiz catalog page, use ChoiceChips to filter quizzes by difficulty. You can also weight scoring by difficulty in the Cloud Function.

### How do I show which answers were correct after submission?

On the results page, display each question with the user's selected answer and the correct answer. Use Conditional Styling to color correct answers green and incorrect ones red.

### What happens if the timer runs out mid-quiz?

Set up the Periodic Action to check when remainingSeconds reaches zero. When it does, auto-submit whatever answers have been collected so far by calling the Cloud Function with the partial selectedAnswers array.

### Can RapidDev help build a full quiz and e-learning platform?

Yes. RapidDev can build complete quiz platforms with adaptive difficulty, certificate generation, analytics dashboards, and multi-format question types beyond multiple choice.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-an-interactive-quiz-platform-with-leaderboard-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-an-interactive-quiz-platform-with-leaderboard-in-flutterflow
