Indie Log #1
6/16/2024
I completed the task of serving markdown data from Notion. Here's how I accomplished it. Actually, there was a lot more to do.
Setup
Cloud platform
Before starting development, it was necessary to decide on a cloud platform. I wanted a serverless app that didn't require developer maintenance. There were a few options:
- Vercel
- Cloudflare Workers
- Supabase
I selected Cloudflare Workers based on cost, scalability, and security. It also offers a range of impressive products that I needed:
- D1
- R2
- Queue
- WAF
API Server
I configured the app using Hono, Drizzle ORM, and Notion API in the Cloudflare Workers environment.
Web App
Next.js is unquestionably the best framework for creating interactive web apps. I've used Remix, Solid.js, and others, but none have been able to surpass it, mainly due to its stability and environment.
Authentication
Using SaaS for authentication is attractive. Options like Clerk and Supabase are excellent. However, as setting up the authentication environment doesn't take much time for me, I've decided to build it myself with Notion OAuth.
Things I’ve done
UX
After preparing the dev environment, I considered ways to make it more user-friendly.
- Once the publishing process is set up, users can simply use Notion and the changes will automatically apply to their website.
- Therefore, the publishing process should be straightforward.
To fulfill the first criteria, the ideal solution is to periodically fetch data from Notion for synchronization. However, to ensure users see changes quickly, data needs to be fetched at short intervals. This could potentially increase costs significantly or exceed the rate limit of the Notion API.
As a result, I've decided that users should manually sync by clicking a button. However, this solution does present a new issue: users need to open the dashboard page to sync. To address this, I've considered embedding the sync page next to the database within Notion.
For the second point, there's still much to consider and work on. Currently, I've created a npm library to generate client code with Typescript. While I'm uncertain if this is the best solution, I'm open to trying different approaches.
Sync
This is the most important part of Writeflow. When a user clicks the sync button, the sync work is queued in the background, allowing the user to do other things. Let me show you what happens in the queue consumer.
- Retrieve the Notion database
- Check
last_edited_time
to see if it's fresh - Query the database to get the pages
- Check the
last_edited_time
of the pages to see if they're fresh
If the content is not fresh, replace all the existing data in the Writeflow database with the new one. This is where the generated markdown data comes into play.
It might appear simple, but I'm currently dealing with issues related to failed synchronizations and error handling.
Markdown
Writing code to generate markdown was somewhat frustrating because Notion isn't fully compatible with it. For now, it works, but there could be many bugs.
Serving
Once the data was synchronized, serving it became a straightforward task. I defined routes for the public API. However, this process required the creation of an API Key to prevent abuse. Consequently, I developed the necessary code, incorporating some basic validation logic.
Next Step
Could the Image Optimization feature be considered urgently? It's truly necessary. Currently, I can't use any images due to the expiration of Notion image URLs. (🥲 emojis are fine, though)