Notion is a note-taking software that I recently started using. It is very flexible and easy to use.
It can be a used as a writing repository, task management tool, a workout calendar, a database, and so much more. I manage my long term, short term goals, blog ideas scratch pad within notion.
Notion provides APIs which are good mix of REST and GraphQL. We will use these APIs, to fetch the pages and databases from notion. Because of this we can use notion as a CMS for any website.
Data fetched from the APIs will be added at built time to our demo website.
To showcase a simple use case. Let's consider there is a hiring manager at small startup, And he/she manages the list of candidates in notion boards. Board has sections ex. shortlisted, in process, hired candidates. Hiring manager moves the card of each candidate within respective section.
Names of the selected members should appear in team section on company website. I have created a one page website for this.
Reference:
https://tailwindcomponents.com/component/team-section-2
I modified this example to use data from a json file. Metadata of each team member like name, profilePic, jobtitle is loaded and shown on website.
import team from '../cms/team.json'
export default {
name: 'IndexPage',
data: () => ({
team: team
})
}
Netlify provides easy CICD integration with github. Integrate netlify with your repo and Specify your build command and build output directory.
Follow the below given video to setup CICD for your github repo.
Referance
https://www.youtube.com/watch?v=4h8B080Mv4U
Create a board in notion.
Add few entries to it with relevant data, for this use case I have added name, jobTitle, profilePic, rank etc.
Keep entries in each category. (Later we can move these items to done, that would publish them on website)
Note down the database ID of this board. This will be used in API to query data.
https://www.notion.so/{DB_ID}?v={VIEW_ID}
Names from the Done column should appear on website
This would give you a API key to use within your queries.
Make sure not to commit this to github (or any other SCM).
Navigate to Notion developer --> my-integrations
This makes your content available to the integration, can be accessed using API now.
NOTION_API_KEY
and NOTION_DB_ID
in env variables.Navigate to your site --> build and deploy --> environment
Below script fetches data from notion and writes to a json file.
var axios = require('axios')
var fs = require('fs')
/* Filter entries with status `Done`, i.e.
fetch only team members who are onboarded in company.
Other statuses can be for candidates
who are in process of being hired or shortlisted
*/
var data = JSON.stringify({
sorts: [
{
property: 'Status',
direction: 'ascending'
}
],
filter: {
property: 'Status',
rich_text: {
equals: 'Done'
}
}
})
const NOTION_API_KEY = process.env.NOTION_API_KEY
const NOTION_DB_ID = process.env.NOTION_DB_ID
var config = {
method: 'post',
url: `https://api.notion.com/v1/databases/${NOTION_DB_ID}/query`,
headers: {
Authorization: `Bearer ${NOTION_API_KEY}`,
'Notion-Version': '2022-02-22',
'Content-Type': 'application/json'
},
data: data
}
/* Make API call to fetch data, write to a json file.
This is the file that contains data of team
members shown on the website.*/
axios(config)
.then(function(response) {
let team = response.data.results.map(f => ({
name: f.properties.Name.title[0].text.content,
jobTitle: f.properties.jobTitle.rich_text[0].text.content,
profilePic: f.properties.profilePic.rich_text[0].text.content,
rank: f.properties.rank.rich_text[0].text.content
}))
team.sort((a, b) => a.rank - b.rank)
fs.writeFileSync('./cms/team.json', JSON.stringify(team, null, 2), 'utf-8')
console.log('Team data populated')
})
.catch(function(error) {
console.log(error)
})
Done
column in notion.clear cache and deploy site
option).Website has been deployed with new data fetched at build time.
Full code for this can be found on github
This demo shows example to inject data at runtime, As this data is changed less frequently.
For use cases like product page, data will be changed rapidly .
You can use notion npm library to fetch this data while page loads in browser.