🧩 Travsersy Media - The New Notion API | Node.js Video Schedule Project (May 19, 2021)
Link: https://www.youtube.com/watch?v=9JdP-S3crt8&ab_channel=TraversyMedia
Description
In this video, we will create a Notion calendar database and use the API and SDK/client to fetch the data and display it on a web page
Code: https://github.com/bradtraversy/notion-video-schedule
Notion Developers/API Website: https://developers.notion.com/
Notion JS SDK: https://github.com/makenotion/notion-...
Timestamps:
- 0:00 - Intro
- 1:55 - Add Video Data in Notion
- 4:25 - Explore API & Create Integration
- 7:03 - Using the SDK/Client
- 11:47 - Fetch Video Data & Construct Object
- 21:22 - Create Endpoint with Express
- 23:50 - Creating the Frontend
- TVS-NodeJSNotionAPI-VideoScheduleProject-20210519
- 0 - Notion Api Docs
- 155 Add Video Data in Notion
- 425 Explore API & Create Integration
- 703 Using the SDK / Client
- 1147 Fetch Video Data and Construct Object
- 2122 Create Endpoint with ExpressJS
- 2350 Creating the Frontend
Start building with the Notion API
- Add a new Calendar Page
- Click on a random day on calendar
- Fields:
- Title (default) ex: Video 1
- Date start (default)
- Description - text field ex: Video 1
Start building with the Notion API
Name: TVS-NodeJSNotionAPI-VideoScheduleProject-20210519
Logo: N/A
Integration Type: Internal
Authorization: Bearer Token, then paste the secret integ token
Now if you try this endpoint: https://api.notion.com/v1/databases
its now at status 200 ! however the results in the data received is still empty.
Go back to the calendar page you just a while ago then find share
select the integration we just made with permission: edit
now if you try sending the request again, you shall see the results data
mkdir TVS-NodeJSNotionAPI-VideoScheduleProject-20210519
cd TVS-NodeJSNotionAPI-VideoScheduleProject-20210519
npm init -y
npm i dotenv express nodemon
- Simple and Easy to use client for Notion API
npm i @notionhq/client
{
"name": "TVS-NodeJSNotionAPI-VideoScheduleProject-20210519",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index",
"dev": "nodemon index"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@notionhq/client": "^0.1.3",
"dotenv": "^9.0.2",
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}
create new index.js
const dotenv = require('dotenv').config()
create new .env file
NOTION_TOKEN="" // you get this from the integ secret we saw a while ago
NOTION_DATABASE_ID="3af51cce-d263-45f5-8ee0-14f34deb983b" // when you tried the listing of databases a while ago, you might have seen the id
index.js
const dotenv = require('dotenv').config();
const { Client } = require('@notionhq/client');
//Init Client
const notion = new Client({
auth: process.env.NOTION_TOKEN
})
const listDatabases = async () => {
const res = await notion.databases.list()
console.log(res);
}
listDatabases()
and after saving if you run npm run dev with nodemon, you should see the log on console. you find the id
but yeah you can delete the listDatabases now since that was just for demo hehe
Query a Database API
Start building with the Notion API
index.js
const dotenv = require('dotenv').config();
const { Client } = require('@notionhq/client');
//Init Client
const notion = new Client({
auth: process.env.NOTION_TOKEN
})
// START: Getting Id using code instead of http client @e1147
// const listDatabases = async () => {
// const res = await notion.databases.list()
// console.log(res);
// }
// listDatabases()
// END: Getting Id using code instead of http client @e1147
const notionDatabaseId = process.env.NOTION_DATABASE_ID;
const getVideos = async () => {
const payload = {
path: `databases/${notionDatabaseId}/query`,
method: "POST"
}
const { results } = await notion.request(payload)
console.log(results)
}
getVideos()
const getVideos = async () => {
const payload = {
path: `databases/${notionDatabaseId}/query`,
method: "POST"
}
const { results } = await notion.request(payload)
const videos = results.map(result => {
console.log(result.properties)
})
}
getVideos()
index.js
const dotenv = require('dotenv').config();
const { Client } = require('@notionhq/client');
//Init Client
const notion = new Client({
auth: process.env.NOTION_TOKEN
})
// START: Getting Id using code instead of http client @e1147
// const listDatabases = async () => {
// const res = await notion.databases.list()
// console.log(res);
// }
// listDatabases()
// END: Getting Id using code instead of http client @e1147
const notionDatabaseId = process.env.NOTION_DATABASE_ID;
/**
* @name getVideos()
* @description get the videos from the given database
*/
const getVideos = async () => {
const payload = {
path: `databases/${notionDatabaseId}/query`,
method: "POST"
}
const { results } = await notion.request(payload)
const videos = results.map(result => {
// Knowing each result object's properties
// console.log(result.properties)
return {
id: result.id,
name: result.properties.Name.title[0].text.content,
dateStart: result.properties.Date.date.start,
description: result.properties.Description.rich_text[0].text.content
}
})
return videos
}
(async () => {
const nVideos = await getVideos()
console.log(nVideos)
})()
change getVideos to a normal async function being exported
const dotenv = require('dotenv').config();
const { Client } = require('@notionhq/client');
//Init Client
const notion = new Client({
auth: process.env.NOTION_TOKEN
})
// START: Getting Id using code instead of http client @e1147
// const listDatabases = async () => {
// const res = await notion.databases.list()
// console.log(res);
// }
// listDatabases()
// END: Getting Id using code instead of http client @e1147
const notionDatabaseId = process.env.NOTION_DATABASE_ID;
/**
* @name getVideos()
* @description get the videos from the given database
*/
module.exports = async function getVideos() {
const payload = {
path: `databases/${notionDatabaseId}/query`,
method: "POST"
}
const { results } = await notion.request(payload)
const videos = results.map(result => {
// Knowing each result object's properties
// console.log(result.properties)
return {
id: result.id,
name: result.properties.Name.title[0].text.content,
dateStart: result.properties.Date.date.start,
description: result.properties.Description.rich_text[0].text.content
}
})
return videos
}
const getVideos = require('./services/notion');
(async () => {
const nVideos = await getVideos()
console.log(nVideos)
})()
index.js
const express = require('express');
const getVideos = require('./services/notion');
const EXPRESS = express()
// START: ENDPOINTS
/**
* @name "/videos" endpoint
* @description http://localhost:5000/videos
*/
EXPRESS.get('/videos', async (req, res) => {
const data = await getVideos()
res.json(data)
})
// END: ENDPOINTS
const PORT = process.env.PORT || 5000
EXPRESS.listen(PORT, console.log(`Server started on port ${PORT}`))
// (async () => {
// const nVideos = await getVideos()
// console.log(nVideos)
// })()
Try Performing a get request on http://localhost:5000/videos
it shud work :>>
index.js
const express = require('express');
const getVideos = require('./services/notion');
const EXPRESS = express()
// START: STATICS
EXPRESS.use(express.static('frontend'))
// END: STATICS
// START: ENDPOINTS
/**
* @name "/videos" endpoint
* @description http://localhost:5000/videos
*/
EXPRESS.get('/videos', async (req, res) => {
const data = await getVideos()
res.json(data)
})
// END: ENDPOINTS
const PORT = process.env.PORT || 5000
EXPRESS.listen(PORT, console.log(`Server started on port ${PORT}`))
// (async () => {
// const nVideos = await getVideos()
// console.log(nVideos)
// })()
create frontend/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>TVS-NodeJSNotionAPI-VideoScheduleProject-20210519</h1>
<!-- START: DISPLAY VIDEOS -->
<div id="videos"></div>
<!-- END: DISPLAY VIDEOS -->
<script src="main.js"></script>
</body>
</html>
create new frontend/main.js
const displayVideosElement = document.querySelector('#videos');
/**
* @name getVideosFromBackend()
* @description get video data from server backend
* @returns data
*/
const getVideosFromBackend = async () => {
const res = await fetch('http://localhost:5000/videos');
const data = await res.json();
return data
}
/**
* @name addVideosToDom()
* @description brings the data to a template and display at dom
*/
const addVideosToDom = async () => {
const videos = await getVideosFromBackend()
videos.map(video => {
const div = document.createElement('div')
div.innerHTML = `
<h3>${video.name}</h3>
<ul>
<li><strong>Release Date:</strong> ${video.date}</li>
<li><strong>Description:</strong> ${video.description}</li>
</ul>
`
displayVideosElement.appendChild(div)
})
}
addVideosToDom()