Skip to content

Instantly share code, notes, and snippets.

@rezaarkan
Last active May 3, 2025 05:25
Show Gist options
  • Save rezaarkan/71e2449faa75a69f660031f5668c22b5 to your computer and use it in GitHub Desktop.
Save rezaarkan/71e2449faa75a69f660031f5668c22b5 to your computer and use it in GitHub Desktop.
const MY_DOMAIN = 'rezaarkan.com';
const SLUG_TO_PAGE = {
'': '882cd6dd6e1e482d823b464f326213e5',
'now': '25b7df64071d420d8f609bf76d9f4114',
'portfolio': '6000547bed0d441793bfba1498c063e2',
'resume': '0934b80d2d1544f99dedadb00be9d146',
'recommendations': '29115129efa44f1a870f390dd2c0a6c0',
'photos': 'e78c0492a5ec486aa51f4cdb2c6f4603',
'blog': '29bb193c1a104ba2b832788b57d58cd6',
'bookmarks': 'e31f043461cd4739b9ec967cb36c0cba',
'contact': '15364eee2c8b41188a069184f9e108be',
};
const PAGE_TITLE = 'Reza Arkan';
const PAGE_DESCRIPTION = 'Design // People // Tech';
const FAVICON_URL = 'https://drive.google.com/uc?id=12MYHtCw_uU3j9eyQ60vBLPe5R74gPIaX';
const IOS_ICON_URL = 'https://drive.google.com/uc?id=14LEFgUMPDiOf8iND-ldq8QKwtksLdkm2';
const OG_URL = 'https://rezaarkan.com';
const OG_TYPE = 'website';
const OG_IMAGE_URL = 'https://i.imgur.com/WgH50dv.jpg';
const META_TWITTER_CARD = 'summary';
const META_TWITTER_SITE = '@rezaarkan';
const META_TWITTER_TITLE = PAGE_TITLE;
const META_TWITTER_DESC = PAGE_DESCRIPTION;
const META_TWITTER_IMAGE = 'https://i.imgur.com/15A1v9d.jpg';
const META_TWITTER_URL = 'https://rezaarkan.com';
const GOOGLE_FONT = 'Poppins';
const CUSTOM_SCRIPT = `<script async src="https://www.googletagmanager.com/gtag/js?id=UA-162915679-1"></script>
<script>window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'UA-162915679-1');</script>
<style>.notion-frame{background-image: linear-gradient(180deg, #fdfbfb 0%, #ebedee 100%) !important;} .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;} [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: 0.875rem; text-align: center;} [data-block-id = "fcce5ac2-0901-4e52-a247-4684ece3df01"] .notion-record-icon{display: none !important;} [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: 0.875rem;} .notion-scroller > [style="width: 100%; font-size: 14px;"]{margin-bottom: 1.5rem;} [data-block-id="51ee9852-027b-450e-aa4e-f6f0a1861ec2"] > div:first-child,[data-block-id="f70889a1-feaa-4a1d-b00c-d4ee6e29689d"] > div:first-child,[data-block-id="ec104b15-ff6e-4400-a848-a88f6139e1ff"] > div:first-child{height: 0 !important;} [data-block-id="51ee9852-027b-450e-aa4e-f6f0a1861ec2"] > div:first-child > div,[data-block-id="f70889a1-feaa-4a1d-b00c-d4ee6e29689d"] > div:first-child > div,[data-block-id="ec104b15-ff6e-4400-a848-a88f6139e1ff"] > div:first-child > div{display: none !important;} [data-block-id="99a71a4b-08f7-4c99-945a-ddfbc9df0a1b"],[data-block-id="183d187c-7b2c-4ce4-9d56-13d715eb2e9b"]{display: none !important;} [data-block-id="51ee9852-027b-450e-aa4e-f6f0a1861ec2"],[data-block-id="1aeccf77-b7b9-4b12-9985-4c6a6c288d02"],[data-block-id="fa643738-2ff1-4f7a-b9e9-a7821c8d95f5"],[data-block-id="fa643738-2ff1-4f7a-b9e9-a7821c8d95f5"]{display: 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;}} .notion-image-block{pointer-events:none !important;} .notion-image-block img{pointer-events:none !important;}</style> `;
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);
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, "");
const notionUrl = 'https://www.notion.so' + fullPathname;
let response;
if (url.pathname.startsWith('/app') && url.pathname.endsWith('js')) {
response = await fetch(notionUrl);
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');
} else if ((url.pathname.startsWith('/api'))) {
// Forward API
response = await fetch(notionUrl, {
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', '*');
} 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(notionUrl, {
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(`<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; }
</style>`, {
html: true
})
}
}
class BodyRewriter {
constructor(SLUG_TO_PAGE) {
this.SLUG_TO_PAGE = SLUG_TO_PAGE;
}
element(element) {
element.append(`
<script>
const SLUG_TO_PAGE = ${JSON.stringify(this.SLUG_TO_PAGE)};
const PAGE_TO_SLUG = {};
const slugs = [];
const pages = [];
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);
}
}
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();
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('link', new MetaRewriter())
.on('head', new HeadRewriter())
.on('body', new BodyRewriter(SLUG_TO_PAGE))
.transform(res);
}
@rohan20
Copy link

rohan20 commented Jul 16, 2022

Thank you!

@rslhdyt
Copy link

rslhdyt commented Jul 27, 2022

Hi, Mas @rezaarkan. Thank you for a nice article about notion and fruition. I have a question about the SLUG_TO_PAGE constant.
Does it mean we need to update the SLUG_TO_PAGE every time we have a new page in notion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment