Notion is a multi-featured app for organizing every kind of content material materials, from notes to calendars and reminders. In our remaining article, “Getting Started with the Notion API and Its JavaScript SDK”, we delved into learn how to make use of Notion’s API and created a small interface to work along with it. This textual content now will uncover one different use case for the Notion API: making a JavaScript quiz.
Whereas no earlier data is required to watch along with this textual content (I’ll current all the required steps), we’ll be dealing with front-end and back-end code, as there’s slightly little bit of Node.js and Categorical setup involved, so some JavaScript experience are assumed.
Key Takeaways
- Profit from the Notion API to creatively adapt a Desk database for creating a JavaScript quiz, no matter Notion not being inherently designed for quiz databases.
- Implement a JavaScript and Node.js setting, incorporating Categorical and dotenv for server administration and setting variable security.
- Securely mix with Notion by producing and using an Inside Integration Token, making sure API interactions are authenticated.
- Retrieve quiz data from Notion using a structured query that maps database entries to a usable format inside the JavaScript software program.
- Enhance shopper interaction by dynamically rendering quiz questions and options inside the browser, and coping with shopper responses with seen options.
- Leverage the flexibleness of the Notion API to customize and automate the quiz setup, making it a scalable reply for quite a few functions.
JavaScript Quiz Mission Setup
We’re going to separate our setup into two sections. Throughout the first one, we’ll stroll through the required setup on the Notion side, and one the second half we’ll work with our code.
To look at alongside, you’ll need a Notion account (further on that beneath), along with a modern copy of Node put in in your machine. As ever, the remaining code for the tutorial is likely to be found on GitHub.
The Notion Setup
In case you don’t already have a Notion account, please create one by following this hyperlink. After creating your account and logging in, create a model new internet web page by deciding on Add an online web page and gives it a fame. For this tutorial, we’ll use a Desk
database. Although it’s not the proper database to assemble a quiz, it’s the closest we’ll acquire with Notion!
Inserting information into the desk
Now that we now have our empty Desk
, we’ve to work out learn how to accurately insert our information into it.
Our meant schema for our quiz is the subsequent:
{
"1": {
"Question": "Which is the purpose of JavaScript?",
"Options": {
"1": "To sort HTML Pages",
"2": "In order so as to add interactivity to HTML pages",
"3": "To hold out server side scripting operations"
},
"Acceptable": "In order so as to add interactivy to HTML pages"
},
"2": {
"Question": "To insert a JavaScript into an HTML internet web page, which tag is used?",
"Options": {
"1": ",
"2": "" ,
"3": "
},
"Acceptable": "
},
"3": {
"Question": "Which of the subsequent is acceptable to jot down “Hello there World” on the web internet web page?",
"Options": {
"1": "print('Hello there World')",
"2": "doc.write('Hello there World')",
"3": "response.write('Hello there World')"
},
"Acceptable": "doc.write('Hello there World')"
}
}
Notion isn’t truly constructed for such a database, so we’ve to get creative with it! 💡 So our Question
column will in all probability be solely a Title
(which works good) and our Acceptable
column will in all probability be of kind Textual content material
(which moreover works as meant). For our numerous decisions, though, we’ve to do one factor completely completely different! My technique to it is to utilize the Multi-select
topic kind so I can write numerous outcomes into the similar cell (we’ll see down the path what the information retrieved from this seems like). So our Desk
must look like the subsequent image because the tip finish outcome.
Creating our Notion API integration
Now we’ve to go to the Notion API site to create our integration. Press the My Integrations button on the very best correct nook after which click on on on Create new integration. Now we have to fill in our title and make certain you choose our Associated workspace (will in all probability be chosen by default nonetheless make certain that of this). If we press Submit, we’ll be directed to a model new internet web page with an Inside Integration Token (we’ll use this in our code) and with two selection containers for the place we have to use our integration. We don’t must do one thing on this internet web page aside from copy our token and press Save changes.
Now we return to our Notion workspace. In our newly created Notion database, we have to press Share, then Invite. We’ll then have the power to pick out our newly created integration. If we choose it and press Invite, our Notion setup is completed. Properly carried out! 🙌
The Code Setup
For our code setup, we’ll use a Notion template repository (which we’ll then use on any of our Notion API duties!) that already has the preliminary code required to work with Notion’s API. This repo is likely to be found proper right here, so make certain you fork it and clone it to accompany our mission! In case you’re taken with what all the bits of code do, please talk about with “Getting Started with the Notion API and Its JavaScript SDK”, since we go into quite a few component for every little little bit of code (the repo moreover has a README
that must make clear what it does!).
Placing in dependencies
After forking and cloning our Notion template repo, our first step is to place in our dependencies, so make certain that to run yarn
or npm arrange
on our terminal contained within the folder. On this mission we now have three dependencies: the @notionhq/shopper, dotenv and Categorical. We’ll use dotenv to deal with our variables and preserve them protected (such as a result of the one we observed on our integration) and Categorical to create our once more end and server for our software program.
To deal with our variables with dotenv, create a .env
file on the foundation of our mission and paste the subsequent there:
NOTION_API_KEY = YOUR_TOKEN_HERE
NOTION_API_DATABASE = YOUR_DATABASE_ID_HERE
Our NOTION_API_KEY
is the essential factor that we are going to uncover in our Integrations, and our NOTION_API_DATABASE
is likely to be found by going to the created Notion internet web page and looking on the browser’s URL bar. It comes after your workspace title (if we now have one) and the slash (myworkspace/
) and sooner than the question mark (?
). The ID is 32 characters prolonged, containing numbers and letters:
https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...
|--------- Database ID --------|
If we’re fearful about having Notion’s API keys on a file inside our repo, uncover that on our .gitignore
we now have the .env
file there; the .gitignore
permits us to position completely completely different file/folder names inside, and that signifies that these recordsdata/folders obtained’t be added to our repo as soon as we push our code.
Now that we now have our preliminary repository and we now have the required credentials from Notion, we’ll start engaged on our quiz!
Grabbing the JavaScript Quiz Data
We should all the time first confirm if we’re effectively associated 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 all the time see one factor like the subsequent screenshot on our terminal.
Seeing this on our terminal signifies that we’re accurately associated to our Notion database and that we are going to 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.outcomes.map((internet web page) => {
return {
id: internet web page.id,
question: internet web page.properties.Question.title[0].plain_text,
options: internet web page.properties.Options.multi_select,
acceptable: internet web page.properties.Acceptable.rich_text[0].plain_text,
};
});
return responseResults;
};
With responseResults
, we’re mapping over our outcomes
(matching the entries in our database) and we’re mapping the paths for numerous properties to names that we’re deciding on (on this case, id
, question
, options
and acceptable
). Uncover how explicit the merchandise path is. That’s by design, which signifies that, when rising and coping with your private database, it is best to continually look at the returned properties until you uncover the information you’re looking for (it’s truly a matter of trial and error).
With this new code, we’re nearly making a reputation to our API and deciding on the properties that we have to use in our code, which signifies that we’re capable of work with them on our interface!
Displaying Our Data inside the Browser
Let’s start by dealing with our HTML and CSS, since they’re pretty direct! We obtained’t do any changes on our HTML from the template, and on our sort.css
we’ll paste the subsequent code beneath the current one:
.questionContainer {
padding: 30px;
present: flex;
flex-direction: column;
justify-content: coronary heart;
align-items: coronary heart;
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%;
present: flex;
flex-direction: column;
gap: 20px;
}
.answerOption {
padding: 20px;
margin: 0px;
font-size: 18px;
text-align: coronary heart;
cursor: pointer;
border: 1px secure rgb(42, 43, 44);
border-radius: 40px;
}
We obtained’t see these styling changes however, nonetheless we’ll now give consideration to the efficiency, which is the additional important part of this tutorial.
If we now go to the main.js
file contained within the public
folder, we’ll see that we’re already grabbing our data from our once more end with the getDataFromBackend
function. In case you’re confused by this, “Getting Started with the Notion API and Its JavaScript SDK” has a lengthier rationalization for it, nonetheless primarily on our server.js
we created a route that can get our database, and proper right here on getDataFromBackend
we’re making a fetch
to that exact same route, which might seize our data for us.
Uncover how inside addData
we already have const data = await getDataFromBackend();
. Due to this we’re ready to start working with our data, and we’ll actually confirm this! log
this data
variable and we should all the time see, on our console, an array of our database entries.
Displaying our data on the show display screen
Now that everyone knows what our returned data seems like, we’ve to think about how we actually have to current it on the show display screen. My idea for it is to have a card for each question, with the completely completely different options inside, and when the buyer presses the correct reply, the reply’s background must flip inexperienced; if it’s fallacious, it must flip pink.
Let’s start by making a
forEach
loop, allowing us to create the
and add some programs to it.
So inside our addData
function we'll try this:
const addData = async () => {
const data = await getDataFromBackend();
data.forEach((price, index) => {
const div = doc.createElement('div');
div.classList.add('questionContainer');
container.append(div);
});
};
But it surely absolutely nonetheless feels a bit empty, so let’s append a header for each card like this:
const addData = async () => {
const data = await getDataFromBackend();
data.forEach((price, index) => {
const div = doc.createElement('div');
div.classList.add('questionContainer');
const numberElement = doc.createElement('p');
numberElement.classList.add('numberElement');
numberElement.innerHTML = `Question ${index + 1}`;
div.appendChild(numberElement);
container.append(div);
});
};
Proper right here we’re making a
and giving it a class, and we’re working with index + 1
, on account of arrays in JavaScript are zero-based and we don’t have to see Question 0, since that doesn’t make sense! If we now start our app, we should all the time see one factor like what’s pictured beneath.
The satisfying half: new capabilities for rendering questions and options
Now for the satisfying half! We might do all of our logic inside addData
, nonetheless that will get too messy, so we’re going to create new capabilities to render our question and options.
Let’s start with the question, and let’s do some work on our addData
function that obtained’t nonetheless translate into quite a bit:
const addData = async () => {
const data = await getDataFromBackend();
data.forEach((price, index) => {
const div = doc.createElement('div');
div.classList.add('questionContainer');
const numberElement = doc.createElement('p');
numberElement.classList.add('numberElement');
numberElement.innerHTML = `Question ${index + 1}`;
div.appendChild(numberElement);
const question = createQuestion(price.question);
div.appendChild(question);
container.append(div);
});
};
The code we merely added is much like that for the numberElement
, nonetheless proper right here we’re assigning a function to a variable and appending that variable. Uncover moreover that we’re passing price.question
into our createQuestion
, on account of we have to work with and render the question, in any case. It may all make sense in a short time — don’t worry!
Now, outdoor and above addData
, let’s create this new createQuestion
function. Inside it, we nearly want the similar logic that we added for our numberElement
: create a part, give it a class, and add some content material materials to it. Proper right here we’ll be using not innerHTML
nonetheless createTextNode
: since our questions are related to code, if we've been to utilize innerHTML
in a single factor like textual content material
, it is going to actually render the phrase textual content material
nonetheless with daring instead of the entire syntax (you'll see an occasion proper right here). Our remaining createQuestion
will look like this:
const createQuestion = (question) => {
const questionElement = doc.createElement('h3');
questionElement.classList.add('question');
const questionNode = doc.createTextNode(question);
questionElement.appendChild(questionNode);
return questionElement;
};
If we now run yarn start
, our browser ought to appear as confirmed beneath.
Now our setup for our options is simply in regards to the similar. Let’s first do the similar issue that we did with createQuestion
inside addData
:
const addData = async () => {
const data = await getDataFromBackend();
data.forEach((price, index) => {
const div = doc.createElement('div');
div.classList.add('questionContainer');
const numberElement = doc.createElement('p');
numberElement.classList.add('numberElement');
numberElement.innerHTML = `Question ${index + 1}`;
div.appendChild(numberElement);
const question = createQuestion(price.question);
div.appendChild(question);
const options = createAnswers(price);
div.appendChild(options);
container.append(div);
});
};
And now our preliminary seek for createAnswers
will look like this:
const createAnswers = (price) => {
const answersDiv = doc.createElement('div');
answersDiv.classList.add('answersDiv');
return answersDiv;
};
Uncover how we’re doing const options = createAnswers(price);
. We'll’t merely cross price.options
to our function, on account of we moreover need the price.acceptable
. We might instead of this cross two arguments to our function: one for the array of options and the other one may be the acceptable one.
Rendering an array of options
We now have an array of options, and we've to render all of them, so we would like a loop to endure all of them. The tactic inside this loop will nearly be the similar as for all the other elements, so we must be professionals at this degree at rendering elements on the DOM:
const createAnswers = (price) => {
const answersDiv = doc.createElement('div');
answersDiv.classList.add('answersDiv');
for (let i = 0; i price.options.measurement; i++) {
const answerElement = doc.createElement('p');
answerElement.classList.add('answerOption');
const answerNode = doc.createTextNode(price.options[i].title);
answerElement.appendChild(answerNode);
answersDiv.appendChild(answerElement);
}
return answersDiv;
};
With this code, we’re looping over our array
, making a part, giving it a class and using createTextNode
to render our options. (Funnily adequate, if we had used innerHTML
proper right here, the options with
wouldn’t render 😄.) Then we’re merely appending this answerNode
to our
and appending this one to our
! If we run yarn start
, we’ll now see our complete quiz! Woo! 🚀
Interacting with the Options
Hmm… Nonetheless we'll’t truly work along with the options, and it’s unlikely a quiz if we don’t get to know if we obtained the reply correct or fallacious, correct? We should all the time restore that!
Everyone knows that we have to click on on on each reply and know if it’s correct or fallacious, so we'll start by together with an event listener to it like so:
const createAnswers = (price) => {
const answersDiv = doc.createElement('div');
answersDiv.classList.add('answersDiv');
for (let i = 0; i price.options.measurement; i++) {
const answerElement = doc.createElement('p');
answerElement.classList.add('answerOption');
const answerNode = doc.createTextNode(price.options[i].title);
answerElement.addEventListener('click on on', () => {});
answerElement.appendChild(answerNode);
answersDiv.appendChild(answerElement);
}
return answersDiv;
};
Don't forget that we did createAnswers(price)
, so we might get the price.acceptable
? Now it’s its time to shine! After we click on on on an answer, there are two attainable outcomes: the buyer chooses the reply that’s equal to the fitting reply, or the buyer chooses an answer that’s not equal to the fitting reply. To deal with these attainable outcomes, we’re going to utilize an if assertion, and one of the best ways we’re going to point to our clients that they obtained an answer correct or fallacious is through a change of the background-color
of the reply. So our logic will look like this:
const createAnswers = (price) => {
const answersDiv = doc.createElement('div');
answersDiv.classList.add('answersDiv');
for (let i = 0; i price.options.measurement; i++) {
const answerElement = doc.createElement('p');
answerElement.classList.add('answerOption');
const answerNode = doc.createTextNode(price.options[i].title);
answerElement.addEventListener('click on on', () => {
answerElement.sort.shade = 'white';
if (price.options[i].title !== price.acceptable) {
answerElement.sort.backgroundColor = '#f55142';
} else {
answerElement.sort.backgroundColor = '#6dbf39';
}
});
answerElement.appendChild(answerNode);
answersDiv.appendChild(answerElement);
}
return answersDiv;
};
So with each click on on, we’re altering the textual content material shade to white, after which we’re checking if the title
property of each reply is identical as price.acceptable
(that's clearly not best possible, and an index may be somewhat quite a bit larger, nonetheless we did our best with Notion’s databases!). If it’s not, we modify its shade to pink and whether or not it's, we modify it to inexperienced!
And that’s our quiz carried out! 🚀 Isn’t it unbelievable?
Notion JavaScript Quiz Wrapup
On this tutorial, we’ve explored quite a few functionalities provided by Notion’s API and, truly, it’s on a regular basis very thrilling to see how quite a bit you'll be able to do with such a simple instrument!
I hope this put up ends up inspiring you to find the Notion API and to assemble your private quizzes and completely different rad stuff with Notion!
Should you want to quickly check out this Notion mission, you'll clone it from our GitHub repo.
Steadily Requested Questions (FAQs) about Notion API and JavaScript Quiz
How can I exploit the Notion API to create a JavaScript Quiz?
The Notion API allows you to work along with Notion’s database and create dynamic functions like a JavaScript Quiz. To do this, it is worthwhile to first create a Notion account and generate an API key. Then, you need to make the most of this key to make requests to the Notion API and fetch data out of your Notion workspace. It's possible you'll then use this data to create inquiries to your JavaScript Quiz. The API provides quite a few flexibility, allowing you to customize the quiz in keeping with your desires.
What are some great benefits of using the Notion API for making a JavaScript Quiz?
The Notion API provides an a variety of benefits for making a JavaScript Quiz. Firstly, it allows you to retailer and deal with your quiz data in a structured and organized methodology. Secondly, it provides quite a few flexibility, allowing you to customize the quiz in keeping with your desires. Lastly, it allows you to automate the tactic of creating and updating the quiz, saving you quite a few time and effort.
Can I exploit the Notion API to create quizzes in several programming languages?
Certain, you need to make the most of the Notion API to create quizzes in several programming languages. The API is language-agnostic, which means it could be used with any programming language that helps HTTP requests. This incorporates commonplace languages like Python, Java, and Ruby, amongst others.
How secure is the Notion API?
The Notion API makes use of secure HTTPS connections for all requests, making sure that your data is encrypted and secure. Furthermore, it requires an API key for authentication, making sure that solely accepted clients can entry your data.
Can I exploit the Notion API to create differing types of functions?
Certain, the Notion API should not be restricted to creating quizzes. That you must use it to create quite a lot of functions, from mission administration devices to personal note-taking apps. The API provides quite a few flexibility, allowing you to customize your software program in keeping with your desires.
How can I get started with the Notion API?
To get started with the Notion API, it is worthwhile to first create a Notion account and generate an API key. Then, you need to make the most of this key to make requests to the Notion API and fetch data out of your Notion workspace. Yow will uncover detailed documentation on learn how to make use of the API on the Notion site.
What are the restrictions of the Notion API?
Whereas the Notion API provides quite a few flexibility, it does have some limitations. As an example, it would not assist real-time updates, which means it is worthwhile to manually refresh the information. Furthermore, it has charge limits to cease abuse, which might limit the number of requests you might make in a certain interval.
Can I exploit the Notion API for enterprise features?
Certain, you need to make the most of the Notion API for enterprise features. Nonetheless, it is worthwhile to regulate to Notion’s phrases of service and guarantee that your use of the API would not violate any authorized pointers or guidelines.
How can I troubleshoot factors with the Notion API?
In case you encounter factors with the Notion API, you'll talk about with the API documentation for troubleshooting concepts. Furthermore, you'll attain out to Notion’s assist crew for assist.
Can I mix the Notion API with completely different APIs?
Certain, you'll mix the Notion API with completely different APIs to create further difficult functions. As an example, you may mix it with a local weather API to create a personalised local weather dashboard in your Notion workspace.
Hi there, I'm Rui and I'm from Portugal. I'm a self-taught front-end developer with a Grasp's Diploma in Psychology. After ending my course I noticed that I wanted to go away my mark on the world and the dev world was the plain different as a result of it on a regular basis fascinated me!
NotionNotion API