TNS
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
NEW! Try Stackie AI
Databases / Software Development

Build a Custom Quiz App With Nuxt and Xata

Use open source technologies to create an intuitive Q&A application to test your (or someone else’s) knowledge.
Feb 12th, 2025 9:00am by
Featued image for: Build a Custom Quiz App With Nuxt and Xata
Featured image by Soifer on Shutterstock.
Life is a continuous test of your knowledge. This tutorial delves into how to build a question-answering (quiz) application with Nuxt and Xata as the data store. Nuxt.js is an intuitive, open source framework built on Vue that helps create performant, production-grade, full-stack web apps. And Xata is an open source serverless PostgreSQL database built for modern development that is optimized for reliability, scalability and the developer experience. In this guide, you’ll learn how to use the Xata database to:
  • Fetch questions and answers.
  • Track the number of questions answered and the correct answers.
  • Display the final result based on the user’s performance.
Let’s explore and create something amazing together!
Get the completed Nuxt and Xata code for this guide in this GitHub repo.
Example Quiz app question "Who wrote 'Romeo and Juliet'?" with four potential answers: Charles Dickens, William Shakespeare, Mark Twain, Jane Austen

Quiz application

Getting Started

Before you begin, complete the following tasks to create a new Nuxt app: Run the Nuxt command-line interface (CLI) command, which will bundle the boilerplate and its necessary dependencies to start a new project:
npx nuxi@latest init xata-quiz-app
Accept the default options and follow the other instructions from the installation prompt:
cd xata-quiz-app
npm install
npm run dev
The application runs on http://localhost:3000.

Create a New Database

With the Xata CLI, install the command to connect your project code to Xata and authenticate your account to the CLI, which will generate a new database. Next, run this command:
xata init
Output of `xata init` command

Xata CLI integration with Nuxt.js

This command creates .env, .xatarc and src/xata.ts files within your root directory, and includes all necessary credentials to access your database. Note that the data in these files is automatically generated.

Define the Database Schema

Create a new seed folder in the project’s root directory and download the questions CSV file. There are two ways to add data with its defined schema: either manually through the Xata user interface (UI) or by using the CLI. The Xata CLI will handle the table creation and autogenerate the schema by importing the data from the terminal into the database.
curl --create-dirs -o seed/questions.csv 
https://raw.githubusercontent.com/Terieyenike/xata-quiz-app/main/seed/questions.csv
Choose one of the methods above and apply it to your project. Either manually create the folder or run the command to create the CSV file in the seed folder.

Create the Other Schema

The reason for doing this is to link the answers table (which is an example of a one-to-many relationship) to the questions table, which may not be possible by importing the CSV to the Xata UI. In your dashboard, click Tables to add the new table, called answers, to the preexisting questions table by using the + Add a table button.
Schema view for adding additional tables

Schema view for adding additional tables

Below the answers schema, click on + Add a column to add the following columns with the following column type:
  • answer_text: text
  • is_correct: boolean
  • question: link; under Table to link records from in the drop-down menu, select questions from the drop-down. For the column name, type in question
To create a quiz, you need to add records to the questions and answers tables in your Xata database, as shown in this animation. Make sure to include right and wrong answers to the answers table for each question in the questions table.
With the database schema in place, generate the code that allows you to access and query the data in the Nuxt application. Run this command to apply the changes in your code:
xata pull main
This updates the contents of src/xata.ts based on the schema defined on the main branch of your database. If you make any changes to the schema, run xata pull <branch> to update the autogenerated code.

Register the API

In the codebase, the server in the root directory is used to register APIs, which will be vital when calling the APIs in the page of your application. Within the server directory, create a folder called api with the following files:
  • answers.ts
  • questions.ts
server/api/answers.ts server/api/questions.ts Each file imports the getXataClient function and assigns the result of calling the function with a variable named xata. The server uses the configuration sets in the .env file to read its data from the database. It is also important to note that the export defineEventHandler function returns the data in JSON. To test the results in your browser, run either http://localhost:3000/api/answers or http://localhost:3000/api/questions.
"Answers" JSON data

“Answers” JSON data

Style the App

Create a file named assets/css/main.css in the root directory to contain the app’s stylesheet: assets/css/main.css Now, update the nuxt.config.ts file to accept the changes globally. nuxt.config.ts

Create the Quiz Application

You’re now ready to start setting up the quiz application. Create a folder named components in the root directory and add these files: Footer.vue, Questions.vue and Result.vue. components/Footer.vue components/Questions.vue components/Result.vue To see the result in the browser, create a new folder called pages; in it, create a file called index.vue with the following contents: pages/index.vue The useSeoMeta composable helps you define your site’s SEO with details that can be found in every modern web app or website, such as title, description, open graph (OG) image, description for social media and so on. In addition, the results array of objects will be shown only when the user completes the quiz, to report the number of answers the user got right with their respective title and description. So far, the page looks like this:
Quiz app UI before it's integrated with the database

Quiz app sample question

Render the Questions

Before you render the questions from the database, update the home page: pages/index.vue To keep track of how many questions and answers the player gets correct, define the state with a default value 0 with the useState composable. Also, import the questions and answers API endpoints with the useFetch composable. In the Questions component, using the v-if directive with questionsAnswered < questions.length states that if the questions answered are less than the question’s length, show the question component; otherwise, show the Result component with the v-else directive. Finally, apply the attributes :questions and :answers and bind them to the questions and answers array objects. The numQuestions variable counts the length of the questions array. components/Questions.vue The updated code for the Result component accepts the questions and answers properties passed down from the parent component in the defineProps() macro. The getAnswersForQuestion function uses the filter method to create a new array.
All questions and answers are on one screen

All questions and answers

Display a Single Question

As of now, all the questions are displayed, but a better user experience is to show one question at a time. Back in the pages/index.vue file, pass an attribute called questionsAnswered in the Questions component. pages/index.vue In the Questions.vue component, pass the props as follows: components/Questions.vue Check whether the current index of the questions answered in the loop matches the index in the database, using the v-show attribute with the qi in the v-for.
Displaying a single question with 4 answer choices and a reset button

Displaying a single question with answers

Listen to Clicks

You still have a static page that’s not interactive to a user’s clicks. To keep track of the correct answer, you have to pass the selected answer to the parent component. Update the Questions.vue component: components/Questions.vue The selectAnswer() function passes a parameter with the boolean value is_correct and receives an emit event with the value question-answered. Vue requires you to add the emit option, which lets you know what custom events will be emitted from the component. In the home component, index.vue, pass the event in the Questions component with the questionAnswered function, which is responsible for incrementing both the value of totalCorrect (answer) and the questionsAnswered (questions) on the user’s click. pages/index.vue

Work on the Progress Bar

When a user answers a question, the bar above the question should increase. In the Questions.vue file, use the style bindings and pass an object (:style) to handle the changes dynamically. Also, within the status element, change the static value to its respective expressions. components/Questions.vue
Progress bar above the question shows 2 out of 5 questions answered

Progress bar

Enable Quiz Reset

Upon reaching the end of the quiz, it would be nice for a user if they could click the reset button and return to the first question. In the index.vue component, add: pages/index.vue The Reset button element contains the condition that states that if the number of questions answered is equal to the length of the questions in the database, the user should be returned to the first question.

Calculate the Result

The quiz result is essential for the user to know their score. Update the index.vue component and pass the following in the <Result /> component: pages/index.vue Next, update the Result component with the following: components/Result.vue In the code block, the resultIndex uses the computed object to compare the minimum and maximum values with the user’s total number of correct answers. If both indexes are true, a result has been found. The currentResult displays the result from the results array, mapping to the index value. Finally, the computed titleClass property changes the color of the {{ currentResult.title }} expression to either red if the user gives incorrect answers or green for the right answers.
Results screen indicates 1 of 5 questions were correctly answered and recommends doing more studying

Results screen

Wrapping Up

The quiz application is a fun project that can be scaled to include other features, such as capturing data from multiple users with authentication. This guide demonstrated the possibilities of using Xata as a backend database paired with a frontend technology, Nuxt, and its effectiveness for various applications, such as quizzes. We hope you have as much fun building quiz apps as your users will have answering the questions in them.

More Information

For further insights, explore the references below: Now you’ve mastered building a quiz app, read Andela’s blog, Python for Automating APIs: Create a Trivia Quiz CSV File, and learn how to generate a list of CSV trivia questions and answers using the Trivia API.
Group Created with Sketch.
TNS owner Insight Partners is an investor in: Enable.
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.