It started with a steno pad in 1998. It was my first “office” job, and I needed a way to keep track of my tasks. I built a process of writing down my tasks as they came in, updating them as I worked on them, and crossing them off when they were done. It was a great system that made me feel productive and in control.
My tasks were simpler then. They all had definitive steps and a clear end. Once I started working as an engineer, my tasks became more complex. While I had JIRA tickets, GitHub issues, and other tools to track my work, I still needed a way that made sense to me and could include those tasks that weren’t associated with code.
I found a good groove using OneNote for about 8 years but was never satisfied. As I started to focus more on content creation & scheduling, I needed something different. I went through a slew of tools like Notion & Obsidian, but nothing felt right. Then a friend took an hour or so to show me their setup in Notion and the light finally clicked. I’ve been hooked ever since and now I manage everything in Notion.
As I was building a new version of my website, I knew I wanted to include my content schedule. All that data already existed in Notion, and I hoped to avoid duplicating it in an Astro content collection. So… I did what any lazy developer would do. I built a way to pull that data from Notion into my Astro site.
permalinkGetting Started with the Notion API
I’m not going to focus on how to set up a Notion database and populate it. I’ll assume you’ve already got that part done. The Notion API is documented well, but to give you a quick shortcut, you’ll need an API “integration token” and the ID of your database.
permalinkGet a Notion Integration Token
Within the Notion app, click on the “Settings & Members” button in the top right corner. Then click on the “Connections” section under “Workspace.” On the connections screen, click the link at the bottom that says “Develop or manage integrations”. This will take you to the integrations page.
On the “My integrations” page, click the ”+ New integration” button. This will open the “Create a New Integration” form. Choose the Notion workspace that contains your database and give your integration a name. Then click the “Submit” button.
Once you’ve created your integration, you’ll be taken to the “Secrets” tab of your new integration. Press the “Show” button to reveal and copy your “Internal Integration Secret”. This is your integration token and you’ll need it later to authenticate with the Notion API.
permalinkGet the Notion Database ID
Getting the ID of your Notion database is a little more involved. You’ll need to open the Notion app in your browser and navigate to the database you want to use.
The ID of the database is the first alphanumeric string after your Notion workspace name (highlighted in the image above). Copy that ID and save it for the next step.
permalinkConfiguring Your Astro Project
Now that we have our database ID and our integration token, we need to set up our project. First, we’ll install the Notion JavaScript SDK.
In the code snippet above, I install the SDK as a development dependency. This is because my site is built statically and I don’t need the SDK in my production build. If you’re building a server-side rendered site, you’ll want to install it without that flag.
Next, we’ll need to create a .env
file at the root of our project (if one
doesn’t already exist.) Then add the following to the .env
file:
Astro will pull these in auto-magically and we’ll be able to use them in our code later.
permalinkConnecting to the Notion API
Now that our environment is set up, let’s write some code. Remember that this code is specific to my Notion database and schema so it will need to be modified to fit the schema of your Notion database.
We’ll start by creating a notion.ts
file in the src/scripts
directory. This
file will contain all the code we need to pull data from the Notion API and will
be referenced from any page or component that needs to use that data.
To start, copy the following into your notion.ts
file:
The first thing we do is import the Client
class from the Notion SDK. Then we
define a type that will represent our Notion data for the Astro site. In this
case, I’m using a ScheduledEvent
type that contains a date, title,
description, and type. If you’re using TypeScript, you’ll want to modify this
to match the type definition of the object you’ll be passing around your Astro
project.
Finally, we define an async function called getEvents
that returns a promise
of an array of ScheduledEvent
objects. This is the method we’ll use throughout
our app’s pages & components to pull data from Notion. Let’s fill in the
body of that function next. Add the following within the getEvents
function:
This creates a new instance of the Notion client and passes in the integration
token we added to our .env
file earlier.
permalinkQuerying the Notion API
Now we can query the Notion API to get our data. Add the following code to the
getEvents
function:
This snippet will retrieve all the pages from our Notion database. However,
it’s unlikely that you’d want to pull back all records. Be sure to add a filter
to narrow your request to just the pages you want. You can find out more about
the filter
parameter of the query
function in the
Notion API documentation.
As an example, the filter for my implementation is below:
permalinkTransforming the Notion API Response
The response from the Notion API is a bit verbose, and by “a bit” I mean “a lot”. We’ll need to transform the response into something more manageable. But like the filters above, this code will be very dependent on your Notion schema and the type definition you want to use in your Astro project.
Here’s the code I use to transform the response from the Notion API:
In my case, I’m only ever going to want the next 5 events, so I use the splice
function to limit the number of events returned. That may be different for your
use case.
Finally, we return the array of events from the getEvents
function making the
full function look like this:
permalinkUsing Notion Data in Your Astro Component
Now that we have our data, we can use it in a page or component. My use case
lists upcoming events on my homepage, so I created a Schedule.astro
component.
Then I imported the getEvents
function from the notion.ts
file and wrote
the HTML to display it.
Whether your use case is similar or not, the process is the same. Accessing your Notion data is fairly straightforward and can save you from duplicating content in your Astro project.