Build a Custom Quiz App With Nuxt and Xata
- Fetch questions and answers.
- Track the number of questions answered and the correct answers.
- Display the final result based on the user’s performance.

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
cd xata-quiz-app
npm install
npm run dev
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

Xata CLI integration with Nuxt.js
.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 newseed 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
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
- 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
xata pull main
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, theserver 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
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
Style the App
Create a file namedassets/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 namedcomponents 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 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 theQuestions 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
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 thepages/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 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 theQuestions.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 theQuestions.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
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 theindex.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 theindex.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
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:- Demo quiz app
- GitHub repo
- Xata docs: Import/export CSV files
- Nuxt docs: SEO and meta
- Get started with Nuxt and Xata
- Nuxt docs: Directory structure/server
- Nuxt docs: useState composable
- Nuxt docs: useFetch composable