Giter Site home page Giter Site logo

react-notion's Introduction

react-notion

npm version npm version minzipped sized

A React renderer for Notion pages. Use Notion as CMS for your blog, documentation or personal site.

react-notion was developed by Splitbee. Splitbee is a fast, reliable, free, and modern analytics for any team.

This package doesn't handle the communication with the API. Check out notion-api-worker for an easy solution.

Created by Timo Lins & Tobias Lins with the help of all contributors ❤️

Features

⚡️ Fast – Up to 10x faster than Notion*

🎯 Accurate – Results are almost identical

🔮 Code Highlighting – Automatic code highlighting with prismjs

🎨 Custom Styles – Styles are easily adaptable. Optional styles included

* First Meaningful Paint compared to a hosted example on Vercel.

react-notion is best suited as minimal renderer for blogs & content pages. If you're looking for a full-featured solution to render Notion-like pages, check out react-notion-x.

Install

npm install react-notion

How to use

Minimal Example

We can store the API response in a .json file and import it.

import "react-notion/src/styles.css";
import "prismjs/themes/prism-tomorrow.css"; // only needed for code highlighting
import { NotionRenderer } from "react-notion";

import response from "./load-page-chunk-response.json"; // https://www.notion.so/api/v3/loadPageChunk

const blockMap = response.recordMap.block;

export default () => (
  <div style={{ maxWidth: 768 }}>
    <NotionRenderer blockMap={blockMap} />
  </div>
);

A working example can be found inside the example directory.

Next.js Example

In this example we use Next.js for SSG. We use notion-api-worker to fetch data from the API.

/pages/my-post.jsx

import "react-notion/src/styles.css";
import "prismjs/themes/prism-tomorrow.css";

import { NotionRenderer } from "react-notion";

export async function getStaticProps() {
  const data = await fetch(
    "https://notion-api.splitbee.io/v1/page/<NOTION_PAGE_ID>"
  ).then(res => res.json());

  return {
    props: {
      blockMap: data
    }
  };
}

export default ({ blockMap }) => (
  <div style={{ maxWidth: 768 }}>
    <NotionRenderer blockMap={blockMap} />
  </div>
);

Sites using react-notion

List of pages that implement this library.

Supported Blocks

Most common block types are supported. We happily accept pull requests to add support for the missing blocks.

Block Type Supported Notes
Text ✅ Yes
Heading ✅ Yes
Image ✅ Yes
Image Caption ✅ Yes
Bulleted List ✅ Yes
Numbered List ✅ Yes
Quote ✅ Yes
Callout ✅ Yes
Column ✅ Yes
iframe ✅ Yes
Video ✅ Yes Only embedded videos
Divider ✅ Yes
Link ✅ Yes
Code ✅ Yes
Web Bookmark ✅ Yes
Toggle List ✅ Yes
Page Links ✅ Yes
Header ✅ Yes Enable with fullPage
Databases ❌ Missing Not planned. Supported by react-notion-x
Checkbox ❌ Missing Supported by react-notion-x
Table Of Contents ❌ Missing Supported by react-notion-x

Block Type Specific Caveats

When using a code block in your Notion page, NotionRenderer will use prismjs to detect the language of the code block. By default in most project, prismjs won't include all language packages in the minified build of your project. This tends to be an issue for those using react-notion in a next.js project. To ensure the programming language is correctly highlighted in production builds, one should explicitly imported into the project.

import 'prismjs/components/prism-{language}';

Credits

react-notion's People

Contributors

cball avatar dependabot[bot] avatar dvdsgl avatar el-angel avatar indreklasn avatar janniks avatar mxstbr avatar pyk avatar saitoukun avatar sorcererxw avatar thmsmlr avatar timolins avatar tobiaslins avatar transitive-bullshit avatar vinpac avatar younho9 avatar zhyd1997 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-notion's Issues

react-notion crashes when rendering untitled toggle block

Library Crashes When Rendering Untitled Toggle Block

Description:

Encountering a crash in the library when attempting to render a toggle block without a title (i.e., only with the placeholder "Toggle").

Problem:

The application crashes with a TypeError: Cannot read properties of undefined (reading 'title') when attempting to render a toggle block without a specified title.

Reproduction Steps:

  1. Visit the original Notion page containing a toggle block without a title: Original Notion Page
  2. Attempt to render the page using React Notion: Rendered Page

Expected Behavior:

The library should handle toggle blocks without titles gracefully and avoid crashing the application.

Error Screenshot:

Screenshot 2024-03-21 at 11 57 30 AM

How to modify href for in-page links?

Hi, I have a notion page that I've rendered (easily and beautifully, so well done there), but the links within it point to host/blockValue.id, but I'd love to edit it to something like host/path/blockValue.id. Therefore, something like example.com/support/abcd1234.

The problem I'm encountering is that I don't really know how to use the customDecoratorComponents and customBlockComponents, and I can't find any documentation about it besides the actual src code.

I've tried something like this (added the redundancy just to ensure it could work, I can't articulate the difference between customDecoratorComponents and customBlockComponents)

<NotionRenderer
  blockMap={this.state.data}
  customDecoratorComponents={{
    'a': ({ decoratorValue, children }) => (
      <a href={`/support/${decoratorValue}`}>
        {children}
      </a>
    )
  }}
  customBlockComponents={{
    page: ({ blockValue, renderComponent }) => {
      return (
      <a href={`/support/${blockValue.id}`}>{renderComponent()}</a>
    )}
  }}
/>

It seems that what renderComponent() returns is not respecting the modified href I've added, even if I were to add different attributes.

It does work If I add something like "foo" right after {renderComponent()}, then the renderer creates two links, the normal renderComponent() link and my decorated "foo" link, but that foo link then loses all the styles and I would rather not reinvent the wheel and apply all the styling and extra bells and whistles to my foo link from scratch.

Thank you in advance!

Full support for collection views

Let's track progress in this issue. Higher priority items listed first.

Note that none of these items have been merged or released yet.

  • table view
  • gallery view
  • list view
  • board view
  • calendar view
  • formula support
  • ability to switch views
  • lazy loading for larger collections (e.g. pokedex)
  • ability to search / filter views
  • ability to sort views

How to create pretty URL slugs posts?

Hi. First of all, thanks for this amazing library 👏

I have a question about the blog URL. I've noticed that your articles at Splitbee have pretty URLs instead of the classic ugly Notion URLs which append a UUID at the end.

Is there a quick hack to make them work like yours on a Next.js app?

image

Split component into `<NotionPage/>` and `<NotionRenderer/>`

Now that that react-notion has been out for sometime, two main use-cases have established:

  • As content renderer for blogs, documentation or websites. I like to think of it Markdown renderer, but instead of Markdown it is powered by Notion.

  • As fast Notion replacement. More and more folks use Notion to build websites, but the real deal is too slow & limiting.

At the moment we do both, but handle the specific use-cases with props like fullPage, which mixes those concerns.

Proposal

Extract some functionality (fullPage, disableHeader) to a new component called <NotionPage/>. This would result in the following benefits:

  • Leaner core - Remove unnecessary options & dependencies from the <NotionRenderer/>.
  • More flexibility - By moving all Notion page related stuff into its own component, we can start to add more functionality to it, without affecting the core. That would be things like:
    • Twemoji fallback (#24)
    • Darkmode
    • Support for an image lightbox: medium-zoom

We are currently beta testing a support for custom components, which should make this separation possible - See #30

Grid layout is not working properly.

I'm trying out this beautiful library, everything works as expected.
But the grid layout, especially a complex one, make the images look out of resolution, check out this example:

This is from notion directly:

scr-05-27-08-PM5013

And this is from react-notion:

scr-05-27-08-PM5031

Allow styled links

Currently, when I use the component to render content from a notion page and there's a link on that page, the link doesn't get displayed with the same styling that it has in notion. Like, the underlines disappear on the web page and it's all the same color, so users can't tell there's a link there. Is there a way to enable links to have different styling than plain text, or has that not been implemented yet?

For example, this is what a page looks like in notion:

image

But this is how the page looks rendered on a web page:

image

And this is the code I used to render that page in pages/index.js

import { NotionRenderer } from "react-notion";
import Head from "next/head";
import fetch from "node-fetch";

export async function getStaticProps() {
  const data = await fetch(
    "https://notion-api.splitbee.io/v1/page/399efa86bc1b4dcdb5a1dd2cb6af2458"
  ).then((res) => res.json());

  return {
    props: {
      blockMap: data,
    },
    revalidate: 1,
  };
}

export default function Home({ blockMap }) {
  return (
    <div>
      <Head>
        <style>{`body { margin: 0;}`}</style>
        <title>react-notion example</title>
      </Head>
      <NotionRenderer blockMap={blockMap} />
    </div>
  );
}

Allow autoplay control for embedded videos

Hi! I noticed that the rendered videos are being played automatically. Would it be possible to disable autoplay by default to match its behaviour with those from the original notion pages?

Return errors when importing unsupported content types

Currently if you import a Notion page that has either a database or a checkbox, the library appears to simply not load — ideally the library should return an error and explain what the unsupported content is, eg:

"This Notion document includes a Database which we cannot import, please remove the Database to render this page"

Unsupported type undefined

I have encountered an issue while using the React-Notion library to render blocks from a Notion page. It seems that the library is not functioning properly with the current block structure of the Notion page.

When attempting to render the page, I noticed a console message stating "Unsupported type undefined". To investigate further, I set up a debugger and discovered that the problem is related to the block type. It appears that the library may not yet support the rendering of Paragraph blocks.

My Notion page primarily consists of basic elements such as headings and paragraphs. However, when I attempt to render the page using React-Notion, I encounter this error.

I believe it would be beneficial to enhance the React-Notion library's compatibility with various block types, including Paragraph blocks, to ensure a seamless rendering experience for users.

Steps to Reproduce:

Set up a Notion page with basic elements like headings and paragraphs.
Use the React-Notion library to render the page.
Check the console for any error messages.
Expected Behavior:
The React-Notion library should successfully render the Notion page blocks, including Paragraph blocks, without any error messages.

Actual Behavior:
The library throws an "Unsupported type undefined" error in the console, indicating an issue with the block type, possibly due to the lack of support for Paragraph blocks, and the React-Notion library render nothing to the screen.

Sometimes format is null for the embedded image

Use this doc, the library breaks for the second blog

https://www.notion.so/5dbf519a81a14616ba35b62c196cd823

getting the following error

TypeError: Cannot read property 'block_width' of undefined
at Block (C:\Users\apurv\source\mailmodo\next-blog\node_modules\react-notion\dist\react-notion.cjs.development.js:376:31)
at processChild (C:\Users\apurv\source\mailmodo\next-blog\node_modules\react-dom\cjs\react-dom-server.node.development.js:3043:14)
at resolve (C:\Users\apurv\source\mailmodo\next-blog\node_modules\react-dom\cjs\react-dom-server.node.development.js:2960:5)
at ReactDOMServerRenderer.render (C:\Users\apurv\source\mailmodo\next-blog\node_modules\react-dom\cjs\react-dom-server.node.development.js:3435:22)
at ReactDOMServerRenderer.read (C:\Users\apurv\source\mailmodo\next-blog\node_modules\react-dom\cjs\react-dom-server.node.development.js:3373:29)
at renderToString (C:\Users\apurv\source\mailmodo\next-blog\node_modules\react-dom\cjs\react-dom-server.node.development.js:3988:27)
at Object.renderPage (C:\Users\apurv\source\mailmodo\next-blog\node_modules\next\dist\next-server\server\render.js:50:851)
at Function.getInitialProps (C:\Users\apurv\source\mailmodo\next-blog.next\server\pages_document.js:299:19)
at loadGetInitialProps (C:\Users\apurv\source\mailmodo\next-blog\node_modules\next\dist\next-server\lib\utils.js:5:101)
at renderToHTML (C:\Users\apurv\source\mailmodo\next-blog\node_modules\next\dist\next-server\server\render.js:50:1142)

Codeblock className is prefixed with an empty space on the Server but not on the Client

Hi there! First, let me thank you for writing and sharing this package! I'm a fan of notion and being able to use it as a source for my sites is awesome!

I've come across a weird SSR error using NextJs and the method getStaticProps exactly like in your README example. I'm grabbing content from a notion page that includes a javascript code block. I then get the following (hydration?) error:

Prop `className` did not match. Server: " language-javascript" Client: "language-javascript"

As you can see, the server className is prefixed with a space character but the client is not. I could find where this className is set in the code and where the language is set but I cannot see where the space prefix might come from. Any idea what could cause this difference between server and client?

The code to my repository is here: https://github.com/vogelino/fast-assembled-furniture/blob/staging/pages/brand/ui/buttons.tsx

Thx and keep up the good work! 🤜🤛

Is it possible to style for dark mode?

Is it possible to use custom styles like dark mode ?
I'm using tailwind, but I've tried using a style property as well.

import React from 'react';
import PropTypes from 'prop-types';
import { css, styled } from 'twin.macro';

const styles = css`
.dark-mode {
  .notion, .notion-text, .notion-page-link {
    color: white;
  }
}`;

const StyledDiv = styled.div(() => [styles]);
...
  return (
<StyledDiv>
    <NotionRenderer blockMap={recordMap.data} />
</StyedDiv>
  );

This doesn't seem to work:

Screen Shot 2023-03-07 at 4 10 07 PM

Is there an alternative besides forking this repo and fixing the styles in the fork?

Checkboxes do not render

If you import a Notion page that includes checkboxes, the library will cause an error and not render.

Since the library has no way to actually write back the checkbox interaction back to Notion, I propose it simply reads if the checkbox is checked or not and render that (with no way of toggling it from the library) — so if a checkbox is un-checked, it will simply show an empty checkbox, and if it is checked, it will simply show a checked checkbox.

Proposed fix:

  • Render checkboxes with their current state:
  • If a Notion page has a checkbox that is un-checked, render an empty checkbox
  • If a Notion page has a checkbox that is checked, render a checked checkbox.

Handling null properties values

      case "video":
        var value = block.value;
        return /*#__PURE__*/createElement("figure", {
          className: "notion-asset-wrapper",
          style: value.format !== undefined ? {
            width: value.format.block_width
          } : undefined
        }, /*#__PURE__*/createElement(Asset, {
          block: block,
          mapImageUrl: mapImageUrl
        }), value.properties.caption && /*#__PURE__*/createElement("figcaption", {
          className: "notion-image-caption"
        }, renderChildText(value.properties.caption)));

This generated block in react-notion.esm.js is failing when properties are null. Properties are not always present in this case and therefore there can be a failure here with .caption in the chain. I'm not sure the best way to handle this - is the onus on the notion doc creator to ensure no null properties values? (this could happen if an unfinished video component was inserted in a doc and mistakenly forgotten about).

Should properties be required on ContentValueType? on All values?
Should properties be required? Can we make them nullable, or is that an antipattern?

Lists start over with each item

For some reason, lists start over with each item is rendered.

So instead of -

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

It comes out as -

<ul>
  <li>Item 1</li>
</ul>
<ul>
  <li>Item 2</li>
</ul>
<ul>
  <li>Item 3</li>
</ul>

It has the correct notion classes and everything. But it always starts the list over.

Getting error Unsupported type undefined for heading & paragraph

I am using @notionhq/client to get pages

My page
https://vishwasraj.notion.site/hello-world-8fb2880e72204bdb8b05fa8b4653fdfe

Request Setup

const notion = new Client({
  auth: 'secret'
});

const getPage = async (pageId) => {
  const response = await notion.pages.retrieve({ page_id: pageId });
  return response;
};

getStaticProps

export async function getStaticProps({ params: { slug } }) {
  const page = await getPage(slug);
  const blocks = await getBlocks(slug);
  console.log(blocks);
  return {
    props: {
      blocks,
      page
    }
  };
}

Response

[
  {
    object: 'block',
    id: '29eab320-fd21-42db-922e-8d8b637472ef',
    created_time: '2022-01-03T08:44:00.000Z',
    last_edited_time: '2022-01-03T08:44:00.000Z',
    has_children: false,
    archived: false,
    type: 'heading_3',
    heading_3: { text: [Array] }
  },
  {
    object: 'block',
    id: '99d4ab1f-0406-4f1f-afce-3f3017a8b0b5',
    created_time: '2022-01-03T08:44:00.000Z',
    last_edited_time: '2022-01-03T08:44:00.000Z',
    has_children: false,
    archived: false,
    type: 'paragraph',
    paragraph: { text: [Array] }
  }
]

Template

export default function BlogPost({ blocks }) {
  return <NotionRenderer blockMap={blocks} />;
}

Tried using https://github.com/NotionX/react-notion-x with same response. But got error TypeError: Cannot convert undefined or null to object
<NotionRenderer recordMap={blocks} fullPage={true} darkMode={false} />

I am following this blog post
https://splitbee.io/blog/notion-as-cms-using-nextjs

I saw this api endpoint. The structure seems to be very different than the one I am currently getting from notion api.
https://notion-api.splitbee.io/v1/page/2e22de6b770e4166be301490f6ffd420

Am I missing somethig or should I transform the api response before passing on to NotionRenderer ?
Is notion-api-worker necessary for react-notion to work ?

Notion teamspace page images not rendering

Issue: Notion teamspace page images not rendering

Description

Notion introduced a feature called Notion Teamspace, allowing users to create subgroups and manage access to specific pages within those subgroups. However, React Notion does not currently handle images from pages within Teamspace correctly, leading to rendering issues.

Problem

When attempting to display images from pages within Notion Teamspace using React Notion, the images fail to render. This issue specifically affects uploaded images; images such as icons or those selected from Unsplash render correctly.

Solution

To address this issue, a custom function can be implemented to override React Notion's default image URL handling. The following function modifies the image URL parameters to ensure proper rendering within React Notion:

export const toNotionImageUrl: MapImageUrl = (url, block) => {
  let notionUrl = url

  if (!url.startsWith('https://www.notion.so')) {
    notionUrl = 'https://www.notion.so'.concat(
      url.startsWith('/image') ? url : `/image/${encodeURIComponent(url)}`,
    )
  }

  const imageUrl = new URL(notionUrl)

  if (block) {
     // Changed here, to switch from `table=team` to `table=block` in the url
    const table = ['space', 'team'].includes(block.value.parent_table)
      ? 'block'
      : block.value.parent_table
    imageUrl.searchParams.set('table', table)
    imageUrl.searchParams.set('id', block.value.id)
    imageUrl.searchParams.set('cache', 'v2')
  }

  return imageUrl.toString()
}

and used here:

<NotionRenderer
    blockMap={data}
    fullPage
    hideHeader
    mapImageUrl={toNotionImageUrl} // <--- Here
/>

Note: This solution has worked for me, but I cannot guarantee it is the correct one.

Additional Information

This issue affects users who utilize Notion Teamspace and attempt to display images from pages within Teamspace using React Notion. Implementing the provided solution can serve as a temporary workaround until the issue is officially resolved by the React Notion development team.

Links for Reference

These links demonstrate that the image works fine in Notion but not in React Notion, highlighting the issue.

Are there plans to add a renderer for the official Notion API?

  • Notion has released an official API which also returns page blocks similar to what notion-api-worker does, which this package uses.
  • However, the API structure returned by notion-api-worker is a bit different (see below)
  • It would be very useful to add support for rendering both types of API responses, is there plans to support his?

Also, I'm curious to get people's opinion on the following:

We originally used notion-api-worker as our CMS backend, now we're thinking of switching to the official notion API since notion-api-worker says:

Use with caution. This is based on the private Notion API. We can not guarantee it will stay stable.

But notion-api-worker has more feature support than the official API (though perhaps more features will be launched in the future).

So should we continue using the potentially unstable Notion API which has more features?

Or switch to the official API which has fewer features but is (potentially) more stable?

My current thought is we continue using notion-api-worker until the official Notion API has more features or if Notion decided to make it harder to use their private API.

Props `className` did not match

Hey hey, love the project. I'm using it on my blog. I've been trying to debug something with it though. I'm using Next.js with this project. Doing some of the static page generation that came out with next.js 9.4. I've notice something weird though.

When I render a page statically and render it, everything seems fine. However, when the javascript loads on the page right after load and rehydrates the page, it will try to rerender the syntax highlight of the code blocks and throw an error that the server rendered className is not equal to the client side className. This leads the renderer to remove all of the wrapping <span> which denote the various tokens in the code block.

When you load the page with Javascript disabled, everything looks great, but the minute you enable javascript in the browser, the syntax highlight flashes and it goes to a non-highlighted state.

This is the error i'm seeing. I've dug into it a little bit, and don't have any leads on how to debug. Have you seen this? Do you have any leads on how to fix?

react-dom.development.js:530 Warning: Prop `className` did not match. Server: " language-bash" Client: "language-bash"

With JS enabled:

image

With JS disabled:

image

Dark mode issue

Hi, I've just implemented React Notion to my personal site. But there's a problem when I want to implement it with dark mode. Some text doesn't change its color. It happens when I want to render the article from my notion.

I made my website using Next JS, Chakra UI, and React Notion.

Here's my snippet.

 const { colorMode } = useColorMode();        
  const divStyle = {
    WebkitTextFillColor: "white",
  };

return (
{colorMode === "light" ? (
          <Stack px={isDesktopWidth ? 2 : 0}>
            <NotionRenderer blockMap={blocks} />
          </Stack>
        ) : (
          <div style={divStyle}>
            <Stack px={isDesktopWidth ? 2 : 0}>
              <NotionRenderer blockMap={blocks} />
            </Stack>
          </div>
        )}
);

Here are some texts when it's in light mode.
image

Here are some texts when it's in the dark mode,
image

The live version of my article can be accessed at https://yehezgun.com/articles/post/cerita-di-balik-yehezgun-com, you can check it here.

Is this happens because of my code or from the Notion Renderer itself? Thank you in advance.

Backlinks are not rendered

After some investigation, it seems like backlinks are embedded within the text blocks as such

0: "p"
1: "74c1c34b-93ef-4e71-ad88-103a3503cb6a" // id 
2: "dd90a6b9-e00b-4a53-a360-b36f747bc8e6" // space id 
length: 3
__proto__: Array(0)

As a result, the backlink is rendered as a little triangle
Screen Shot 2021-05-25 at 10 53 26 AM
Any workaround that people are aware of? If not, any pointers on what needs to be changed to have it fixed?

Thanks!

block rendering error

Hi,

I noticed that some of my content blocks in Notion are not rendered and seems like it is related to the error message below. Could anyone tell me why this happens and how I can fix this?

error rendering block eed5135d-4bc8-4a73-a97e-c1684b271546 
NotionRenderer@http://localhost:3000/static/js/0.chunk.js:48952:20
main
div
Block@http://localhost:3000/static/js/0.chunk.js:48618:15
NotionRenderer@http://localhost:3000/static/js/0.chunk.js:48952:20
div
ProjectNotion@http://localhost:3000/static/js/main.chunk.js:2068:23
Route@http://localhost:3000/static/js/0.chunk.js:49815:29
div
div
div
Main@http://localhost:3000/static/js/main.chunk.js:1856:19
Route@http://localhost:3000/static/js/0.chunk.js:49815:29
App
ThemeProvider@http://localhost:3000/static/js/0.chunk.js:54115:37
Router@http://localhost:3000/static/js/0.chunk.js:49450:30
HashRouter@http://localhost:3000/static/js/0.chunk.js:49115:35

Project Wont Run Example

I cloned the project here. CD'd into example, ran yarn install, and then when I spin the project up and navigate to localhost:3000. I'm getting this error:

TypeError: can't access property "name", _block$collection3.schema[gp.property] is undefined

Upon inspecting the JSON object returned from the API it looks like notion has possibly changed the format. The below returned is from https://notion-api.splitbee.io/v1/page/2e22de6b770e4166be301490f6ffd420.

{"2e22de6b-770e-4166-be30-1490f6ffd420":{"role":"reader","value":{"id":"2e22de6b-770e-4166-be30-1490f6ffd420","version":407,"type":"page","properties":{"title":[["react-notion example"]]},"content":["959f085a-918d-4a2b-a7cd-e3f3904bc1a9","a927f272-68d3-4298-bee0-e9dcfc8d3749","074ab012-053a-475d-b70e-0cc5583eff58","2e15b932-b9bd-460e-8ca4-60950912b1d2","10c9bd60-abed-457c-80f1-2425d6e21522","77135bf3-fa11-4c19-8397-69ee133ca1ce","cfee83d5-3030-4b32-b2a9-dc174600abef","ffdc6fe9-a0c1-41a1-a44c-64baf889c9a6","db39542f-cf18-4679-9874-fa281dc90a4d","ed47f303-a49d-4b73-a79a-b579a967ccff","7d23e1e0-e2d8-4770-b29f-a44e2acc8da2","001a3d85-1d98-4708-a23b-bf56f138a9cb","58e8b9e1-3b20-4e40-bf1f-9de85153de24","7dbefaf4-3bb3-4e00-9a7c-3785cbbcfcc8","bdc89b35-4ff0-4eac-a01c-7e3c9cb59980","e42e658d-2b8e-4265-8fa1-2a0807a87952","8ee78741-d191-4a00-9227-5979b3498d24","7b4a31bc-76bf-4243-812a-e09a51bd2c2c","278d40df-89ec-46aa-813c-fa7439840ac4","6c4b0669-5ea3-4ca0-bd01-1f407e4d7474","11d8e225-a0dd-4eb2-9d2a-052ab47e0beb","f1f9ea36-1638-43c8-9173-9cfc2024ba6c","77f5e257-09f2-4770-8236-268ab693f31a","60e6b91e-c96e-4424-b96c-c8f095d4b8a2","86173527-f987-4ed5-bb90-a0e289890651","19bc18de-054c-400e-8991-c4f299822acf","d71afe59-86c7-4094-801c-6461c7b40baa","46adc853-f641-45b5-a20f-3221330e0f7e","a9ec04e9-db22-4381-b24f-a992d04051a5","6056518e-6e1a-44bc-a714-16a91248e102","af42b2ac-6c2d-43e9-ab14-169417e6173b","939e71ec-cf04-41e0-b4b3-c9cd2302ad0d","790a3daf-0f52-45c8-ae06-8a74dbb6b227","1a854c41-c86f-48de-828b-98e0163de611","a523933e-2755-4677-bd00-17f8e35fda03","0651e237-24e8-4476-a00b-a1e0afe2000c","3ae5a1d8-92c8-4df3-a8a4-b88a4d741b54","786f8aa5-8c9e-4bfd-8466-ee3c7f3a6d72","0030dc49-8a9f-41f5-94d0-e313208250ef","c866b3c4-c478-4dcc-97b4-0a831d58abfe"],"permissions":[{"role":"reader","type":"public_permission"},{"role":"editor","type":"space_permission"}],"created_time":1587405360000,"last_edited_time":1590780960000,"parent_id":"b5276213-3d36-4d38-adc7-93cf017f36b7","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"959f085a-918d-4a2b-a7cd-e3f3904bc1a9":{"role":"reader","value":{"id":"959f085a-918d-4a2b-a7cd-e3f3904bc1a9","version":13,"type":"image","properties":{"source":[["https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f6115549-e194-4c05-9165-bffc62150d20/79684011-6c948280-822e-11ea-9e23-1644903796fb.png"]]},"format":{"block_width":1828,"display_source":"https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f6115549-e194-4c05-9165-bffc62150d20/79684011-6c948280-822e-11ea-9e23-1644903796fb.png","block_full_width":false,"block_page_width":true,"block_aspect_ratio":0.24835886214442013,"block_preserve_scale":true},"created_time":1587409080000,"last_edited_time":1587409080000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"file_ids":["f6115549-e194-4c05-9165-bffc62150d20"],"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"a927f272-68d3-4298-bee0-e9dcfc8d3749":{"role":"reader","value":{"id":"a927f272-68d3-4298-bee0-e9dcfc8d3749","version":195,"type":"header","properties":{"title":[["react-notion ",[["b"]]],["example",[["h","gray"],["b"]]]]},"created_time":1587405360000,"last_edited_time":1587420300000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"074ab012-053a-475d-b70e-0cc5583eff58":{"role":"reader","value":{"id":"074ab012-053a-475d-b70e-0cc5583eff58","version":15,"type":"text","created_time":1587977100000,"last_edited_time":1587977100000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"2e15b932-b9bd-460e-8ca4-60950912b1d2":{"role":"reader","value":{"id":"2e15b932-b9bd-460e-8ca4-60950912b1d2","version":78,"type":"text","properties":{"title":[["Welcome to this demo page rendered by "],["react-notion",[["c"]]],["."]]},"created_time":1587410460000,"last_edited_time":1587420180000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"10c9bd60-abed-457c-80f1-2425d6e21522":{"role":"reader","value":{"id":"10c9bd60-abed-457c-80f1-2425d6e21522","version":39,"type":"text","created_time":1587410640000,"last_edited_time":1587498900000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"77135bf3-fa11-4c19-8397-69ee133ca1ce":{"role":"reader","value":{"id":"77135bf3-fa11-4c19-8397-69ee133ca1ce","version":88,"type":"text","properties":{"title":[["All kind",[["i"],["h","orange"],["b"]]],[" of "],["text",[["h","yellow_background"],["b"]]],[" styling ",[["h","yellow_background"]]],["options are supported. "]]},"created_time":1587410640000,"last_edited_time":1587410700000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"cfee83d5-3030-4b32-b2a9-dc174600abef":{"role":"reader","value":{"id":"cfee83d5-3030-4b32-b2a9-dc174600abef","version":2,"type":"text","created_time":1587410040000,"last_edited_time":1587410640000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"ffdc6fe9-a0c1-41a1-a44c-64baf889c9a6":{"role":"reader","value":{"id":"ffdc6fe9-a0c1-41a1-a44c-64baf889c9a6","version":197,"type":"callout","properties":{"title":[[" Compare this page to the "],["original Notion page",[["a","https://www.notion.so/react-notion-example-2e22de6b770e4166be301490f6ffd420"]]]]},"format":{"page_icon":"🔍","block_color":"yellow_background"},"created_time":1587410061269,"last_edited_time":1587463680000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"copied_from":"a374a0d0-39ba-4599-900b-dcfee7d32d48","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"db39542f-cf18-4679-9874-fa281dc90a4d":{"role":"reader","value":{"id":"db39542f-cf18-4679-9874-fa281dc90a4d","version":31,"type":"text","created_time":1590503040000,"last_edited_time":1590503040000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"ed47f303-a49d-4b73-a79a-b579a967ccff":{"role":"reader","value":{"id":"ed47f303-a49d-4b73-a79a-b579a967ccff","version":55,"type":"sub_sub_header","properties":{"title":[["Supported Features"]]},"created_time":1590503040000,"last_edited_time":1590503040000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"7d23e1e0-e2d8-4770-b29f-a44e2acc8da2":{"role":"reader","value":{"id":"7d23e1e0-e2d8-4770-b29f-a44e2acc8da2","version":88,"type":"page","properties":{"title":[["Lists"]]},"content":["457fd62e-186d-4136-bf2b-e3a607afa8c2","a3e67089-ce03-48d6-95f6-792f62c15136","e9d60d88-d0e6-4efe-aade-a4534039921a","c3351276-0898-4cf6-8eef-ba22eaf102d5","14895d49-baa4-44bd-9279-14a95b034d90","7b9d18e1-9abb-4409-a925-a8bcb31ab358","b59a7b8d-ed8f-4a9b-a7e4-94273fda6288","b4e16c37-e9e5-4c7c-9285-accf6cffbfc3","31aba608-4a22-4ea7-8bd7-99de1c600889"],"format":{"page_icon":"🔢","page_cover":"/images/page-cover/met_william_morris_1877_willow.jpg","page_cover_position":0.1},"created_time":1590503073270,"last_edited_time":1590503580000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"001a3d85-1d98-4708-a23b-bf56f138a9cb":{"role":"reader","value":{"id":"001a3d85-1d98-4708-a23b-bf56f138a9cb","version":43,"type":"page","properties":{"title":[["Full width"]]},"content":["47a58694-f4ef-4313-8b95-22f3aad4d116","5bc31114-a491-41a4-9bba-fca5cc7a31bd","42684581-0a10-48d1-a573-741f8a034dfa","40f314e4-ba36-47b0-bb7a-8c0da82fdb7e"],"format":{"page_icon":"↔️","page_full_width":true},"created_time":1590503344671,"last_edited_time":1590503400000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"58e8b9e1-3b20-4e40-bf1f-9de85153de24":{"role":"reader","value":{"id":"58e8b9e1-3b20-4e40-bf1f-9de85153de24","version":26,"type":"page","properties":{"title":[["Small Text"]]},"content":["eb09f782-04c7-468f-8ef8-92ccf53011ef","cf808774-0447-4504-996d-e60a09b1becc","f80e83a0-c8e1-44e6-bcd6-3134f4ded4b0","56bc0bed-1571-4df5-b537-f734ae72e283","6a7d3fb2-4f96-4036-98ea-c0c43eb6de0b"],"format":{"page_icon":"🔍","page_small_text":true},"created_time":1590503484241,"last_edited_time":1590503520000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"7dbefaf4-3bb3-4e00-9a7c-3785cbbcfcc8":{"role":"reader","value":{"id":"7dbefaf4-3bb3-4e00-9a7c-3785cbbcfcc8","version":3,"type":"sub_sub_header","properties":{"title":[["List"]]},"created_time":1587410520000,"last_edited_time":1590503460000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"bdc89b35-4ff0-4eac-a01c-7e3c9cb59980":{"role":"reader","value":{"id":"bdc89b35-4ff0-4eac-a01c-7e3c9cb59980","version":10,"type":"column_list","content":["d28aeb5a-99f4-414d-99fd-553d6546a80d","1a398bae-3db0-4bb5-a95b-2f599c9a7ffb"],"created_time":1589563020000,"last_edited_time":1589563020000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"d28aeb5a-99f4-414d-99fd-553d6546a80d":{"role":"reader","value":{"id":"d28aeb5a-99f4-414d-99fd-553d6546a80d","version":25,"type":"column","content":["e9efe849-ec77-4336-af74-9336207b47ad","4d405cf4-3fad-4670-8106-ab4f0882e2d4","c886d17a-fd5a-4cd9-a029-22c8a4663c91","4be311d8-233b-4738-bc59-59003e8a5bdc"],"format":{"column_ratio":0.5},"created_time":1589563020000,"last_edited_time":1590091500000,"parent_id":"bdc89b35-4ff0-4eac-a01c-7e3c9cb59980","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"1a398bae-3db0-4bb5-a95b-2f599c9a7ffb":{"role":"reader","value":{"id":"1a398bae-3db0-4bb5-a95b-2f599c9a7ffb","version":26,"type":"column","content":["9f5abb10-f72b-40e7-946e-15ac2c34b823","b0d7612c-f96a-47fc-bdf9-946714033744","6552b07c-184a-454f-8eee-29479f4d569e"],"format":{"column_ratio":0.5},"created_time":1589563020000,"last_edited_time":1590091500000,"parent_id":"bdc89b35-4ff0-4eac-a01c-7e3c9cb59980","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"e9efe849-ec77-4336-af74-9336207b47ad":{"role":"reader","value":{"id":"e9efe849-ec77-4336-af74-9336207b47ad","version":114,"type":"bulleted_list","properties":{"title":[["First Item"]]},"created_time":1590091440000,"last_edited_time":1590091500000,"parent_id":"d28aeb5a-99f4-414d-99fd-553d6546a80d","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"9f5abb10-f72b-40e7-946e-15ac2c34b823":{"role":"reader","value":{"id":"9f5abb10-f72b-40e7-946e-15ac2c34b823","version":54,"type":"numbered_list","properties":{"title":[["First Item"]]},"content":["0d3543c2-14d3-4e4d-bc5c-c7087732e137","e58d2329-bc55-4300-a2c4-7c5173a2e37e"],"created_time":1589563049647,"last_edited_time":1590091500000,"parent_id":"1a398bae-3db0-4bb5-a95b-2f599c9a7ffb","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"0d3543c2-14d3-4e4d-bc5c-c7087732e137":{"role":"reader","value":{"id":"0d3543c2-14d3-4e4d-bc5c-c7087732e137","version":25,"type":"numbered_list","properties":{"title":[["Item 1"]]},"content":["14a245b8-bbe1-4517-b897-93f8e2cb3fc1","2248a061-733b-486c-9b14-a077137345ab"],"created_time":1589563020000,"last_edited_time":1589563020000,"parent_id":"9f5abb10-f72b-40e7-946e-15ac2c34b823","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"14a245b8-bbe1-4517-b897-93f8e2cb3fc1":{"role":"reader","value":{"id":"14a245b8-bbe1-4517-b897-93f8e2cb3fc1","version":17,"type":"numbered_list","properties":{"title":[["Nested"]]},"created_time":1589563020000,"last_edited_time":1589563020000,"parent_id":"0d3543c2-14d3-4e4d-bc5c-c7087732e137","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"2248a061-733b-486c-9b14-a077137345ab":{"role":"reader","value":{"id":"2248a061-733b-486c-9b14-a077137345ab","version":18,"type":"numbered_list","properties":{"title":[["Nested"]]},"created_time":1589563020000,"last_edited_time":1589563020000,"parent_id":"0d3543c2-14d3-4e4d-bc5c-c7087732e137","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"e58d2329-bc55-4300-a2c4-7c5173a2e37e":{"role":"reader","value":{"id":"e58d2329-bc55-4300-a2c4-7c5173a2e37e","version":17,"type":"numbered_list","properties":{"title":[["Item 2"]]},"created_time":1589563020000,"last_edited_time":1589563020000,"parent_id":"9f5abb10-f72b-40e7-946e-15ac2c34b823","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"4d405cf4-3fad-4670-8106-ab4f0882e2d4":{"role":"reader","value":{"id":"4d405cf4-3fad-4670-8106-ab4f0882e2d4","version":26,"type":"bulleted_list","properties":{"title":[["Second Item"]]},"created_time":1590091500000,"last_edited_time":1590091500000,"parent_id":"d28aeb5a-99f4-414d-99fd-553d6546a80d","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"b0d7612c-f96a-47fc-bdf9-946714033744":{"role":"reader","value":{"id":"b0d7612c-f96a-47fc-bdf9-946714033744","version":19,"type":"numbered_list","properties":{"title":[["Second Point"]]},"created_time":1590091503146,"last_edited_time":1590091500000,"parent_id":"1a398bae-3db0-4bb5-a95b-2f599c9a7ffb","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"c886d17a-fd5a-4cd9-a029-22c8a4663c91":{"role":"reader","value":{"id":"c886d17a-fd5a-4cd9-a029-22c8a4663c91","version":22,"type":"bulleted_list","properties":{"title":[["Third Icon"]]},"created_time":1590091500000,"last_edited_time":1590091500000,"parent_id":"d28aeb5a-99f4-414d-99fd-553d6546a80d","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"6552b07c-184a-454f-8eee-29479f4d569e":{"role":"reader","value":{"id":"6552b07c-184a-454f-8eee-29479f4d569e","version":22,"type":"numbered_list","properties":{"title":[["Third Point"]]},"created_time":1590091500000,"last_edited_time":1590091500000,"parent_id":"1a398bae-3db0-4bb5-a95b-2f599c9a7ffb","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"4be311d8-233b-4738-bc59-59003e8a5bdc":{"role":"reader","value":{"id":"4be311d8-233b-4738-bc59-59003e8a5bdc","version":24,"type":"bulleted_list","properties":{"title":[["Sublist"]]},"content":["70ad8f77-c7b1-47f1-ac43-6e77b74838e5","964ded56-d04c-422d-b139-e10183cd8f09"],"created_time":1587405806932,"last_edited_time":1590091500000,"parent_id":"d28aeb5a-99f4-414d-99fd-553d6546a80d","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"70ad8f77-c7b1-47f1-ac43-6e77b74838e5":{"role":"reader","value":{"id":"70ad8f77-c7b1-47f1-ac43-6e77b74838e5","version":23,"type":"bulleted_list","properties":{"title":[["Item 1"]]},"content":["1648d172-5703-4059-9060-8dd859c0828b","5d9e807d-ca78-401c-a0cd-5c3f1d9271d2"],"created_time":1587410520000,"last_edited_time":1590091440000,"parent_id":"4be311d8-233b-4738-bc59-59003e8a5bdc","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"1648d172-5703-4059-9060-8dd859c0828b":{"role":"reader","value":{"id":"1648d172-5703-4059-9060-8dd859c0828b","version":30,"type":"bulleted_list","properties":{"title":[["Nested"]]},"created_time":1587978720000,"last_edited_time":1587978720000,"parent_id":"70ad8f77-c7b1-47f1-ac43-6e77b74838e5","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"5d9e807d-ca78-401c-a0cd-5c3f1d9271d2":{"role":"reader","value":{"id":"5d9e807d-ca78-401c-a0cd-5c3f1d9271d2","version":18,"type":"bulleted_list","properties":{"title":[["Nested"]]},"created_time":1587978720000,"last_edited_time":1587984240000,"parent_id":"70ad8f77-c7b1-47f1-ac43-6e77b74838e5","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"964ded56-d04c-422d-b139-e10183cd8f09":{"role":"reader","value":{"id":"964ded56-d04c-422d-b139-e10183cd8f09","version":92,"type":"bulleted_list","properties":{"title":[["Item 2"]]},"created_time":1587410040000,"last_edited_time":1590091440000,"parent_id":"4be311d8-233b-4738-bc59-59003e8a5bdc","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"e42e658d-2b8e-4265-8fa1-2a0807a87952":{"role":"reader","value":{"id":"e42e658d-2b8e-4265-8fa1-2a0807a87952","version":10,"type":"text","created_time":1587410880000,"last_edited_time":1587410880000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"8ee78741-d191-4a00-9227-5979b3498d24":{"role":"reader","value":{"id":"8ee78741-d191-4a00-9227-5979b3498d24","version":113,"type":"quote","properties":{"title":[["This is an example quote."]]},"created_time":1587410022165,"last_edited_time":1587415740000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"copied_from":"ab550245-d7ec-4baa-9a29-781d6a0b02c1","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"7b4a31bc-76bf-4243-812a-e09a51bd2c2c":{"role":"reader","value":{"id":"7b4a31bc-76bf-4243-812a-e09a51bd2c2c","version":17,"type":"text","created_time":1590252480000,"last_edited_time":1590252480000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"278d40df-89ec-46aa-813c-fa7439840ac4":{"role":"reader","value":{"id":"278d40df-89ec-46aa-813c-fa7439840ac4","version":9,"type":"toggle","properties":{"title":[["You can toggle this list"]]},"content":["20820346-3a3f-41e7-a4c6-062e28c91ccd"],"created_time":1590252492387,"last_edited_time":1590252492387,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"copied_from":"63e9cd8f-a10c-48f4-84db-a82e596b99ee","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"6c4b0669-5ea3-4ca0-bd01-1f407e4d7474":{"role":"reader","value":{"id":"6c4b0669-5ea3-4ca0-bd01-1f407e4d7474","version":2,"type":"text","created_time":1587417900000,"last_edited_time":1590252480000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"11d8e225-a0dd-4eb2-9d2a-052ab47e0beb":{"role":"reader","value":{"id":"11d8e225-a0dd-4eb2-9d2a-052ab47e0beb","version":7,"type":"divider","created_time":1587410906896,"last_edited_time":1587410880000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"f1f9ea36-1638-43c8-9173-9cfc2024ba6c":{"role":"reader","value":{"id":"f1f9ea36-1638-43c8-9173-9cfc2024ba6c","version":40,"type":"sub_header","properties":{"title":[["Complex Layouts"]]},"created_time":1587405780000,"last_edited_time":1587411480000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"77f5e257-09f2-4770-8236-268ab693f31a":{"role":"reader","value":{"id":"77f5e257-09f2-4770-8236-268ab693f31a","version":13,"type":"column_list","content":["7707c5de-1663-496d-b6a1-9a01fd11cd33","2735c1c5-6b7d-4d18-9c39-31f15be1fd94"],"created_time":1587409380000,"last_edited_time":1587409920000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"7707c5de-1663-496d-b6a1-9a01fd11cd33":{"role":"reader","value":{"id":"7707c5de-1663-496d-b6a1-9a01fd11cd33","version":27,"type":"column","content":["08299481-b6aa-40d8-978c-1df557e2880c","a1498ed5-6eb9-4191-b19a-d8290496e906","bc78619b-57e2-42f6-9307-106ede7df255"],"format":{"column_ratio":0.5},"created_time":1587409380000,"last_edited_time":1587411180000,"parent_id":"77f5e257-09f2-4770-8236-268ab693f31a","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"2735c1c5-6b7d-4d18-9c39-31f15be1fd94":{"role":"reader","value":{"id":"2735c1c5-6b7d-4d18-9c39-31f15be1fd94","version":39,"type":"column","content":["9d188b6d-ef94-4e23-be62-e9ae8252a009","7fb3f694-ec0a-41c6-b787-22ce48ec4be4","c916bf1b-2738-4df5-95b5-7aa7ebc82c7e","593ead9d-7b71-4ef1-9fef-251959ffe6e6"],"format":{"column_ratio":0.5000000000000002},"created_time":1587409380000,"last_edited_time":1587983160000,"parent_id":"77f5e257-09f2-4770-8236-268ab693f31a","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"08299481-b6aa-40d8-978c-1df557e2880c":{"role":"reader","value":{"id":"08299481-b6aa-40d8-978c-1df557e2880c","version":74,"type":"image","properties":{"source":[["https://s3-us-west-2.amazonaws.com/secure.notion-static.com/adac4e1e-1a94-4306-b41f-57f80b45f90d/roger-bradshaw-7o3uFw2xrAk-unsplash.jpg"]],"caption":[["This is an"],[" ",[["b"]]],["image caption",[["i"],["b"]]]]},"format":{"block_width":500,"block_height":333,"display_source":"https://s3-us-west-2.amazonaws.com/secure.notion-static.com/adac4e1e-1a94-4306-b41f-57f80b45f90d/roger-bradshaw-7o3uFw2xrAk-unsplash.jpg","block_full_width":false,"block_page_width":false,"block_aspect_ratio":0.666,"block_preserve_scale":true},"created_time":1587409380000,"last_edited_time":1587411300000,"parent_id":"7707c5de-1663-496d-b6a1-9a01fd11cd33","parent_table":"block","alive":true,"file_ids":["ecd873aa-0009-43da-be68-626c835410d9","adac4e1e-1a94-4306-b41f-57f80b45f90d"],"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"9d188b6d-ef94-4e23-be62-e9ae8252a009":{"role":"reader","value":{"id":"9d188b6d-ef94-4e23-be62-e9ae8252a009","version":21,"type":"image","properties":{"source":[["https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d4b5070d-5e28-40bf-a4a5-2200e147aa84/ricardo-gomez-angel-geBHIpvA6us-unsplash.jpg"]]},"format":{"block_width":400,"block_height":417,"display_source":"https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d4b5070d-5e28-40bf-a4a5-2200e147aa84/ricardo-gomez-angel-geBHIpvA6us-unsplash.jpg","block_full_width":false,"block_page_width":false,"block_aspect_ratio":1.0425,"block_preserve_scale":true},"created_time":1587409380000,"last_edited_time":1587410820000,"parent_id":"2735c1c5-6b7d-4d18-9c39-31f15be1fd94","parent_table":"block","alive":true,"file_ids":["9d629ec4-7876-464e-97a5-af8d91407de6","d4b5070d-5e28-40bf-a4a5-2200e147aa84"],"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"a1498ed5-6eb9-4191-b19a-d8290496e906":{"role":"reader","value":{"id":"a1498ed5-6eb9-4191-b19a-d8290496e906","version":25,"type":"image","properties":{"source":[["https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fc4a23e4-7898-4afa-ac20-e7834097a605/marsumilae-Og4S8NW-p_I-unsplash.jpg"]]},"format":{"block_width":500,"block_height":281,"display_source":"https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fc4a23e4-7898-4afa-ac20-e7834097a605/marsumilae-Og4S8NW-p_I-unsplash.jpg","block_full_width":false,"block_page_width":false,"block_aspect_ratio":0.562,"block_preserve_scale":true},"created_time":1587409380000,"last_edited_time":1587410820000,"parent_id":"7707c5de-1663-496d-b6a1-9a01fd11cd33","parent_table":"block","alive":true,"file_ids":["97c8c13f-e55c-40c1-9235-cbb7ccd2ea49","fc4a23e4-7898-4afa-ac20-e7834097a605"],"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"7fb3f694-ec0a-41c6-b787-22ce48ec4be4":{"role":"reader","value":{"id":"7fb3f694-ec0a-41c6-b787-22ce48ec4be4","version":57,"type":"sub_sub_header","properties":{"title":[["Nesting works just fine."]]},"created_time":1587411395881,"last_edited_time":1587415800000,"parent_id":"2735c1c5-6b7d-4d18-9c39-31f15be1fd94","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"bc78619b-57e2-42f6-9307-106ede7df255":{"role":"reader","value":{"id":"bc78619b-57e2-42f6-9307-106ede7df255","version":17,"type":"text","created_time":1587410580000,"last_edited_time":1587410880000,"parent_id":"7707c5de-1663-496d-b6a1-9a01fd11cd33","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"c916bf1b-2738-4df5-95b5-7aa7ebc82c7e":{"role":"reader","value":{"id":"c916bf1b-2738-4df5-95b5-7aa7ebc82c7e","version":272,"type":"text","properties":{"title":[["It is also responsive."]]},"created_time":1587411360000,"last_edited_time":1587469140000,"parent_id":"2735c1c5-6b7d-4d18-9c39-31f15be1fd94","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"593ead9d-7b71-4ef1-9fef-251959ffe6e6":{"role":"reader","value":{"id":"593ead9d-7b71-4ef1-9fef-251959ffe6e6","version":8,"type":"text","created_time":1587411420000,"last_edited_time":1587411420000,"parent_id":"2735c1c5-6b7d-4d18-9c39-31f15be1fd94","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"60e6b91e-c96e-4424-b96c-c8f095d4b8a2":{"role":"reader","value":{"id":"60e6b91e-c96e-4424-b96c-c8f095d4b8a2","version":6,"type":"divider","created_time":1587410912082,"last_edited_time":1587411180000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"copied_from":"11d8e225-a0dd-4eb2-9d2a-052ab47e0beb","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"86173527-f987-4ed5-bb90-a0e289890651":{"role":"reader","value":{"id":"86173527-f987-4ed5-bb90-a0e289890651","version":54,"type":"text","created_time":1587977100000,"last_edited_time":1587977100000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"19bc18de-054c-400e-8991-c4f299822acf":{"role":"reader","value":{"id":"19bc18de-054c-400e-8991-c4f299822acf","version":3,"type":"bookmark","properties":{"link":[["https://github.com"]],"title":[["Build software better, together"]],"description":[["GitHub brings together the world's largest community of developers to discover, share, and build better software. From open source projects to private team repositories, we're your all-in-one platform for collaborative development."]]},"format":{"bookmark_icon":"https://github.com/favicon.ico","bookmark_cover":"https://github.githubassets.com/images/modules/open_graph/github-logo.png"},"created_time":1587977172998,"last_edited_time":1587977160000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"copied_from":"534179fe-2db6-47ad-80ba-5865514f6a1b","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"d71afe59-86c7-4094-801c-6461c7b40baa":{"role":"reader","value":{"id":"d71afe59-86c7-4094-801c-6461c7b40baa","version":14,"type":"divider","created_time":1587409860000,"last_edited_time":1587977100000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"46adc853-f641-45b5-a20f-3221330e0f7e":{"role":"reader","value":{"id":"46adc853-f641-45b5-a20f-3221330e0f7e","version":8,"type":"text","created_time":1587977123744,"last_edited_time":1587977100000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"a9ec04e9-db22-4381-b24f-a992d04051a5":{"role":"reader","value":{"id":"a9ec04e9-db22-4381-b24f-a992d04051a5","version":10,"type":"column_list","content":["8385ee55-1393-49ad-9c7a-f959fbd9cc8d","a88299ed-67cf-426c-a5d2-565d4d826700"],"created_time":1587415260000,"last_edited_time":1587415260000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"8385ee55-1393-49ad-9c7a-f959fbd9cc8d":{"role":"reader","value":{"id":"8385ee55-1393-49ad-9c7a-f959fbd9cc8d","version":12,"type":"column","content":["4b3c1178-7dfd-4c01-8e22-ecb239e13132","c12890df-642f-4046-ac45-489a40c140cb"],"format":{"column_ratio":0.3125},"created_time":1587415260000,"last_edited_time":1587415260000,"parent_id":"a9ec04e9-db22-4381-b24f-a992d04051a5","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"a88299ed-67cf-426c-a5d2-565d4d826700":{"role":"reader","value":{"id":"a88299ed-67cf-426c-a5d2-565d4d826700","version":16,"type":"column","content":["701b9f28-b90f-4a88-a0aa-5181d9e15940","706bbb05-d974-466c-8938-3712e4db2aaa"],"format":{"column_ratio":0.6875},"created_time":1587415260000,"last_edited_time":1587418980000,"parent_id":"a9ec04e9-db22-4381-b24f-a992d04051a5","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"4b3c1178-7dfd-4c01-8e22-ecb239e13132":{"role":"reader","value":{"id":"4b3c1178-7dfd-4c01-8e22-ecb239e13132","version":31,"type":"callout","properties":{"title":[["Code Snippet"]]},"format":{"page_icon":"💻","block_color":"blue_background"},"created_time":1587415267644,"last_edited_time":1587463680000,"parent_id":"8385ee55-1393-49ad-9c7a-f959fbd9cc8d","parent_table":"block","alive":true,"copied_from":"9e328328-2100-4120-86ed-5a291871ed23","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"701b9f28-b90f-4a88-a0aa-5181d9e15940":{"role":"reader","value":{"id":"701b9f28-b90f-4a88-a0aa-5181d9e15940","version":54,"type":"code","properties":{"title":[["const Example = () => (\n  <div style={{ maxWidth: 768 }}>\n    <NotionRenderer blockMap={blockMap} />\n  </div>\n);"]],"language":[["JavaScript"]]},"created_time":1587409380000,"last_edited_time":1587415260000,"parent_id":"a88299ed-67cf-426c-a5d2-565d4d826700","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"c12890df-642f-4046-ac45-489a40c140cb":{"role":"reader","value":{"id":"c12890df-642f-4046-ac45-489a40c140cb","version":5,"type":"text","created_time":1587415267645,"last_edited_time":1587415260000,"parent_id":"8385ee55-1393-49ad-9c7a-f959fbd9cc8d","parent_table":"block","alive":true,"copied_from":"29f586f2-f853-4c30-9dbc-71ccff8b6d36","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"706bbb05-d974-466c-8938-3712e4db2aaa":{"role":"reader","value":{"id":"706bbb05-d974-466c-8938-3712e4db2aaa","version":37,"type":"text","created_time":1587417242789,"last_edited_time":1587417240000,"parent_id":"a88299ed-67cf-426c-a5d2-565d4d826700","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"6056518e-6e1a-44bc-a714-16a91248e102":{"role":"reader","value":{"id":"6056518e-6e1a-44bc-a714-16a91248e102","version":18,"type":"text","created_time":1587415560000,"last_edited_time":1587415560000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"af42b2ac-6c2d-43e9-ab14-169417e6173b":{"role":"reader","value":{"id":"af42b2ac-6c2d-43e9-ab14-169417e6173b","version":2,"type":"text","created_time":1587415080000,"last_edited_time":1587415560000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"939e71ec-cf04-41e0-b4b3-c9cd2302ad0d":{"role":"reader","value":{"id":"939e71ec-cf04-41e0-b4b3-c9cd2302ad0d","version":10,"type":"column_list","content":["2d4677f3-09e4-4026-801a-1d0dba2113fb","3ea4bc44-9d35-4a46-a8d7-7a1a539e74c0"],"created_time":1587415140000,"last_edited_time":1587415140000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"2d4677f3-09e4-4026-801a-1d0dba2113fb":{"role":"reader","value":{"id":"2d4677f3-09e4-4026-801a-1d0dba2113fb","version":21,"type":"column","content":["9e328328-2100-4120-86ed-5a291871ed23","29f586f2-f853-4c30-9dbc-71ccff8b6d36"],"format":{"column_ratio":0.3125},"created_time":1587415140000,"last_edited_time":1587415260000,"parent_id":"939e71ec-cf04-41e0-b4b3-c9cd2302ad0d","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"3ea4bc44-9d35-4a46-a8d7-7a1a539e74c0":{"role":"reader","value":{"id":"3ea4bc44-9d35-4a46-a8d7-7a1a539e74c0","version":15,"type":"column","content":["8fd1ed30-dee9-4e81-a877-06c26b0dc92b"],"format":{"column_ratio":0.6875},"created_time":1587415140000,"last_edited_time":1587415200000,"parent_id":"939e71ec-cf04-41e0-b4b3-c9cd2302ad0d","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"9e328328-2100-4120-86ed-5a291871ed23":{"role":"reader","value":{"id":"9e328328-2100-4120-86ed-5a291871ed23","version":116,"type":"callout","properties":{"title":[["Video Embed"]]},"format":{"page_icon":"📹","block_color":"teal_background"},"created_time":1587414166977,"last_edited_time":1587463680000,"parent_id":"2d4677f3-09e4-4026-801a-1d0dba2113fb","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"8fd1ed30-dee9-4e81-a877-06c26b0dc92b":{"role":"reader","value":{"id":"8fd1ed30-dee9-4e81-a877-06c26b0dc92b","version":14,"type":"video","properties":{"source":[["https://www.youtube.com/watch?v=aqz-KE-bpKQ"]]},"format":{"block_width":432,"display_source":"https://www.youtube.com/embed/aqz-KE-bpKQ?feature=oembed","block_full_width":false,"block_page_width":false,"block_aspect_ratio":0.5620608899297423,"block_preserve_scale":true},"created_time":1587414149796,"last_edited_time":1587415140000,"parent_id":"3ea4bc44-9d35-4a46-a8d7-7a1a539e74c0","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"29f586f2-f853-4c30-9dbc-71ccff8b6d36":{"role":"reader","value":{"id":"29f586f2-f853-4c30-9dbc-71ccff8b6d36","version":8,"type":"text","created_time":1587415140000,"last_edited_time":1587415140000,"parent_id":"2d4677f3-09e4-4026-801a-1d0dba2113fb","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"790a3daf-0f52-45c8-ae06-8a74dbb6b227":{"role":"reader","value":{"id":"790a3daf-0f52-45c8-ae06-8a74dbb6b227","version":35,"type":"text","created_time":1587415560000,"last_edited_time":1587415560000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"1a854c41-c86f-48de-828b-98e0163de611":{"role":"reader","value":{"id":"1a854c41-c86f-48de-828b-98e0163de611","version":10,"type":"text","created_time":1587415560000,"last_edited_time":1587415560000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"a523933e-2755-4677-bd00-17f8e35fda03":{"role":"reader","value":{"id":"a523933e-2755-4677-bd00-17f8e35fda03","version":2,"type":"text","created_time":1587414180000,"last_edited_time":1587415560000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"0651e237-24e8-4476-a00b-a1e0afe2000c":{"role":"reader","value":{"id":"0651e237-24e8-4476-a00b-a1e0afe2000c","version":17,"type":"column_list","content":["96366d59-c840-469d-84fd-65c9d6bbce4c","30bdde01-5373-466b-bac3-28b87dbf1b55"],"created_time":1587415200000,"last_edited_time":1587476400000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"96366d59-c840-469d-84fd-65c9d6bbce4c":{"role":"reader","value":{"id":"96366d59-c840-469d-84fd-65c9d6bbce4c","version":22,"type":"column","content":["e6b8db27-ddb6-4e5a-915b-c238305c9085","6e79a13b-2427-4929-9035-e7600fcf9352"],"format":{"column_ratio":0.3125},"created_time":1587415200000,"last_edited_time":1587476400000,"parent_id":"0651e237-24e8-4476-a00b-a1e0afe2000c","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"30bdde01-5373-466b-bac3-28b87dbf1b55":{"role":"reader","value":{"id":"30bdde01-5373-466b-bac3-28b87dbf1b55","version":30,"type":"column","content":["1f729ddb-9c9c-478a-93ca-45fd858b825b","e67a4915-1607-4d70-b333-8706eae29152"],"format":{"column_ratio":0.6875},"created_time":1587415200000,"last_edited_time":1587476520000,"parent_id":"0651e237-24e8-4476-a00b-a1e0afe2000c","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"e6b8db27-ddb6-4e5a-915b-c238305c9085":{"role":"reader","value":{"id":"e6b8db27-ddb6-4e5a-915b-c238305c9085","version":65,"type":"callout","properties":{"title":[["Custom Content"]]},"format":{"page_icon":"🖼️","block_color":"yellow_background"},"created_time":1587415238452,"last_edited_time":1587476400000,"parent_id":"96366d59-c840-469d-84fd-65c9d6bbce4c","parent_table":"block","alive":true,"copied_from":"9e328328-2100-4120-86ed-5a291871ed23","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"1f729ddb-9c9c-478a-93ca-45fd858b825b":{"role":"reader","value":{"id":"1f729ddb-9c9c-478a-93ca-45fd858b825b","version":50,"type":"embed","properties":{"source":[["https://www.openstreetmap.org/export/embed.html?bbox=13.3964,52.5147,13.4185,52.5251&amp;marker=52.52,13.408&amp;layer=mapnik"]]},"format":{"block_width":720,"block_height":320,"display_source":"https://www.openstreetmap.org/export/embed.html?bbox=13.3964,52.5147,13.4185,52.5251&amp;marker=52.52,13.408&amp;layer=mapnik","block_full_width":false,"block_page_width":true,"block_preserve_scale":false},"created_time":1587414215513,"last_edited_time":1587476580000,"parent_id":"30bdde01-5373-466b-bac3-28b87dbf1b55","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"6e79a13b-2427-4929-9035-e7600fcf9352":{"role":"reader","value":{"id":"6e79a13b-2427-4929-9035-e7600fcf9352","version":15,"type":"text","created_time":1587415260000,"last_edited_time":1587476400000,"parent_id":"96366d59-c840-469d-84fd-65c9d6bbce4c","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"e67a4915-1607-4d70-b333-8706eae29152":{"role":"reader","value":{"id":"e67a4915-1607-4d70-b333-8706eae29152","version":8,"type":"text","created_time":1587476520000,"last_edited_time":1587476520000,"parent_id":"30bdde01-5373-466b-bac3-28b87dbf1b55","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"3ae5a1d8-92c8-4df3-a8a4-b88a4d741b54":{"role":"reader","value":{"id":"3ae5a1d8-92c8-4df3-a8a4-b88a4d741b54","version":8,"type":"collection_view","view_ids":["1a28f59f-5a42-460b-abff-bb05d8396d8b"],"collection_id":"6887d852-2d5d-422f-ac16-6ce46a98ec21","created_time":1590780066022,"last_edited_time":1590780180000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"},"collection":{"title":[["titled"]],"schema":{"a6R!":{"name":"Tags","type":"multi_select","options":[{"id":"991cb1b4-0d6b-4b04-b9ae-b18344b714b8","color":"yellow","value":"tag"}]},"title":{"name":"Name","type":"title"}},"types":[{"id":"1a28f59f-5a42-460b-abff-bb05d8396d8b","version":1,"type":"table","name":"Default view","format":{"table_wrap":true,"table_properties":[{"width":276,"visible":true,"property":"title"},{"visible":true,"property":"a6R!"},{"visible":true,"property":"m~|v"}]},"parent_id":"3ae5a1d8-92c8-4df3-a8a4-b88a4d741b54","parent_table":"block","alive":true,"page_sort":["9e3af432-da5d-4f94-ab00-5590268584fe","34d5f1f7-f112-46c9-85dd-5965d039d9b7","2cbb89cf-4b28-469c-8fc1-3f756481983b"],"query2":{"aggregations":[{"property":"title","aggregator":"count"}]}}],"data":[{"id":"9e3af432-da5d-4f94-ab00-5590268584fe","Tags":[["tag"]],"Name":[["a"]]},{"id":"34d5f1f7-f112-46c9-85dd-5965d039d9b7","Name":[["b"]]},{"id":"2cbb89cf-4b28-469c-8fc1-3f756481983b","Name":[["cdef"]]}]}},"786f8aa5-8c9e-4bfd-8466-ee3c7f3a6d72":{"role":"reader","value":{"id":"786f8aa5-8c9e-4bfd-8466-ee3c7f3a6d72","version":11,"type":"divider","created_time":1587415238453,"last_edited_time":1587416820000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"copied_from":"29f586f2-f853-4c30-9dbc-71ccff8b6d36","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}},"0030dc49-8a9f-41f5-94d0-e313208250ef":{"role":"reader","value":{"id":"0030dc49-8a9f-41f5-94d0-e313208250ef","version":15,"type":"collection_view","view_ids":["03255514-51e2-4679-bfcf-cf2f18312e3f"],"collection_id":"4f8b9b04-88ab-4360-bd1f-33852256b7b0","created_time":1590780973765,"last_edited_time":1590780960000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"38159360-3514-4f55-8058-80cd8b9f6114","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"},"collection":{"title":[["titled"]],"schema":{"a6R!":{"name":"Tags","type":"multi_select","options":[{"id":"991cb1b4-0d6b-4b04-b9ae-b18344b714b8","color":"yellow","value":"tag"}]},"title":{"name":"Name","type":"title"}},"types":[{"id":"03255514-51e2-4679-bfcf-cf2f18312e3f","version":1,"type":"table","name":"Default view","format":{"table_wrap":true,"table_properties":[{"width":276,"visible":true,"property":"title"},{"visible":true,"property":"r~!~"},{"visible":true,"property":"[XF9"}]},"parent_id":"0030dc49-8a9f-41f5-94d0-e313208250ef","parent_table":"block","alive":true,"page_sort":["263f4636-8f49-4523-8b6b-26dc77ec730f","5e8d9f95-e070-4436-b0ad-852c553e02f9","ebf71cbe-eae6-4ea4-92ed-e65aac2da3c9"],"query2":{"aggregations":[{"property":"title","aggregator":"count"}]}}],"data":[{"id":"9e3af432-da5d-4f94-ab00-5590268584fe","Tags":[["tag"]],"Name":[["a"]]},{"id":"34d5f1f7-f112-46c9-85dd-5965d039d9b7","Name":[["b"]]},{"id":"2cbb89cf-4b28-469c-8fc1-3f756481983b","Name":[["cdef"]]}]}},"c866b3c4-c478-4dcc-97b4-0a831d58abfe":{"role":"reader","value":{"id":"c866b3c4-c478-4dcc-97b4-0a831d58abfe","version":54,"type":"text","properties":{"title":[["GitHub",[["h","gray"],["a","https://github.com/splitbee/react-notion"]]]]},"created_time":1587416834013,"last_edited_time":1590780960000,"parent_id":"2e22de6b-770e-4166-be30-1490f6ffd420","parent_table":"block","alive":true,"created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"38159360-3514-4f55-8058-80cd8b9f6114"}},"20820346-3a3f-41e7-a4c6-062e28c91ccd":{"role":"reader","value":{"id":"20820346-3a3f-41e7-a4c6-062e28c91ccd","version":1,"type":"text","properties":{"title":[["This is hidden content 🤫"]]},"created_time":1590252492387,"last_edited_time":1590252492387,"parent_id":"278d40df-89ec-46aa-813c-fa7439840ac4","parent_table":"block","alive":true,"copied_from":"308e46f2-30a5-4a63-bcf9-2e44c92766d4","created_by_table":"notion_user","created_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1","last_edited_by_table":"notion_user","last_edited_by_id":"bfe4e4aa-0528-4ca2-8620-9d1813ba92c1"}}}

Proposal: NotionComponentsProvider

The idea is to make react-notion more extensible by allowing users to optionally override individual components.

This is extremely useful in practice. For example, using next/link within a Next.js app if you want to override all of the page link components (where Next.js does some fancy pre-fetching that's disabled if you just use normal <a> tags). Or if you want to override all img instances to use lazy loading. Or if you want to use a custom table component in the future. etc. etc.

Docz has a great implementation of this by @pedronauck. Here's links to their implementation and docs.

The idea is to add a single hook useNotionComponents that uses React Context to get a component mapping that users can override via a NotionComponentsProvider.

This would also solve #10 and deprecate #11 @josemussa because you could override the link component and provide whatever default props you want.

I've already implemented this for notion2site.

Here's a quick overview of my implementation which is a slimmed down version of Docz's impl:

import * as React from 'react'
import { SFC, useContext, createContext } from 'react'

export interface NotionComponentsMap {
  [key: string]: any
}

const DefaultLink: SFC = (props) => <a {...props} />

const defaultComponents: NotionComponentsMap = {
  link: DefaultLink,
  pageLink: DefaultLink
}

export interface ComponentsProviderProps {
  components: NotionComponentsMap
}

const ctx = createContext<NotionComponentsMap>(defaultComponents)
export const NotionComponentsProvider: SFC<ComponentsProviderProps> = ({
  components: themeComponents = {},
  children
}) => (
  <ctx.Provider value={{ ...defaultComponents, ...themeComponents }}>
    {children}
  </ctx.Provider>
)

export const useNotionComponents = (): NotionComponentsMap => {
  return useContext(ctx)
}

And then in block.tsx:

export const Block: React.FC<Block> = (props) => {
  // ...
  const components = useNotionComponents()
  // ...
  
  return (
    <components.pageLink
      className='notion-page-link'
      href={mapPageUrl(blockValue.id)}
    >
      ...
    </components.pageLink
  )
}

And here's how a user of react-notion would configure this (optional):

import Link from 'next/link'

// ...
render() {
  return (
      <NotionComponentsProvider
        components={{
          pageLink: ({ href = '', ...rest }) => {
            return (
              <Link href='/[pageId'] as={href}>
                <a {...rest} />
              </Link>
            )
          }
        }}
      >
        <NotionRenderer
          blockMap={blockMap}
          mapPageUrl={mapPageUrl}
          fullPage
        />
      </NotionComponentsProvider>
  )
}

Replace notion-api-worker with official Notion API?

Hi,
The Notion API beta version is out now!
Wondering if that changes anything for this project? I haven't looked at it in detail yet but I wanted to make a portfolio website for myself that looked like and came from Notion and that's when I came across this - seems very cool 😮 .
If you want to add in the JS SDK for the official Notion API here, I'd like to contribute 😸 !

Tracking react-notion vs react-notion-x

React Notion X

Context

The purpose of this thread is to give some context between these two projects and track their differences, with the goal of ultimately converging on a single solution for the React Notion community going forwards.

I've spent the past few months working to improve react-notion for Notion2Site. Towards that end, I've had several conversations with @tobiaslins and @timolins who did a lot of the amazing legwork in creating the first version of react-notion.

I was working on a fork of react-notion with all of my changes in a Next.js project (not a Git fork, unfortunately), and I finally found the time to move this fork back out into its own set of standalone packages: react-notion-x.

Summary of changes

The largest changes can be broken into a few themes:

  • structural => isolating functionality into distinct packages
  • new functionality => new blocks, solid collection support, dark mode, etc
  • robustness => dozens of bug fixes
  • testing => test suite covering as much notion functionality as possible

I'll go into a bit more depth on some of these below.

Packages

One of the biggest changes is structural. Instead of relying on a CF worker and having types and utilities duplicated between react-notion and notion-api-worker, all of this has been split into isolated packages:

Package NPM Docs Environment Description
react-notion-x NPM docs Browser + SSR Fast React renderer for Notion.
notion-client NPM docs Server-side* Robust TypeScript client for the Notion API.
notion-types NPM docs Universal Core Notion TypeScript types.
notion-utils NPM docs Universal Useful utilities for working with Notion data.

imho it makes a lot more sense to expose a Notion API wrapper as notion-client that can be used from Node.js (and Next.js SSR), Deno, etc instead of just CF workers.

The goal is that hopefully once Notion releases its public API, these packages should only require minor updates with react-notion-x not having to change much if at all.

New Blocks

  • table of contents
  • checklists
  • figma
  • google maps
  • google drive
  • tweet
  • pdf
  • audio
  • file
  • equation (block & inline)
  • table collection view
  • gallery collection view
  • list collection view
  • board collection view
  • collection view page

General Improvements

  • dark mode
  • lazy loading heavy portions of the code via next/dynamic as a peer dep (eg, PDF support, collection support, equations / katex, etc)
  • support for LQIP images
  • formula support

Performance

I know one of the things that Tobias and Timo expressed very fair concerns about has been how to manage the tradeoffs between react-notion's original goal of being extremely lightweight and focused on embeddable use cases versus react-notion-x's goal of faithfully supporting all Notion content with both embedded and full page use cases.

This is very closely related to perf and bundle size, two things which I've spent a lot of time working on with react-notion-x, though there are definitely lots of tradeoffs to consider here.

I go into a bit more depth about my approach here, but in general I think that lazy loading larger optional dependencies like react-pdf, react-katex, as well as heavier portions of react-notion like collection views and equation support, gets us the best of both worlds.

The first load JS and total JS bundle size for most pages is comparable with react-notion, with larger optional dependencies only being loaded if needed by any given page.

The net result is that it's pretty easy to get solid lighthouse perf scores.

One downside of this approach is that I'm not sure how adding next/dynamic as a peer dependency works for devs who may want to use React Notion from non-Next.js projects. Does anyone have any good examples of large third-party React libraries that support loading portions of their bundle dynamically (and work regardless of if the consuming app is using Webpack or another bundler)?

Design

react-notion-x started as a fork of react-notion, and although 90% of the code has changed, the core NotionRenderer and Block classes should look very similar.

I took a very similar approach to #30 via @cball in supporting the ability to override specific components via a components prop on NotionRenderer.

Conversely, I ended up finding that as the number of components and their complexity grew, it became significantly simpler to expose an internal-only NotionContext that gives sub-components access to this configuration. It also became necessary for some interesting cases where when you render some subtrees, you want to completely negate the possibility of using <a> tags even though that subtree could contain any type of blocks. You can see an example of this in CollectionCard which can contain lots of different types of property content that we want to ensure doesn't contain any links so we override components.link and components.pageLink with a dummy link component.

Closing Thoughts

I hope this gives a good overview of my changes to react-notion-x with an emphasis on the most important design decisions.

I would've loved to have this be a real Git fork, but as I explained above this just wasn't in the cards for practical reasons as I learned about the scope of the changes needed as I went along.

Anyhow, I'm hoping that this public thread opens up a productive discussion that will benefit both projects and anyone interested in hacking on Notion in the future.

I'm very open to ideas about the best way to move both projects forward and hopefully merge them into a single react-notion solution that will provide the most long-term benefits.

Thanks!

Images are overflowing

I'm trying to render one notion page.
Font size is fine but the images are getting bigger than the wrapper and the layout isn't working properly. I don't know what to do Plz help me.

This is the notion page:
image

And this is the react-notion page:
스크린샷 2021-08-04 19 08 36

image

This is my code:

<StyledNotionWrapper>
{isNotionContent && <NotionRenderer blockMap={notionData} />}
</StyledNotionWrapper>

const StyledNotionWrapper = styled.div`
	width: 792px;
	max-width: 792px;
	font-size: 0.2rem;
`;

Open links in new tab

Notions' default behavior is to use target="_blank" for all a elements. I'm not sure if you want to match functionality 1:1 or allow for customization, but I wanted to highlight this.

Example not compiling

I'm not able to compile the example given in the repo, the following is the output

[ec2-user@ip-172-31-5-195 example]$ npm run build

> [email protected] build /home/ec2-user/react-notion/example
> next build

Failed to compile.

./pages/[pageId].tsx:47:9
Type error: Type '{ blockMap: any; fullPage: true; customBlockComponents: { page: ({ blockValue, renderComponent }: { blockValue: any; renderComponent: any; }) => Element; }; }' is not assignable to type 'IntrinsicAttributes & NotionRendererProps & { children?: ReactNode; }'.
  Property 'customBlockComponents' does not exist on type 'IntrinsicAttributes & NotionRendererProps & { children?: ReactNode; }'.

  45 |         blockMap={blockMap}
  46 |         fullPage
> 47 |         customBlockComponents={{
     |         ^
  48 |           page: ({ blockValue, renderComponent }) => (
  49 |             <Link href={`/${blockValue.id}`}>{renderComponent()}</Link>
  50 |           )
info  - Creating an optimized production build .npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `next build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ec2-user/.npm/_logs/2020-12-09T06_24_12_204Z-debug.log

Can I use this with GatsbyJS?

This is not an issue but I wonder whether I can use this with Gatsby. Any examples? Also when I use it with gatsby will my form embeds from mailerlite will work accordingly?

Uncaught TypeError: can't access property "caption", value.properties is undefined

Hi there,

I'm using the library to render a notion page on my react app.

I used the notion-API-worker to fetch the page, passing in the pageId:

export const getNotionPage = async (pageId: string) => {
  const data = await fetch(
    `https//notion-api.splitbee.io/v1/page/${pageId}`
  ).then((res) => res.json());
  return data;
};

Then in my component, I used the useEffect hook to set the pate state:

  useEffect(() => {
    setLoading(true);
    getNotionPage(PAGE_ID)
      .then((page) => setSupportPage(page))
      .catch((err) =>  console.error(err))
      .finally(() => setLoading(false));
  }, []);

In my console, I keep getting the error:
Screenshot 2023-03-17 at 10 03 16

I'm not sure why this is happening, could it be because I have an empty video block on my notion page?

Thanks in advance.

Underlined text not supported

Since an underlined text doesn't have a tag in Notion, there is no tag on the API side.
Notion uses border instead of tags.
For this reason, Notion renderer cannot manipulate underlined texts.
How can we find a solution to this?
Is it necessary to make an improvement on the API worker side?

Notion page:
image

Output:
image

API worker:
image

notion worker only fetching default view.

I have a notion database with many views.
examples
default -> https://www.notion.so/0bd7b86073744122bd61c5c552289447?v=fd64f69c0cbc40778e8b7678cc9c7efc
view using filter -> https://www.notion.so/0bd7b86073744122bd61c5c552289447?v=75f71e6a98af49c7a99bfffd5831062c
view using sort -> https://www.notion.so/0bd7b86073744122bd61c5c552289447?v=62490a5720ff45c8bc7201e9bf8831d9
I tried fetching using the notion worker https://notion-api.splitbee.io/v1/table/${NOTION_BLOG_ID}
So the result I am found that all the 3 views are returning same results .
In case of filter , It results returning all .In case of sort , it returns unsorted .

New feature: KaTeX support

I'm wondering if there is any plan to add math formulas support, for both in-line and block flavors. It would be awesome!

Support for image page icons

When uploading an image as a page icon it breaks when rendered.

Here's what it looks like in Notion:

IMAGE 2020-09-27 10:33:18

Here's what it looks like when rendered with react-notion:

IMAGE 2020-09-27 10:33:31

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.