Hey guys! I’ve been working on a new script that will be the main workhorse for my blog. I’ve pivoted to using Notion to write my posts. It gives me access to a nice interface for writing documents, with cool features like coloured text that something like Markdown wouldn’t. It’s also really easy to manage and view all of my posts in a nicely formatted database in any format I want. To me, it’s a much more intuitive way to write, and I don’t run into the problem where I have to search up how to do a certain thing in Markdown, like making links behave a certain way. Plus, Notion has features more further oriented towards a visual presentation, compared to Markdown’s more strictly writing-oriented design.

Parser

I wrote a custom parser to translate the JSON data I get from Notion’s API into clean HTML formatted how I like it. I think my favourite feature I’ve implemented is the embed feature, where embeds from different sites are styled differently to look the best that they can on any given device. For example, here’s an episode from one of my favourite tech podcasts:

https://open.spotify.com/embed/episode/2140ckei8GUs33tAFocqt3?theme=0&t=0

When I wrote the parser, I tried to work with a very functional programming style, where parsers for every element would be placed in different functions and would be run conditionally based on the datatype that we were processing. Elements with rich text inside of them, such as paragraphs, would be processed differently to things like images and videos. match cases were a wonderful way to implement this cleanly. I love the way I implemented the more general relations. I had a dictionary that literally just relates a Notion API datatype to an HTML tag, and a surprisingly high amount of elements were implemented just like that. For example:

{
	"heading_1": "h1",
	"heading_2": "h2",
	"heading_3": "h3",
}

Just like that, those features were implemented. We detect rich text inside of these elements and throw that text into the parseRichText function. We output perfectly formatted HTML. How wonderful! And by implementing these functions independent of datatype, it makes the system extremely modular.

Database

The database is a more recent development that I’m focusing more on now that I have finished the main part of the project, being the parser itself. The database uses the feature of the same name within the Notion interface, allowing me to create posts and assign properties to them such as visibility, cover image, etc.

I just hooked up the database to my main parsing script. This main parsing script queries the database for posts that are marked as either unlisted or public (this will be more important when I design a homepage for my blog) and selects only those to parse. It then outputs the posts into directories following the blog file structure that I always use. Of course, this will change when I move the system to dynamically generate things on Vercel through Flask.

Here’s a sample from my main parser. I don’t really care about leaking the document IDs since you’d need an API key to access them anyways, lol.

Initializing Blotion.
Fetching public and unlisted pages.
6 pages match filter!

Parsing unlisted document with ID [1eeeea7e-8196-804f-81f3-e885c498919c]
Page title: March Update
Page created at: May 08, 2025 18:24
Page last edited at: May 08, 2025 20:58
Fetching Notion article.
Parsing article contents.

Parsing public document with ID [1eeeea7e-8196-804c-bea8-e82bd0b3b9e4]
Page title: Late March Update
Page created at: May 08, 2025 18:22
Page last edited at: May 08, 2025 18:29
Fetching Notion article.
Parsing article contents.

Parsing unlisted document with ID [1eeeea7e-8196-80e0-9f21-ef304473550b]
Page title: New Drives
Page created at: May 08, 2025 18:21
Page last edited at: May 08, 2025 18:22
Fetching Notion article.
Parsing article contents.

It’s a small thing, but I would really like to show how many pages of each type fall into the filter. It’s very easy to do, but I just don’t feel like implementing it right now.

All of these features make blogging a super easy process. I honestly love this workflow, and I’ll be using it more often in the coming months as things begin to clear up soon.