Using CloudFlare with Notion

With my website (which uses Notion as its CMS), I ran into a problem caused by a quirk of Notion’s API. When you upload an image to Notion and then fetch that image as part of a page payload, the image URL is an S3 bucket key that expires after an hour. Which is fine for most use cases but is problematic when pre-rendering a site - like I do for

To solve the problem, I use R2 as a repository for static imagery. When I fetch an image from Notion and it is has an expiring URL, I will check to see if the file is already in R2 and, if not, upload it there. I then return the URL from that location when rendering.

graph TD
  BuildPage --Image Found--> QueryR2ForImage[Query R2 for Image]
	QueryR2ForImage --File Exists--> BuildR2URL[Build R2 Image URL]
  QueryR2ForImage --File Does Not Exist --> UploadToR2[Upload to R2]
	UploadToR2 --Return Url To Renderer --> BuildR2URL
  BuildR2URL --Return Url To Renderer --> RenderWithNewStaticUrl[Render Image with Static URL]

Checking for the image ahead of time is important to ensure we don’t keep uploading the same image to R2 repeatedly.

Different images with the same filename are not a problem here because the R2 file key uses the block ID as a prefix ensuring there are no collisions. The one problem I haven’t solved yet is what happens when the same block ID gets an updated image with the same name but different content. I don’t currently have a way to know to update the image.

As a side-note, I use custom domains for my R2 bucket which makes nicer looking static file URLs.
And as a side-side-not, R2’s UI for building buckets is so much easier to use than AWS’s.