Skip to content

A super simple way to publish personal pages / blogs using Notion as CMS and Cloudflare Workers as publisher

License

Notifications You must be signed in to change notification settings

partham16/notion-cloudflare

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Notion + Cloudflare as a blog service

A super simple way to publish personal pages / blogs using Notion as CMS and Cloudflare Workers as publisher

Check out Demo website

TL;DR

Tools

  • Notion

    Notion is great tool that lets you manage your workspace - and that's what we are going to use as our CMS i.e. content management

    Different options available at Notion notion
  • Cloudflare Workers

    Workers is going to be our execution environment where we are goint to run worker.js code and serve out our Notion content on a subdomain provided by Cloudflare (subdomain.domain.workers.dev) or a personalized domain of our choosing


Steps

Prerequisites: Set up your Notion page (make it public) and register at Cloudflare

  • Let's look at our goal first : We want to serve the Notion page we created when people to come to our website or the .workers.dev subdomain

  • So, let's look into the documentation for serving another site:

    addEventListener("fetch", event => {
    return event.respondWith(
      fetch("https://youtube.com")
    )
    })

    Anyone who comes to our site, should be served the YouTube home page!

    Let's see if that works?

    Look ma, I built youtube!

    Interestingly, it's being served out of Singapore, because that's where my closest Cloudflare server is.

  • Ok, that works! But, that means we are done, right?

    We can just replace youtube.com with our Notion public page, and voila!

  • Nah, Unfortunately that doesn't work!

    (or fortunately rather, otherwise there is not much point in creating this whole post!)

    So, if we do a view-source of Notion home page, we see:

    <script type="text/javascript" src="/app-1ae08b9f66e81e1cf0c9.js"></script></body></html>

    Yeah, that's a relative reference - and when we serve out our blog, it's not gonna find it!

  • But, I know! Let's just replace these with absolute references!

    We are already using javascript, a little bit of regular expression magic and we are done, right?

    const regex = /(?<=(href|src)=\")/gm;
    const subst = `https://www.notion.so`;
    const new_result = results.replace(regex, subst);
  • Well, not exactly!

    You see, we have something called a content-security-policy violation

    It's basically just that our domain , quite justifiably, doesn't want to run a random javascript it gets from Notion!

    And security wise, that's a great thing! You wouldn't want your browser to run arbitrary javascript anyway!

  • Yeah, but, we know what we are doing!, right? Let's edit the csp:

    let csp = response.headers.get('content-security-policy')
    let new_csp = csp.replaceAll("'self'", "'self' https://www.notion.so")
    new_response.headers.set('content-security-policy',new_csp)
  • Ok, so, we have gone through quite a many hoops. At least, now tell me that we are done?

    Well, not exactly! But, we are close!

    But, first, the hurdle we face : we are now greeted with a Mismatch between origin and baseUrl (dev). pop-up!

    And it's actually a little but dense function in the app-1ae08b9f66e81e1cf0c9.js we saw before:

    didMount(){const{device:e}=this.environment;"external"===Object(m.l)  ({url:window.location.href,isMobile:e.isMobile,baseUrl:g.default.baseURL,protocol:g.default.protocol,currentUrl:window.location.href}).name&&Ve.showDialog({message:"Mismatch between origin and baseUrl (dev).",showCancel:!1,keepFocus:!1,items:[{label:n.createElement(o.FormattedMessage,{defaultMessage:"Okay",id:"notionAppContainer.dialog.mismatchedOriginURL.okayButton.label"}),onAccept:()=>{const e=xi.j({relativeUrl:xi.f(window.location.href),baseUrl:g.default.baseURL}),t=xi.e(e);t.protocol=xi.e(window.location.href).protocol,window.location.href=xi.b(t)}}]})}
  • Sidebar:

    Frankly, intensely trying to solve this puzzle for the last 2 days has been pretty rewarding.

    I had learnt a little bit of javascript when I was starting out - but, by now I had forgotten most of it.

    So, my knowledge of js increased exponentially in these 2 days!

    But, I was ultimately trying to solve a problem, not trying to learn the language

    Yet, unfortunately it seemed like I would need to delve much deeper into this!

  • Fortunately, that's when I came across fruition

    Yes, finally we are at the TL;DR part!

    Aren't you happy that there was a TL;DR so you could just glean that and get on with your life!

    Turns out all we need to do is to download the .js files so that it can be served from our blog, and then redirect the request to the link that we want!

    Adapting the code was pretty easy (except for a minor glitch)

    All you need to do is to get the code above and edit the configuration here:

    /* Step 1: enter your domain name like fruitionsite.com */
    // either custom domain or cloudflare one
    const MY_DOMAIN = '*.workers.dev';
    
    /*
     * Step 2: enter your URL slug to page ID mapping
     * The key on the left is the slug (without the slash)
     * The value on the right is the Notion page ID
     */
    const SLUG_TO_PAGE = {
      // home page - // add 'page name': 'notion id' for more
      'demo': '0d44ee0e01944fabbb047c7bb9f885fd',
      '': '1d44ee0e01944fabbb047c7bb9f885fd'
    };

    There are a few more things you can change like the PAGE_TITLE or FONT or any CUSTOM_SCRIPT you may have.

    But, even without making those changes, you will be able to have a blog / portfolio / show-case deployed in no time!

About

A super simple way to publish personal pages / blogs using Notion as CMS and Cloudflare Workers as publisher

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published