stephenou / fruitionsite

Build your website with Notion for free
https://fruitionsite.com
MIT License
1.6k stars 223 forks source link

notion site not showing - blank screen #113

Open bejaeger opened 3 years ago

bejaeger commented 3 years ago

Hi all,

is anyone else facing a blank screen with their webpage? I solved the baseDomain issue and things seem to work yesterday, but now the notion page is not appearing anymore. I have the following in the console log but I'm not sure if this is related to the issue. image

Any information would be very helpful, thanks!

Madekuji commented 3 years ago

I'm also currently having this exact error as well. When checking api/v3/getPublicPageData, it gives me a Cloudflare Error 1101.

willzhaoworld commented 3 years ago

same issue

perogeremmer commented 3 years ago

If your page created when the format url still using notion.so/username, it was completely safe, checkout my website.

But, if your page was created after the format url changed into username.notion.so it was completely break or even redirected like my Links website.

That's why the reason fruitionsite website are safe.

Madekuji commented 3 years ago

If your page created when the format url still using notion.so/username, it was completely safe, checkout my website.

But, if your page was created after the format url changed into username.notion.so it was completely break or even redirected like my Links website.

That's why the reason fruitionsite website are safe.

I'm not quite sure if this is the case, since I'm trying to use older version of the code (documented in https://fruitionsite.com/update) and it still gives me the error.

Madekuji commented 3 years ago

This also looks very similar to the issue faced in #103.

perogeremmer commented 3 years ago

If your page created when the format url still using notion.so/username, it was completely safe, checkout my website. But, if your page was created after the format url changed into username.notion.so it was completely break or even redirected like my Links website. That's why the reason fruitionsite website are safe.

I'm not quite sure if this is the case, since I'm trying to use older version of the code (documented in https://fruitionsite.com/update) and it still gives me the error.

I know, that's why I told you. I have used Notion since 2020 and having many old pages. Since 2021 Notion transforms their URL into a username.notion.so it breaks my new page, then the update of fruitionsite to add some code into the condition on the worker came.

You can check my code and modify your needs. It works on an old page created but breaks if you were create a new page with a message "Continue to external site by following the link below"

  /* CONFIGURATION STARTS HERE */

  /* Step 1: enter your domain name like fruitionsite.com */
  const MY_DOMAIN = 'perogeremmer.com';
  const MY_FULL_DOMAIN = 'https://perogeremmer.com';

  /*
   * 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 = {
    '': '<your-notion-page-id>'
  };

  /* Step 3: enter your page title and description for SEO purposes */
  const PAGE_TITLE = '';
  const PAGE_DESCRIPTION = "";

  /* Step 4: enter a Google Font name, you can choose from https://fonts.google.com */
  const GOOGLE_FONT = 'Roboto';

  /* Step 5: enter any custom scripts you'd like */
  const CUSTOM_SCRIPT = ``;

  /* CONFIGURATION ENDS HERE */

  const PAGE_TO_SLUG = {};
  const slugs = [];
  const pages = [];
  Object.keys(SLUG_TO_PAGE).forEach(slug => {
    const page = SLUG_TO_PAGE[slug];
    slugs.push(slug);
    pages.push(page);
    PAGE_TO_SLUG[page] = slug;
  });

  addEventListener('fetch', event => {
    event.respondWith(fetchAndApply(event.request));
  });

  function generateSitemap() {
    let sitemap = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
    slugs.forEach(
      (slug) =>
        (sitemap +=
          '<url><loc>https://' + MY_DOMAIN + '/' + slug + '</loc></url>')
    );
    sitemap += '</urlset>';
    return sitemap;
  }

  const corsHeaders = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
  };

  function handleOptions(request) {
    if (request.headers.get('Origin') !== null &&
      request.headers.get('Access-Control-Request-Method') !== null &&
      request.headers.get('Access-Control-Request-Headers') !== null) {
      // Handle CORS pre-flight request.
      return new Response(null, {
        headers: corsHeaders
      });
    } else {
      // Handle standard OPTIONS request.
      return new Response(null, {
        headers: {
          'Allow': 'GET, HEAD, POST, PUT, OPTIONS',
        }
      });
    }
  }

  async function fetchAndApply(request) {
    if (request.method === 'OPTIONS') {
      return handleOptions(request);
    }
    let url = new URL(request.url);
    url.hostname = 'www.notion.so';
    if (url.pathname === '/robots.txt') {
      return new Response('Sitemap: https://' + MY_DOMAIN + '/sitemap.xml');
    }
    if (url.pathname === '/sitemap.xml') {
      let response = new Response(generateSitemap());
      response.headers.set('content-type', 'application/xml');
      return response;
    }
    let response;
    if (url.pathname.startsWith('/app') && url.pathname.endsWith('js')) {
      response = await fetch(url.toString());
      let body = await response.text();
      response = new Response(body.replace(/www.notion.so/g, MY_DOMAIN).replace(/notion.so/g, MY_DOMAIN), response);
      response.headers.set('Content-Type', 'application/x-javascript');
      return response;
    } else if ((url.pathname.startsWith('/api'))) {
      // Forward API
      response = await fetch(url.toString(), {
        body: request.body,
        headers: {
          'content-type': 'application/json;charset=UTF-8',
          'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
        },
        method: 'POST',
      });
      response = new Response(response.body, response);
      response.headers.set('Access-Control-Allow-Origin', '*');
      return response;
    } else if (slugs.indexOf(url.pathname.slice(1)) > -1) {
      const pageId = SLUG_TO_PAGE[url.pathname.slice(1)];
      return Response.redirect('https://' + MY_DOMAIN + '/' + pageId, 301);  
    } 
    else {
      response = await fetch(url.toString(), {
        body: request.body,
        headers: request.headers,
        method: request.method,
      });
      response = new Response(response.body, response);
      response.headers.delete('Content-Security-Policy');
      response.headers.delete('X-Content-Security-Policy');
    }

    return appendJavascript(response, SLUG_TO_PAGE);
  }

  class MetaRewriter {
    element(element) {
      if (PAGE_TITLE !== '') {
        if (element.getAttribute('property') === 'og:title'
          || element.getAttribute('name') === 'twitter:title') {
          element.setAttribute('content', PAGE_TITLE);
        }
        if (element.tagName === 'title') {
          element.setInnerContent(PAGE_TITLE);
        }
      }
      if (PAGE_DESCRIPTION !== '') {
        if (element.getAttribute('name') === 'description'
          || element.getAttribute('property') === 'og:description'
          || element.getAttribute('name') === 'twitter:description') {
          element.setAttribute('content', PAGE_DESCRIPTION);
        }
      }
      if (element.getAttribute('property') === 'og:url'
        || element.getAttribute('name') === 'twitter:url') {
        element.setAttribute('content', MY_DOMAIN);
      }
      if (element.getAttribute('name') === 'apple-itunes-app') {
        element.remove();
      }
    }
  }

  class HeadRewriter {
    element(element) {
      if (GOOGLE_FONT !== '') {
        element.append(`<link href="https://fonts.googleapis.com/css?family=${GOOGLE_FONT.replace(' ', '+')}:Regular,Bold,Italic&display=swap" rel="stylesheet">
        <style>* { font-family: "${GOOGLE_FONT}" !important; }</style>`, {
          html: true
        });
      }
      element.append(`<style>
      div.notion-topbar > div > div:nth-child(3) { display: none !important; }
      div.notion-topbar > div > div:nth-child(4) { display: none !important; }
      div.notion-topbar > div > div:nth-child(5) { display: none !important; }
      div.notion-topbar > div > div:nth-child(6) { display: none !important; }
      div.notion-topbar-mobile > div:nth-child(3) { display: none !important; }
      div.notion-topbar-mobile > div:nth-child(4) { display: none !important; }
      div.notion-topbar > div > div:nth-child(1n).toggle-mode { display: block !important; }
      div.notion-topbar-mobile > div:nth-child(1n).toggle-mode { display: block !important; }
      </style>`, {
        html: true
      })
    }
  }

  class BodyRewriter {
    constructor(SLUG_TO_PAGE) {
      this.SLUG_TO_PAGE = SLUG_TO_PAGE;
    }
    element(element) {
      element.append(`<div style="display:none">Powered by <a href="http://fruitionsite.com">Fruition</a></div>
      <script>
      window.CONFIG.domainBaseUrl = "${ MY_FULL_DOMAIN }";
      const SLUG_TO_PAGE = ${JSON.stringify(this.SLUG_TO_PAGE)};
      const PAGE_TO_SLUG = {};
      const slugs = [];
      const pages = [];
      const el = document.createElement('div');
      let redirected = false;
      Object.keys(SLUG_TO_PAGE).forEach(slug => {
        const page = SLUG_TO_PAGE[slug];
        slugs.push(slug);
        pages.push(page);
        PAGE_TO_SLUG[page] = slug;
      });
      function getPage() {
        return location.pathname.slice(-32);
      }
      function getSlug() {
        return location.pathname.slice(1);
      }
      function updateSlug() {
        const slug = PAGE_TO_SLUG[getPage()];
        if (slug != null) {
          history.replaceState(history.state, '', '/' + slug);
        }
      }
      function onDark() {
        el.innerHTML = '<div title="Change to Light Mode" style="margin-left: auto; margin-right: 14px; min-width: 0px;"><div role="button" tabindex="0" style="user-select: none; transition: background 120ms ease-in 0s; cursor: pointer; border-radius: 44px;"><div style="display: flex; flex-shrink: 0; height: 14px; width: 26px; border-radius: 44px; padding: 2px; box-sizing: content-box; background: rgb(46, 170, 220); transition: background 200ms ease 0s, box-shadow 200ms ease 0s;"><div style="width: 14px; height: 14px; border-radius: 44px; background: white; transition: transform 200ms ease-out 0s, background 200ms ease-out 0s; transform: translateX(12px) translateY(0px);"></div></div></div></div>';
        document.body.classList.add('dark');
        __console.environment.ThemeStore.setState({ mode: 'dark' });
      };
      function onLight() {
        el.innerHTML = '<div title="Change to Dark Mode" style="margin-left: auto; margin-right: 14px; min-width: 0px;"><div role="button" tabindex="0" style="user-select: none; transition: background 120ms ease-in 0s; cursor: pointer; border-radius: 44px;"><div style="display: flex; flex-shrink: 0; height: 14px; width: 26px; border-radius: 44px; padding: 2px; box-sizing: content-box; background: rgba(135, 131, 120, 0.3); transition: background 200ms ease 0s, box-shadow 200ms ease 0s;"><div style="width: 14px; height: 14px; border-radius: 44px; background: white; transition: transform 200ms ease-out 0s, background 200ms ease-out 0s; transform: translateX(0px) translateY(0px);"></div></div></div></div>';
        document.body.classList.remove('dark');
        __console.environment.ThemeStore.setState({ mode: 'light' });
      }
      function toggle() {
        if (document.body.classList.contains('dark')) {
          onLight();
        } else {
          onDark();
        }
      }
      function addDarkModeButton(device) {
        const nav = device === 'web' ? document.querySelector('.notion-topbar').firstChild : document.querySelector('.notion-topbar-mobile');
        el.className = 'toggle-mode';
        el.addEventListener('click', toggle);
        nav.appendChild(el);
        onLight();
      }
      const observer = new MutationObserver(function() {
        if (redirected) return;
        const nav = document.querySelector('.notion-topbar');
        const mobileNav = document.querySelector('.notion-topbar-mobile');
        if (nav && nav.firstChild && nav.firstChild.firstChild
          || mobileNav && mobileNav.firstChild) {
          redirected = true;
          updateSlug();
          addDarkModeButton(nav ? 'web' : 'mobile');
          const onpopstate = window.onpopstate;
          window.onpopstate = function() {
            if (slugs.includes(getSlug())) {
              const page = SLUG_TO_PAGE[getSlug()];
              if (page) {
                history.replaceState(history.state, 'bypass', '/' + page);
              }
            }
            onpopstate.apply(this, [].slice.call(arguments));
            updateSlug();
          };
        }
      });
      observer.observe(document.querySelector('#notion-app'), {
        childList: true,
        subtree: true,
      });
      const replaceState = window.history.replaceState;
      window.history.replaceState = function(state) {
        if (arguments[1] !== 'bypass' && slugs.includes(getSlug())) return;
        return replaceState.apply(window.history, arguments);
      };
      const pushState = window.history.pushState;
      window.history.pushState = function(state) {
        const dest = new URL(location.protocol + location.host + arguments[2]);
        const id = dest.pathname.slice(-32);
        if (pages.includes(id)) {
          arguments[2] = '/' + PAGE_TO_SLUG[id];
        }
        return pushState.apply(window.history, arguments);
      };
      const open = window.XMLHttpRequest.prototype.open;
      window.XMLHttpRequest.prototype.open = function() {
        arguments[1] = arguments[1].replace('${MY_DOMAIN}', 'www.notion.so');
        return open.apply(this, [].slice.call(arguments));
      };
    </script>${CUSTOM_SCRIPT}`, {
        html: true
      });
    }
  }

  async function appendJavascript(res, SLUG_TO_PAGE) {
    return new HTMLRewriter()
      .on('title', new MetaRewriter())
      .on('meta', new MetaRewriter())
      .on('head', new HeadRewriter())
      .on('body', new BodyRewriter(SLUG_TO_PAGE))
      .transform(res);
  }
bejaeger commented 3 years ago

I have no luck with any of the versions. It actually redirects me to the notion login screen now.

karincurkowicz commented 3 years ago

I've been getting this error on and off all day. Still blank screen. The thing is that I'm hosted through hostnotion. Not independently hosted through cloudflare. @hostnotion

image

dark-swordsman commented 3 years ago

I created a worker with wrangler (kind of annoying I can't tail existing workers). The error I got was:

{"name":"TypeError","message":"response.body.delete is not a function","timestamp":1629262161661}

It is on the /api/v3/getPublicPageData route, so that's at least our debug step.

It has to do with this part of the code:

      response = await fetch(url.toString(), {
        body: request.body,
        headers: {
          'content-type': 'application/json;charset=UTF-8',
          'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
        },
        method: 'POST',
      });
      response = new Response(response.body, response);
      response.headers.set('Access-Control-Allow-Origin', '*');
      if (url.pathname.startsWith('/api/v3/getPublicPageData')) {
        response.body.delete('requireInterstitial');
      }

So this means that response.body does not exist, probably because of the 500 error from Notion. But, given that we are getting 500 from Notion on that request, then something in the request or about the request is probably faulty.

However, I've never worked with notion so I have no idea what things to try to solve this. Maybe one of the other devs can use this as a starting point?

justanthonylee commented 3 years ago

This appears to be affecting any service that provides a domain in front of notion. It's kinda a problem in a lot of cases but I am unable to detect if it's a CloudFlare edge problem or not, but seeing as other providers for Notion domains are down I doubt they all use CF and workers so might fully on Notions end.

dark-swordsman commented 3 years ago

Given that the CF worker is throwing a JavaScript error and it has to do with response.body.delete not being a function, I think this is a Notion issue.

If I replace response.body.delete('requireInterstitial') with just a console.log, the page renders requiring me to log in:

image

This tells me that it's trying to access my editor instead of the public URL.

Also, the body on the /api/v3/getPublicPageData route ends up being:

betaEnabled: false
canJoinSpace: false
canRequestAccess: false
icon: "https://s3-us-west-2.amazonaws.com/public.notion-static.com/51444871-9329-42c5-82d8-a1457bdeab37/pfp1.png"
publicAccessRole: "comment_only"
requireLogin: true
spaceDomain: "darkswordsman"
spaceId: "7eec1f3f-d91a-438c-8103-551bfe46b71c"
spaceName: "Dark's Blog"

This includes the part where requireLogin: true is set, even though that's the only changed value between the normal notion domain and the custom domain. So something about the CF worker is forcing it to require login. IDK why.

Though, what I'm failing to understand is that the response for the same URL via the worker is:

{
  "webSocket": null,
  "url": "https://www.notion.so/api/v3/getPublicSpaceData",
  "redirected": false,
  "ok": true,
  "headers": {},
  "statusText": "OK",
  "status": 200,
  "bodyUsed": false,
  "body": {
    "locked": false
  }
}

The "body" you see there with "locked": false is the same body where it was trying to delete the key for requireInterstitial.

I have some understanding of JavaScript through webapp development, but I am failing to see how this script is working.

My only conclusion is that notion changed something on their end, so the request it incorrect in some way. I wish I can debug further, but I just simply don't know. We will have to wait for a dev I guess.

dark-swordsman commented 3 years ago

Alright, so update:

For the part where it makes a new request on /api, I added the following code:

const responseTwo = await fetch(url.toString(), {
  body: url.pathname.startsWith('/api/v3/getPublicPageData') ? JSON.stringify({
    requestedOnPublicDomain: true,
  }) : request.body,
  headers: {
    'content-type': 'application/json;charset=UTF-8',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
  },
  method: 'POST',
});

The only part there that is new is:

url.pathname.startsWith('/api/v3/getPublicPageData') ? JSON.stringify({
  requestedOnPublicDomain: true,
}) 

This causes it to work. I am not proposing this as a fix though, because I still have no idea how it works and this is clearly very different from how it was working before. It also probably is very wrong to do it this way.

My only possible guess after analyzing the requests is that cloudflare is not passing the request body and other information from the original request. So this is probably not a notion issue, but a cloudflare one.

I think it has to do with the body: false I was seeing earlier.

Hopefully the fruition devs can properly fix this or provide some other solution.

Edit: It also appears some sites, even fruition, are still running fine. So I'm not sure how this is possible, unless it's like @perogeremmer mentioned with the URL change.

Either way, very frustrating. Hopefully this is properly resolved.

jruers commented 3 years ago

I also think reason of issue is not:

Observation:

Perhaps a new change at Notion side is now causing a problem with the newest Fruition code

perogeremmer commented 3 years ago

Alright, so update:

For the part where it makes a new request on /api, I added the following code:

const responseTwo = await fetch(url.toString(), {
  body: url.pathname.startsWith('/api/v3/getPublicPageData') ? JSON.stringify({
    requestedOnPublicDomain: true,
  }) : request.body,
  headers: {
    'content-type': 'application/json;charset=UTF-8',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
  },
  method: 'POST',
});

The only part there that is new is:

url.pathname.startsWith('/api/v3/getPublicPageData') ? JSON.stringify({
  requestedOnPublicDomain: true,
}) 

This causes it to work. I am not proposing this as a fix though, because I still have no idea how it works and this is clearly very different from how it was working before. It also probably is very wrong to do it this way.

My only possible guess after analyzing the requests is that cloudflare is not passing the request body and other information from the original request. So this is probably not a notion issue, but a cloudflare one.

I think it has to do with the body: false I was seeing earlier.

Hopefully the fruition devs can properly fix this or provide some other solution.

Edit: It also appears some sites, even fruition, are still running fine. So I'm not sure how this is possible, unless it's like @perogeremmer mentioned with the URL change.

Either way, very frustrating. Hopefully this is properly resolved.

That's what I said 🤣. It's quite frustrating because the old pages worked fine like my website. But it breaks for the new page like my another website. It must be Notion dev changes some flow to redefine the URL for the new page version request.

But actually, something weird with the deeper page, if you're using linked pages for the old version page as I did, it would return the error message "Continue to external site by following the link below" like the new page version.

Fruitionsite is working properly since they're not using linked pages.

mattbarrie commented 3 years ago

I'm not a developer so do shout at me if I'm totally off - when adding the new base URL that Notion provide, ie. the "xyz.notion.site" to _const slug_topage moves me from a 301 fail to a 200 response. I wonder if every "notion.so" URL and reference to it in the Fruition script needs updating to "xyz.notion.site" for consistency. Lmk what you guys think.

Screenshot 2021-08-18 at 12 08 07 Screenshot 2021-08-18 at 12 07 54
dark-swordsman commented 3 years ago

Does it also resolve the blank page issue? Because that test you're doing is only the base web app. I had the same 301 status before (and 200 if I did my own domain), but it didn't reflect the 500 of the API route mentioned.

prodaea commented 3 years ago

if i did his test correctly, it doesn't work and i still get the api error in the console when i deploy/reload.

humanagent commented 3 years ago

same issue to me

jordanurbs commented 3 years ago

same issue

Krystal-zqy commented 3 years ago

same issue

LykeJ commented 3 years ago

Same issue with me, yesterday the code worked fine with the new urls. I updated all my links to the new format with no problems, but today all my websites are just blank screens.

aashay96 commented 3 years ago

Is there an update on this issue?

cosmic-designer commented 3 years ago

Is there an update on this issue?

i think we need to wait

disachantel commented 3 years ago

adding to the thread here. patiently waiting on a fix.

jgregoryjones commented 3 years ago

Ditto

lasharor commented 3 years ago

Instead of replying just to get notifications there is a "subscribe" function on the right sidebar of this page. I suggest using that.

dark-swordsman commented 3 years ago

Instead of replying just to get notifications there is a "subscribe" function on the right sidebar of this page. I suggest using that.

I was going to mention this as well. Though, the reason I'm replying here now is just to provide an annoying but more stable alternative (in my opinion).

I just ripped out the worker for various reasons and replaced it with redirects and page rules.

The reasons I ripped it out were:

  1. I hit 17k out of 100k requests on my worker after linking it on a single page with very little traffic.

Because this worker redirects all requests, I had 17k requests for 450 unique visitors. This is way too much in my opinion just for me to have a pretty URL. If I'm going to spend money on a cloudflare worker, it would probably be cheaper and easier to just get a Digital Ocean box to do Nginx proxying.

  1. Since these are just URL redirects, they are protected by RFC specifications. This means that it is more stable and not subject to change on Notion's end or have a chance to break because of the script not being updated correctly.

You can see these here:

image

image

The only oddity is that only the www subdomain works at redirecting to my blog. The apex (@, or root) does not work, so I have to also specify a redirect/rule for @ to www. But, it works great otherwise, and 192.0.2.1 is just a dummy domain, since we're redirecting anyways.

Maybe one day Fruition can be more stable, or better yet: Notion could actually provide support for custom domains.

Even if it's not the original intent, it is probably my favorite of all the blogging software I have tried. So it's a shame that custom domains don't work.

okisdev commented 3 years ago

⭐️ UPDATED: For those who still see the blank page after applying these(#117) changes, please make sure:

  1. The browser cache has been cleared. (For Chrome User)
  2. Cloudflare Dev Mode is turned on. (You can turn it off after it works for you.)
  3. Use other browsers (or Browser Private Mode) or mobile phones to visit your website, these devices or browsers must never visit this website. (Once it works for any device or browser, it would also work for all platforms)

Refer to this comment.

Here is a SOLUTION.

But it can absolutely solve these problems we are currently facing with.

All we need to do is make that system think we returned /api/v3/getPublicPageData with any content, even this JSON content is not relative to Notion, however, we could not just make it return error 500 directly, 500 will let the page shown blank, as many users face with.

I modified the code here, and delete the code here, these changes made it work again. I tried it many times between different Notion pages and domains, and it also brought all of my FruitionSite projects back to life.

Here is what I have changed.

// Modified line 111
body: url.pathname.startsWith('/api/v3/getPublicPageData') ? null : request.body,

// Deleted line 121-123
if (url.pathname.startsWith('/api/v3/getPublicPageData')) {
  response.body.delete('requireInterstitial');
}

Complete code is here. See changes on this Pull Request(#117).

Hope this helps.

bejaeger commented 3 years ago

Great! that works indeed, Harry-Yep, thanks so much.

For some reason I still had the blank screen in the same chrome browser session (even with empty cache and hard reload) and saw the content only when testing the URL in safari or in a private chrome session. Just in case other people experience the same.

okisdev commented 3 years ago

Great! that works indeed, Harry-Yep, thanks so much.

For some reason I still had the blank screen in the same chrome browser session (even with empty cache and hard reload) and saw the content only when testing the URL in safari or in a private chrome session. Just in case other people experience the same.

Make sure to clear your browser’s cache before visiting your website, I believe that these changes will be effective in all platforms.

aashay96 commented 3 years ago

@Harry-Yep Tried this but it didn't work for me. Tried with clearing cache also.

Madekuji commented 3 years ago

I can confirm that the fix works on my end. Thanks! For those having cache issues, in Cloudflare, try using Development Mode and also purging the cache.

lucaberta commented 3 years ago

@Harry-Yep I have implemented the changes you suggested in your https://github.com/stephenou/fruitionsite/issues/113#issuecomment-901524424 on the worker, and they worked fine. Website is visible again.

Many thanks,

Luca

okisdev commented 3 years ago

@aashay96 Hi, see the update on original comment. Hope this helps.

nhatanhngx commented 3 years ago

⭐️ UPDATED: For those who still see the blank page after applying these(#117) changes, please make sure:

  1. The browser cache has been cleared. (For Chrome User)
  2. Cloudflare Dev Mode is turned on. (You can turn it off after it works for you.)
  3. Use other browsers (or Browser Private Mode) or mobile phones to visit your website, these devices or browsers must never visit this website. (Once it works for any device or browser, it would also work for all platforms)

Refer to this comment.

Here is a SOLUTION, even it is not that perfect.

But it can absolutely solve these problems we are currently facing with.

All we need to do is make that system think we returned /api/v3/getPublicPageData with any content, even this JSON content is not relative to Notion, however, we could not just make it return error 500 directly, 500 will let the page shown blank, as many users face with.

I modified the code here, and delete the code here, these changes made it work again. I tried it many times between different Notion pages and domains, and it also brought all of my FruitionSite projects back to life.

Here is what I have changed.

// Modified line 111
body: url.pathname.startsWith('/api/v3/getPublicPageData') ? null : request.body,

// Deleted line 121-123
if (url.pathname.startsWith('/api/v3/getPublicPageData')) {
  response.body.delete('requireInterstitial');
}

Complete code is here. See changes on this Pull Request(#117).

Hope this helps.

Thank you Harry-Yep, it works for me!

leshapetrovskiy commented 3 years ago

hey. thanks for that. works fine. but there are a few errors in the console. don't know how critical that is or if it needs to be corrected. i'm not a programmer.

2021-08-19_18-05-08

and one thing. now the browser does not display the page description.

patrickbatememan commented 3 years ago

⭐️ UPDATED: For those who still see the blank page after applying these(#117) changes, please make sure:

  1. The browser cache has been cleared. (For Chrome User)
  2. Cloudflare Dev Mode is turned on. (You can turn it off after it works for you.)
  3. Use other browsers (or Browser Private Mode) or mobile phones to visit your website, these devices or browsers must never visit this website. (Once it works for any device or browser, it would also work for all platforms)

Refer to this comment.

Here is a SOLUTION, even it is not that perfect.

But it can absolutely solve these problems we are currently facing with.

All we need to do is make that system think we returned /api/v3/getPublicPageData with any content, even this JSON content is not relative to Notion, however, we could not just make it return error 500 directly, 500 will let the page shown blank, as many users face with.

I modified the code here, and delete the code here, these changes made it work again. I tried it many times between different Notion pages and domains, and it also brought all of my FruitionSite projects back to life.

Here is what I have changed.

// Modified line 111
body: url.pathname.startsWith('/api/v3/getPublicPageData') ? null : request.body,

// Deleted line 121-123
if (url.pathname.startsWith('/api/v3/getPublicPageData')) {
  response.body.delete('requireInterstitial');
}

Complete code is here. See changes on this Pull Request(#117).

Hope this helps.

Worked for me! Thankyou bro! I don't know the technicalities behind it but is this a permanent fix?

okisdev commented 3 years ago

@leshapetrovskiy This is normal, and it does not interfere with your daily use. Because the code replaces all *.notion.so with your domain name, therefore, some deep subdomain will return an error.

@patrickbatememan If Notion makes any more changes to their code, or takes a different approach to validation. Then we need to change the code to accommodate the new variations. Unless Notion has a conscious objection to us doing such things. However, I don't think that will happen, because I believe Notion is friendly to all developers.

jgregoryjones commented 3 years ago

Works. Many thanks.

bigansh commented 3 years ago

Please stop commenting about the solution working. It's better if you just REACT with the emoji!

remgriff commented 3 years ago

Hi. I have followed all the instructions here and have the latest code updated on my worker (after I completely deleted the old worker on CloudFlare) and all I get is a blank page. I tried clearing the cache, purging CF cache, turning on CF dev mode, I am completely out of ideas. Can somebody help me out here? What should I do? Thank you very, very much! Website is: https://remgriff.ro/

LE: managed to get it working by deleting the site from CF then redoing the whole Fruition procedure.

joshsabol46 commented 3 years ago

Still experiencing the Mismatch between origin and baseUrl (dev). issue and can reproduce even after following these steps:

  1. Removing existing worker + route
  2. Removing my site altogether
  3. Adding the site back
  4. Turning on Developer Mode
  5. Creating a new worker
  6. Pasting brand new script created from Fruition Site (see below)
  7. Opening Firefox Private (a browser I haven't used before, i.e. no cache of my site)
  8. Opening my site (sabol.io)
Brand new Fruition script from no. 6
``` /* CONFIGURATION STARTS HERE */ /* Step 1: enter your domain name like fruitionsite.com */ const MY_DOMAIN = 'sabol.io'; /* * 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 = { '': 'd37469163f9a4a199caa10ba58ada034', 'resume': '3c6ed9b1437d4edf8c74aad69e23e15c', }; /* Step 3: enter your page title and description for SEO purposes */ const PAGE_TITLE = ''; const PAGE_DESCRIPTION = ''; /* Step 4: enter a Google Font name, you can choose from https://fonts.google.com */ const GOOGLE_FONT = ''; /* Step 5: enter any custom scripts you'd like */ const CUSTOM_SCRIPT = ``; /* CONFIGURATION ENDS HERE */ const PAGE_TO_SLUG = {}; const slugs = []; const pages = []; Object.keys(SLUG_TO_PAGE).forEach(slug => { const page = SLUG_TO_PAGE[slug]; slugs.push(slug); pages.push(page); PAGE_TO_SLUG[page] = slug; }); addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)); }); function generateSitemap() { let sitemap = ''; slugs.forEach( (slug) => (sitemap += 'https://' + MY_DOMAIN + '/' + slug + '') ); sitemap += ''; return sitemap; } const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; function handleOptions(request) { if (request.headers.get('Origin') !== null && request.headers.get('Access-Control-Request-Method') !== null && request.headers.get('Access-Control-Request-Headers') !== null) { // Handle CORS pre-flight request. return new Response(null, { headers: corsHeaders }); } else { // Handle standard OPTIONS request. return new Response(null, { headers: { 'Allow': 'GET, HEAD, POST, PUT, OPTIONS', } }); } } async function fetchAndApply(request) { if (request.method === 'OPTIONS') { return handleOptions(request); } let url = new URL(request.url); url.hostname = 'www.notion.so'; if (url.pathname === '/robots.txt') { return new Response('Sitemap: https://' + MY_DOMAIN + '/sitemap.xml'); } if (url.pathname === '/sitemap.xml') { let response = new Response(generateSitemap()); response.headers.set('content-type', 'application/xml'); return response; } let response; if (url.pathname.startsWith('/app') && url.pathname.endsWith('js')) { response = await fetch(url.toString()); let body = await response.text(); response = new Response(body.replace(/www.notion.so/g, MY_DOMAIN).replace(/notion.so/g, MY_DOMAIN), response); response.headers.set('Content-Type', 'application/x-javascript'); return response; } else if ((url.pathname.startsWith('/api'))) { // Forward API response = await fetch(url.toString(), { body: url.pathname.startsWith('/api/v3/getPublicPageData') ? null : request.body, headers: { 'content-type': 'application/json;charset=UTF-8', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36' }, method: 'POST', }); response = new Response(response.body, response); response.headers.set('Access-Control-Allow-Origin', '*'); return response; } else if (slugs.indexOf(url.pathname.slice(1)) > -1) { const pageId = SLUG_TO_PAGE[url.pathname.slice(1)]; return Response.redirect('https://' + MY_DOMAIN + '/' + pageId, 301); } else { response = await fetch(url.toString(), { body: request.body, headers: request.headers, method: request.method, }); response = new Response(response.body, response); response.headers.delete('Content-Security-Policy'); response.headers.delete('X-Content-Security-Policy'); } return appendJavascript(response, SLUG_TO_PAGE); } class MetaRewriter { element(element) { if (PAGE_TITLE !== '') { if (element.getAttribute('property') === 'og:title' || element.getAttribute('name') === 'twitter:title') { element.setAttribute('content', PAGE_TITLE); } if (element.tagName === 'title') { element.setInnerContent(PAGE_TITLE); } } if (PAGE_DESCRIPTION !== '') { if (element.getAttribute('name') === 'description' || element.getAttribute('property') === 'og:description' || element.getAttribute('name') === 'twitter:description') { element.setAttribute('content', PAGE_DESCRIPTION); } } if (element.getAttribute('property') === 'og:url' || element.getAttribute('name') === 'twitter:url') { element.setAttribute('content', MY_DOMAIN); } if (element.getAttribute('name') === 'apple-itunes-app') { element.remove(); } } } class HeadRewriter { element(element) { if (GOOGLE_FONT !== '') { element.append(` `, { html: true }); } element.append(``, { html: true }) } } class BodyRewriter { constructor(SLUG_TO_PAGE) { this.SLUG_TO_PAGE = SLUG_TO_PAGE; } element(element) { element.append(`
Powered by Fruition
${CUSTOM_SCRIPT}`, { html: true }); } } async function appendJavascript(res, SLUG_TO_PAGE) { return new HTMLRewriter() .on('title', new MetaRewriter()) .on('meta', new MetaRewriter()) .on('head', new HeadRewriter()) .on('body', new BodyRewriter(SLUG_TO_PAGE)) .transform(res); } ```

For reference, also pasting my original code below:

Original script that worked fine up until a few months ago
``` const MY_DOMAIN = "sabol.io"; const SLUG_TO_PAGE = { "": "d37469163f9a4a199caa10ba58ada034", resume: "3c6ed9b1437d4edf8c74aad69e23e15c", harvestn: "ab8b94bcb1584f13b14671c0f20ca0b9", spreely: "12ca2ce330564b3bbb093ecdbfdf818e", corenps: "d17e45422c77498bb34ea386d6218af0", insights: "55dfd0038bed4e6698632b3db17039b0", vendorconnections: "fcd5e42e80dc4cdd8f99b106c5ac996a", mixpanel: "e06d1373a47e4800aadeae5f1e182b25", sql: "10624377ce494cf7a01599213f2ddb68", excel: "256b0e67cd5847008c90ce697bd3fc29", notion: "7171b061881746668b54bd63776fd61e", books: "c9bf950ed6ea472bbd2a715b2abcf48b", }; const ERROR_PAGE = ""; const PAGE_TITLE = "Josh Sabol"; const PAGE_DESCRIPTION = "Hi, I'm Josh, a Product Manager at AWS in Seattle. Connect with me on Twitter @joshsabol."; const FAVICON_URL = "https://img.icons8.com/ios-filled/50/000000/circled-j.png"; const IOS_ICON_URL = "https://i.imgur.com/aZPdaEs.png"; const OG_URL = "https://sabol.io"; const OG_TYPE = "website"; const OG_IMAGE_URL = "https://i.imgur.com/9Mn5eXW.png"; const META_TWITTER_CARD = "summary"; const META_TWITTER_SITE = "@joshsabol"; const META_TWITTER_TITLE = PAGE_TITLE; const META_TWITTER_DESC = PAGE_DESCRIPTION; const META_TWITTER_IMAGE = "https://i.imgur.com/aZPdaEs.png"; const META_TWITTER_URL = "https://sabol.io"; const GOOGLE_FONT = "Poppins"; const CUSTOM_SCRIPT = ``; const CUSTOM_CSS = `div.notion-topbar>div>div:nth-child(1n).toggle-mode{display:none!important}div.notion-topbar-mobile>div:nth-child(1n).toggle-mode{display:none!important}div.notion-topbar-mobile>div:nth-child(5){display:none!important}.notion-frame{background-image:linear-gradient(180deg,#fdfbfb 0,#ebedee 100%)!important}@keyframes gradient{0%{background-position:0 50%!important}50%{background-position:100% 50%}100%{background-position:0 50%}}.notion-page-content{padding-bottom:2.5rem!important;padding-top:2.5rem!important;background:#fff;border-radius:1rem;margin:-2.75rem 0 10vh 0}.notion-page-block{position:relative}.notion-scroller>[style="width: 100%; font-size: 14px;"]{margin-bottom:1.5rem}.notion-image-block{pointer-events:none!important}.notion-image-block img{pointer-events:none!important}.notion-callout-block>div>div{border-radius:.5rem!important}.notion-peek-renderer{background:#142025!important;transition:.3s}.notion-peek-renderer>div:nth-child(2){border-radius:.5rem!important;overflow:hidden}.notion-gallery-view>div>div>a{border-radius:.5rem!important}.notion-gallery-view>div>div>a:hover{opacity:.75}.notion-scroller>div:nth-child(2)>div{opacity:0!important;pointer-events:none!important}[data-block-id=c7ef4bd9-4069-480b-a481-3533903733e8]>div>div:nth-child(even),[data-block-id=f34cdbc9-8cd0-42aa-8189-3aa368fd0f37]>div>div:nth-child(even){display:none!important}@media only screen and (min-width:50em){[data-block-id=c7ef4bd9-4069-480b-a481-3533903733e8]>div>div:nth-child(even),[data-block-id=f34cdbc9-8cd0-42aa-8189-3aa368fd0f37]>div>div:nth-child(even){display:block!important}}[data-block-id=c7ef4bd9-4069-480b-a481-3533903733e8]>div>div:nth-child(odd),[data-block-id=f34cdbc9-8cd0-42aa-8189-3aa368fd0f37]>div>div:nth-child(odd){display:inline-block!important;max-width:50%!important}@media only screen and (min-width:50em){[data-block-id=c7ef4bd9-4069-480b-a481-3533903733e8]>div>div:nth-child(odd),[data-block-id=f34cdbc9-8cd0-42aa-8189-3aa368fd0f37]>div>div:nth-child(odd){display:block!important}}[data-block-id="971194ae-0c81-4fc6-a386-382167111c79"]{display:none}@media only screen and (min-width:50em){[data-block-id="971194ae-0c81-4fc6-a386-382167111c79"]{display:block;text-align:right;margin-top:-5.825rem!important;font-size:4rem}}[data-block-id=fcce5ac2-0901-4e52-a247-4684ece3df01]{font-size:.875rem;text-align:center}[data-block-id=fcce5ac2-0901-4e52-a247-4684ece3df01] .notion-record-icon{display:none!important}[data-block-id="6aa56b96-f6bf-4590-82c4-adca0c85b920"]{text-align:center}[data-block-id="6f58376d-b7c3-47a6-8720-d537db62ebf0"]{text-align:center;margin-bottom:-3.5rem!important}[data-block-id="6d7f9450-7f4e-4b6e-a9b8-45bccd9bfdd5"]{text-align:center;font-size:.875rem}[data-block-id="70792c31-f2b7-40b2-94ba-5a3a6c517273"]>div:first-child,[data-block-id=b15a7f0e-0538-4bc7-aaeb-b9494458f5bb]>div:first-child,[data-block-id=ef16e429-9a91-4e22-8391-032d4fe51cd3]>div:first-child{min-height:0!important}[data-block-id="70792c31-f2b7-40b2-94ba-5a3a6c517273"]>div:first-child>div,[data-block-id=b15a7f0e-0538-4bc7-aaeb-b9494458f5bb]>div:first-child>div,[data-block-id=ef16e429-9a91-4e22-8391-032d4fe51cd3]>div:first-child>div{display:none!important}[data-block-id="70792c31-f2b7-40b2-94ba-5a3a6c517273"].notion-selectable.notion-collection_view-block,[data-block-id=b15a7f0e-0538-4bc7-aaeb-b9494458f5bb].notion-selectable.notion-collection_view-block,[data-block-id=ef16e429-9a91-4e22-8391-032d4fe51cd3].notion-selectable.notion-collection_view-block{border:none!important}[data-block-id="70792c31-f2b7-40b2-94ba-5a3a6c517273"].notion-selectable.notion-collection_view-block,[data-block-id=b15a7f0e-0538-4bc7-aaeb-b9494458f5bb].notion-selectable.notion-collection_view-block{padding-top:0!important}[data-block-id="70792c31-f2b7-40b2-94ba-5a3a6c517273"] .notion-list-view,[data-block-id=b15a7f0e-0538-4bc7-aaeb-b9494458f5bb] .notion-list-view{padding-bottom:0!important}[data-block-id="255f5a05-d774-467f-a73f-7079bcc0eeee"]{display:none!important}@media only screen and (min-width:50em){[data-block-id="255f5a05-d774-467f-a73f-7079bcc0eeee"]{display:block!important}}[data-block-id="75a3b99e-f428-430d-a87b-3d5242fe5cce"]{text-align:right;padding-top:1rem}[data-block-id="51ee9852-027b-450e-aa4e-f6f0a1861ec2"]>div:first-child,[data-block-id=ec104b15-ff6e-4400-a848-a88f6139e1ff]>div:first-child,[data-block-id=f70889a1-feaa-4a1d-b00c-d4ee6e29689d]>div:first-child{min-height:0!important}[data-block-id="51ee9852-027b-450e-aa4e-f6f0a1861ec2"]>div:first-child>div,[data-block-id=ec104b15-ff6e-4400-a848-a88f6139e1ff]>div:first-child>div,[data-block-id=f70889a1-feaa-4a1d-b00c-d4ee6e29689d]>div:first-child>div{display:none!important}[data-block-id="183d187c-7b2c-4ce4-9d56-13d715eb2e9b"],[data-block-id="566014b3-8ba6-448f-b305-717f947ca58a"],[data-block-id="99a71a4b-08f7-4c99-945a-ddfbc9df0a1b"],[data-block-id=a1dd0805-87b2-444e-8a6b-90ce0086a1c3],[data-block-id=afad12b7-f88f-419c-9a7f-7e621018b287],[data-block-id=e8e72e41-d5b4-4987-a016-44f8f489b53f],[data-block-id=ff122c47-f4fe-4b7f-b827-703883217388]{display:none!important}[data-block-id="00b8412b-49d8-4a22-a739-a4f666fbd082"]~div img{border-radius:.5rem!important}[data-block-id=e0fa74a3-dfc2-4b66-bcd9-30abfced1863]~div img{border-radius:.5rem!important}[data-block-id="039a5f84-338a-4b2d-bed7-cd2112784fe2"],[data-block-id="43e70b54-3b70-4735-814e-776b5f5dc4fb"],[data-block-id="8371d4f9-4924-4e07-a422-2b871e2d504b"],[data-block-id=a9066f17-df96-43ab-a81a-ccba76c34176],[data-block-id=e11ff443-eddf-42cc-a197-6580c47d1bc5],[data-block-id=f23de68b-e100-4ff2-a4e0-1a3b19eb98d9]{display:none}@media only screen and (min-width:50em){[data-block-id="54db5892-e2da-460e-8dc9-caa48615b902"],[data-block-id="5fc61763-35d2-4ae7-ab98-086e63758bfb"],[data-block-id="69a89fae-e10d-4f22-806c-e37ab3397f7e"],[data-block-id="71a0c46d-f859-4f2c-80e2-b1e6972f5f0e"],[data-block-id=b506d1bf-8ad7-4bb8-81d2-87e43bf21756],[data-block-id=c0b083f9-d63d-4f45-bee7-8b08d5e7e0f6]{display:none}[data-block-id="039a5f84-338a-4b2d-bed7-cd2112784fe2"],[data-block-id="43e70b54-3b70-4735-814e-776b5f5dc4fb"],[data-block-id="8371d4f9-4924-4e07-a422-2b871e2d504b"],[data-block-id=a9066f17-df96-43ab-a81a-ccba76c34176],[data-block-id=e11ff443-eddf-42cc-a197-6580c47d1bc5],[data-block-id=f23de68b-e100-4ff2-a4e0-1a3b19eb98d9]{display:block}}[data-block-id="8a0b343f-5acc-4095-9fce-266148517eda"]{display:none!important}`; const PAGE_TO_SLUG = {}; const slugs = []; const pages = []; Object.keys(SLUG_TO_PAGE).forEach((slug) => { const page = SLUG_TO_PAGE[slug]; slugs.push(slug); pages.push(page); PAGE_TO_SLUG[page] = slug; }); addEventListener("fetch", (event) => { event.respondWith(fetchAndApply(event.request)); }); function generateSitemap() { let sitemap = ''; slugs.forEach( (slug) => (sitemap += "https://" + MY_DOMAIN + "/" + slug + "") ); sitemap += ""; return sitemap; } const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, HEAD, POST, PUT, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", }; function handleOptions(request) { if ( request.headers.get("Origin") !== null && request.headers.get("Access-Control-Request-Method") !== null && request.headers.get("Access-Control-Request-Headers") !== null ) { // Handle CORS pre-flight request. return new Response(null, { headers: corsHeaders, }); } else { // Handle standard OPTIONS request. return new Response(null, { headers: { Allow: "GET, HEAD, POST, PUT, OPTIONS", }, }); } } async function fetchAndApply(request) { if (request.method === "OPTIONS") { return handleOptions(request); } let url = new URL(request.url); url.hostname = "www.notion.so"; if (url.pathname === "/robots.txt") { return new Response("Sitemap: https://" + MY_DOMAIN + "/sitemap.xml"); } if (url.pathname === "/sitemap.xml") { let response = new Response(generateSitemap()); response.headers.set("content-type", "application/xml"); return response; } let fullPathname = request.url.replace("https://" + MY_DOMAIN, ""); let response; if (url.pathname.startsWith("/app") && url.pathname.endsWith("js")) { response = await fetch(url.toString()); let body = await response.text(); response = new Response( body .replace(/www.notion.so/g, MY_DOMAIN) .replace(/notion.so/g, MY_DOMAIN), response ); response.headers.set("Content-Type", "application/x-javascript"); return response; } else if (url.pathname.startsWith("/api")) { // Forward API response = await fetch(url.toString(), { body: url.pathname.startsWith("/api/v3/getPublicPageData") ? null : request.body, headers: { "content-type": "application/json;charset=UTF-8", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36", }, method: "POST", }); response = new Response(response.body, response); response.headers.set("Access-Control-Allow-Origin", "*"); return response; } else if (slugs.indexOf(url.pathname.slice(1)) > -1) { const pageId = SLUG_TO_PAGE[url.pathname.slice(1)]; return Response.redirect("https://" + MY_DOMAIN + "/" + pageId, 301); } else { response = await fetch(url.toString(), { body: request.body, headers: request.headers, method: request.method, }); response = new Response(response.body, response); response.headers.delete("Content-Security-Policy"); response.headers.delete("X-Content-Security-Policy"); } return appendJavascript(response, SLUG_TO_PAGE); } class MetaRewriter { element(element) { if (PAGE_TITLE !== "") { if ( element.getAttribute("property") === "og:title" || element.getAttribute("property") === "og:site_name" || element.getAttribute("name") === "twitter:title" ) { element.setAttribute("content", PAGE_TITLE); } if (element.tagName === "title") { element.setInnerContent(PAGE_TITLE); } } if (PAGE_DESCRIPTION !== "") { if ( element.getAttribute("name") === "description" || element.getAttribute("property") === "og:description" || element.getAttribute("name") === "twitter:description" ) { element.setAttribute("content", PAGE_DESCRIPTION); } } if (element.getAttribute("property") === "og:url") { element.setAttribute("content", OG_URL); } if (element.getAttribute("name") === "apple-itunes-app") { element.remove(); } if (element.getAttribute("property") === "og:type") { element.setAttribute("content", OG_TYPE); } if (element.getAttribute("property") === "og:image") { element.setAttribute("content", OG_IMAGE_URL); } if ( element.tagName === "link" && element.getAttribute("rel") === "shortcut icon" ) { element.setAttribute("href", FAVICON_URL); } if ( element.tagName === "link" && element.getAttribute("rel") === "apple-touch-icon" ) { element.setAttribute("href", IOS_ICON_URL); } if (element.getAttribute("name") === "twitter:card") { element.setAttribute("content", META_TWITTER_CARD); } if (element.getAttribute("name") === "twitter:site") { element.setAttribute("content", META_TWITTER_SITE); } if (element.getAttribute("name") === "twitter:image") { element.setAttribute("content", META_TWITTER_IMAGE); } if (element.getAttribute("name") === "twitter:url") { element.setAttribute("content", META_TWITTER_URL); } } } class HeadRewriter { element(element) { if (GOOGLE_FONT !== "") { element.append( ` `, { html: true, } ); } element.append( ``, { html: true, } ); } } class BodyRewriter { constructor(SLUG_TO_PAGE) { this.SLUG_TO_PAGE = SLUG_TO_PAGE; } element(element) { element.append(`
Powered by Fruition
${CUSTOM_SCRIPT}`, { html: true, } ); } } async function appendJavascript(res, SLUG_TO_PAGE) { return new HTMLRewriter() .on("title", new MetaRewriter()) .on("meta", new MetaRewriter()) .on("link", new MetaRewriter()) .on("head", new HeadRewriter()) .on("body", new BodyRewriter(SLUG_TO_PAGE)) .transform(res); } ```

Thank you in advance for your help!

tamagamis commented 3 years ago

Still experiencing the Mismatch between origin and baseUrl (dev). issue and can reproduce even after following these steps:

  1. Removing existing worker + route
  2. Removing my site altogether
  3. Adding the site back
  4. Turning on Developer Mode
  5. Creating a new worker
  6. Pasting brand new script created from Fruition Site (see below)
  7. Opening Firefox Private (a browser I haven't used before, i.e. no cache of my site)
  8. Opening my site (sabol.io)

Brand new Fruition script from no. 6

Okay if you already observed, did you add anything else? Or are you using the same original script from the fruitionsite.com site?