Use the Notion API to create a Quiz with JavaScript


Notion is a multi-featured app for organizing all sorts of content, from notes to calendars and reminders. In our last article, “Getting Started with the Notion API and Its JavaScript SDK”, we delved into how to use Notion’s API and created a small interface to interact with it. This article now will explore another use case for the Notion API: creating a JavaScript quiz.

While no previous knowledge is needed to follow along with this article (I’ll provide all the required steps), we’ll be dealing with front-end and back-end code, as there’s a bit of Node.js and Express setup involved, so some JavaScript skills are assumed.

JavaScript Quiz Project Setup

We’re going to split our setup into two sections. In the first one, we’ll walk through the required setup on the Notion side, and one the second part we’ll work with our code.

To follow along, you’ll need a Notion account (more on that below), as well as a recent copy of Node installed on your machine. As ever, the final code for the tutorial can be found on GitHub.

The Notion Setup

If you don’t already have a Notion account, please create one by following this link. After creating your account and logging in, create a new page by choosing Add a page and give it a name. For this tutorial, we’ll use a Table database. Although it’s not the ideal database to build a quiz, it’s the closest we can achieve with Notion!

Inserting information into the table

Now that we have our empty Table, we need to figure out how to properly insert our information into it.
Our intended schema for our quiz is the following:

{
“1”: {
“Question”: “Which is the purpose of JavaScript?”,
“Answers”: {
“1”: “To style HTML Pages”,
“2”: “To add interactivity to HTML pages”,
“3”: “To perform server side scripting operations”
},
“Correct”: “To add interactivy to HTML pages”
},
“2”: {
“Question”: “To insert a JavaScript into an HTML page, which tag is used?”,
“Answers”: {
“1”: “<script=’java’>”,
“2”: “<javascript>”,
“3”: “<script>”
},
“Correct”: “<script>”
},
“3”: {
“Question”: “Which of the following is correct to write “Hello World” on the web page?”,
“Answers”: {
“1”: “print(‘Hello World’)”,
“2”: “document.write(‘Hello World’)”,
“3”: “response.write(‘Hello World’)”
},
“Correct”: “document.write(‘Hello World’)”
}
}

Notion isn’t really built for this type of database, so we need to get creative with it! 💡 So our Question column will be just a Title (which works great) and our Correct column will be of type Text (which also works as intended). For our multiple options, though, we need to do something different! My approach to it is to use the Multi-select field type so I can write multiple results into the same cell (we’ll see down the path what the data retrieved from this looks like). So our Table should look like the following image as the end result.

Creating our Notion API integration

Now we need to go to the Notion API website to create our integration. Press the My Integrations button on the top right corner and then click on Create new integration. We need to fill in our title and be sure to choose our Associated workspace (it will be chosen by default but make sure of this). If we press Submit, we’ll be directed to a new page with an Internal Integration Token (we’ll use this in our code) and with two option boxes for where we want to use our integration. We don’t need to do anything on this page other than copy our token and press Save changes.

Now we go back to our Notion workspace. In our newly created Notion database, we want to press Share, then Invite. We’ll then be able to choose our newly created integration. If we choose it and press Invite, our Notion setup is done. Well done! 🙌

The Code Setup

For our code setup, we’ll use a Notion template repository (which we can then use on any of our Notion API projects!) that already has the initial code required to work with Notion’s API. This repo can be found here, so be sure to fork it and clone it to accompany our project! If you’re interested in what all the bits of code do, please refer to “Getting Started with the Notion API and Its JavaScript SDK”, since we go into a lot of detail for every bit of code (the repo also has a README that should explain what it does!).

Installing dependencies

After forking and cloning our Notion template repo, our first step is to install our dependencies, so make sure to run yarn or npm install on our terminal inside the folder. In this project we have three dependencies: the @notionhq/client, dotenv and Express. We’ll use dotenv to manage our variables and keep them safe (such as the one we saw on our integration) and Express to create our back end and server for our application.

To manage our variables with dotenv, create a .env file at the root of our project and paste the following there:

NOTION_API_KEY = YOUR_TOKEN_HERE
NOTION_API_DATABASE = YOUR_DATABASE_ID_HERE

Our NOTION_API_KEY is the key that we can find in our Integrations, and our NOTION_API_DATABASE can be found by going to the created Notion page and looking at the browser’s URL bar. It comes after your workspace name (if we have one) and the slash (myworkspace/) and before the question mark (?). The ID is 32 characters long, containing numbers and letters:

https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=…
|——— Database ID ——–|

If we’re worried about having Notion’s API keys on a file inside our repo, notice that on our .gitignore we have the .env file there; the .gitignore allows us to put different file/folder names inside, and that means that these files/folders won’t be added to our repo when we push our code.

Now that we have our initial repository and we have the required credentials from Notion, we can start working on our quiz!

Grabbing the JavaScript Quiz Data

We should first check if we’re successfully connected to our Notion database, so we’ll navigate to our .index.js file and log our reponse variable (see how we’re grabbing our databaseId from our .env file and using it on our database query?).

If we then run yarn start, we should see something like the following screenshot on our terminal.

Seeing this on our terminal means that we’re properly connected to our Notion database and that we can now get our required data. Our getDatabase function will look like this:

exports.getDatabase = async function () {
const response = await notion.databases.query({ database_id: databaseId });

const responseResults = response.results.map((page) => {
return {
id: page.id,
question: page.properties.Question.title[0].plain_text,
answers: page.properties.Answers.multi_select,
correct: page.properties.Correct.rich_text[0].plain_text,
};
});

return responseResults;
};

With responseResults, we’re mapping over our results (matching the entries in our database) and we’re mapping the paths for different properties to names that we’re choosing (in this case, id, question, answers and correct). Notice how specific the object path is. This is by design, which means that, when developing and working with your own database, you should continuously investigate the returned properties until you find the information you’re looking for (it’s really a matter of trial and error).

With this new code, we’re pretty much making a call to our API and picking the properties that we want to use in our code, which means that we’re ready to work with them on our interface!

Showing Our Data in the Browser

Let’s start by dealing with our HTML and CSS, since they’re pretty direct! We won’t do any changes on our HTML from the template, and on our style.css we can paste the following code beneath the existing one:

.questionContainer {
padding: 30px;

display: flex;
flex-direction: column;
justify-content: center;
align-items: center;

box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
border-radius: 10px;
}

.numberElement {
margin: 0px auto 10px;

font-size: 12px;
font-weight: 700;
text-transform: uppercase;
}

.question {
margin: 0px auto 40px;
}

.answersDiv {
width: 100%;

display: flex;
flex-direction: column;
gap: 20px;
}

.answerOption {
padding: 20px;
margin: 0px;

font-size: 18px;
text-align: center;

cursor: pointer;

border: 1px solid rgb(42, 43, 44);
border-radius: 40px;
}

We won’t see these styling changes yet, but we can now focus on the functionality, which is the more important part of this tutorial.

If we now go to the main.js file inside the public folder, we’ll see that we’re already grabbing our data from our back end with the getDataFromBackend function. If you’re confused by this, “Getting Started with the Notion API and Its JavaScript SDK” has a lengthier explanation for it, but basically on our server.js we created a route that gets our database, and here on getDataFromBackend we’re making a fetch to that same route, which will grab our data for us.

Notice how inside addData we already have const data = await getDataFromBackend();. This means that we’re ready to start working with our data, and we can actually check this! log this data variable and we should see, on our console, an array of our database entries.

Continue reading
Use the Notion API to create a Quiz with JavaScript
on SitePoint.

Leave a Comment

Your email address will not be published.

Scroll to Top