{"id":19002626,"url":"https://github.com/alvis/gatsby-source-notion","last_synced_at":"2025-06-24T11:06:41.458Z","repository":{"id":40509582,"uuid":"379204188","full_name":"alvis/gatsby-source-notion","owner":"alvis","description":"A Gatsby source plugin for content management with Notion using the official API.","archived":false,"fork":false,"pushed_at":"2022-11-16T05:38:45.000Z","size":4790,"stargazers_count":55,"open_issues_count":4,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-17T08:59:52.343Z","etag":null,"topics":["cms","gatsby","gatsby-plugin","gatsby-source","notion","notion-api"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alvis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-22T08:55:48.000Z","updated_at":"2025-01-13T18:35:38.000Z","dependencies_parsed_at":"2023-01-22T04:51:49.881Z","dependency_job_id":null,"html_url":"https://github.com/alvis/gatsby-source-notion","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/alvis/gatsby-source-notion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alvis%2Fgatsby-source-notion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alvis%2Fgatsby-source-notion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alvis%2Fgatsby-source-notion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alvis%2Fgatsby-source-notion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alvis","download_url":"https://codeload.github.com/alvis/gatsby-source-notion/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alvis%2Fgatsby-source-notion/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261658586,"owners_count":23191088,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","gatsby","gatsby-plugin","gatsby-source","notion","notion-api"],"created_at":"2024-11-08T18:15:30.121Z","updated_at":"2025-06-24T11:06:41.420Z","avatar_url":"https://github.com/alvis.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg alt=\"Gatsby\" src=\"https://www.gatsbyjs.com/Gatsby-Monogram.svg\" width=\"60\" /\u003e\n\n# Gatsby Source Plugin Notion\n\n💫 _Use Notion as the CMS for your Gatsby site, multiple databases and pages via the official API._\n\n•   [Quick Start](#quick-start)   •   [Usage](#usage)   •   [Known Limitations](#known-limitations)   •   [FAQ](#faq)   •   [About](#about)   •\n\n[![npm](https://img.shields.io/npm/v/gatsby-source-notion?style=flat-square)](https://github.com/alvis/gatsby-source-notion/releases)\n[![build](https://img.shields.io/github/workflow/status/alvis/gatsby-source-notion/code%20test?style=flat-square)](../actions)\n[![maintainability](https://img.shields.io/codeclimate/maintainability/alvis/gatsby-source-notion?style=flat-square)](https://codeclimate.com/github/alvis/gatsby-source-notion/maintainability)\n[![coverage](https://img.shields.io/codeclimate/coverage/alvis/gatsby-source-notion?style=flat-square)](https://codeclimate.com/github/alvis/gatsby-source-notion/test_coverage)\n[![security](https://img.shields.io/snyk/vulnerabilities/github/alvis/gatsby-source-notion?style=flat-square)](https://snyk.io/test/github/alvis/gatsby-source-notion)\n[![dependencies](https://img.shields.io/david/alvis/gatsby-source-notion.svg?style=flat-square)](https://david-dm.org/alvis/gatsby-source-notion)\n[![license](https://img.shields.io/github/license/alvis/gatsby-source-notion.svg?style=flat-square)](https://github.com/alvis/gatsby-source-notion/blob/master/LICENSE)\n\n\u003c/div\u003e\n\nTired of committing markdown files to your git repo for every new blog post? Having colleagues who don't know how to git commit? or simply you don't want to introduce an additional toolset (CMS) to manage the content of your website?\n\n**gatsby-source-notion** is a solution for you manage the content of your Gatsby site without any\n\n### Features\n\n- 👉 Allow you to build a website with content from your Notion databases or pages\n- 💈 Page contents in markdown!\n- ⌨️ Title and their properties in plain text accessible via the front matter\n- 🖼️ URL for cover image and icon!\n- 🔮 All page properties accessible via GraphQL\n- 🍻 Support for `remark` and `mdx`\n- 👀 Near real-time preview in development mode\n\n# Quick Start\n\n## Step 0 - Install the source plugin\n\n```shell\nnpm install --save-dev gatsby-source-notion\n```\n\nOptionally, if you want markdown support,\nit's recommended to have `gatsby-plugin-mdx` installed as well.\n\n```shell\nnpm install --save-dev gatsby-source-notion gatsby-plugin-mdx\n```\n\n## Step 1 - Get your access token\n\n[Follow the official integration guide](https://developers.notion.com/docs/getting-started).\n\n1. Go to https://www.notion.com/my-integrations.\n2. Click the `+ New integration` button.\n3. Give your integration a name, for example `My Gatsby Website`.\n4. Select the workspace where you want this plugin to get content from.\n5. Click `Submit` to create the integration.\n6. Copy the `Internal Integration Token` on the next page and export it to the `GATSBY_NOTION_TOKEN` environment variable.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg alt=\"Steps to get an access token\" src=\"https://files.readme.io/2ec137d-093ad49-create-integration.gif\" width=\"50%\" /\u003e\n\u003c/div\u003e\n\n## Step 2 - Specify the databases and pages you allow this plugin to access\n\nIntegrations don't have access to any databases or pages in the workspace initially.\nFor the plugin to access content, you must share a specific database or page with the integration.\n\n1. Open the page or database in which your content sits.\n2. Click the `Share` button and select your integration by its name, then click `Invite`.\n3. Repeat for each of the content resource you want to use for building your Gatsby website.\n\n**NOTE** Alternative to sharing your databases and pages one by one, you can also choose to grant access to all databases and pages to your integration in the `Members` section in the workspace settings.\nHowever, it is not advisable to do this because that will grant unnecessary access which is bad for security.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg alt=\"Steps to share a database\" src=\"https://files.readme.io/0a267dd-share-database-with-integration.gif\" width=\"50%\" /\u003e\n\u003c/div\u003e\n\n**IMPORTANT** For each of your shared databases or pages, remember to record the UUID.\nYou will need to specify them in the config.\n\nThe UUID of a database can be obtained from your database URL.\nOne way to get this information is by using your own database URL which has the following format:\n`https://www.notion.so/\u003cyour workspace\u003e/\u003cdatabase UUID\u003e?some_query_string`\n\n`https://www.notion.so/\u003cyour workspace\u003e/\u003cpage title\u003e-\u003cpage UUID\u003e`\n\n## Step 3 - Setup the plugin in your gatsby site\n\n**IMPORTANT** For security reasons, it's recommended to specify the API access token via the `GATSBY_NOTION_TOKEN` environment variable.\n\nIn your `gatsby-config`, add `gatsby-source-notion` with settings something like:\n\n```ts\n{\n  resolve: 'gatsby-source-notion',\n  options: {\n    databases: ['\u003c\u003c your database UUID \u003e\u003e'],\n    pages: ['\u003c\u003c your page UUID \u003e\u003e'],\n  },\n};\n```\n\n**NOTE** Alternatively, you can specify the databases and pages via the `GATSBY_NOTION_DATABASES` and `GATSBY_NOTION_PAGES` environment variables separated by a comma `,`.\n\n## Step 4 - Create pages with your content stored in Notion\n\n**IMPORTANT** In this step, assume that you have `gatsby-plugin-mdx` installed and there is a `path` property in your database page.\n\nHere is an example in TypeScript. A JS implementation would follow the same logic:\n\n```ts\n/* gatsby-node */\nimport type { GatsbyNode } from 'gatsby';\n\n// types generated from a code generator such as `gatsby-plugin-graphql-codegen`\nimport type { BlogsQuery } from '@graphql';\n\nexport const createPages: GatsbyNode['createPages'] = async ({\n  actions,\n  graphql,\n}) =\u003e {\n  const { createPage } = actions;\n\n  const response = await graphql\u003cBlogsQuery\u003e(`\n    query Blogs {\n      notionDatabase(ref: { eq: \"\u003c\u003c your database UUID \u003e\u003e\" }) {\n        childrenNotionPage {\n          childMdx {\n            id\n            frontmatter {\n              path\n            }\n          }\n        }\n      }\n    }\n  `);\n\n  response?.data?.notionDatabase?.childrenNotionPage?.forEach((page) =\u003e {\n    const mdx = page?.childMdx;\n\n    const path = mdx?.frontmatter?.path;\n\n    if (mdx \u0026\u0026 path) {\n      createPage({\n        path,\n        // NOTE: must resolve to the absolute path of the component\n        component: resolve('\u003c\u003c path to your page component \u003e\u003e'),\n        context: {\n          id: mdx.id,\n        },\n      });\n    }\n  });\n};\n```\n\n```tsx\n/* you page component */\nimport React from 'react';\nimport { graphql } from 'gatsby';\nimport { MDXRenderer } from 'gatsby-plugin-mdx';\n\nimport { Layout } from '\u003c\u003c path to your layout component \u003e\u003e';\n\nimport type { PageProps } from 'gatsby';\n\n// types generated from a code generator such as `gatsby-plugin-graphql-codegen`\nimport type { BlogQuery } from '@graphql';\n\nconst Blog: React.FC\u003cPageProps\u003cBlogQuery\u003e\u003e = ({ data }) =\u003e {\n  // since this page is referred from the createPages API, it's safe to assume the mdx node is there\n  const mdx = data.mdx!;\n\n  const title = mdx.frontmatter?.title;\n  const body = mdx.body;\n\n  return (\n    \u003cLayout\u003e\n      \u003ch1\u003e{title}\u003c/h1\u003e\n      \u003cMDXRenderer\u003e{body}\u003c/MDXRenderer\u003e\n    \u003c/Layout\u003e\n  );\n};\n\nexport const pageQuery = graphql`\n  query Blog($id: String!) {\n    mdx(id: { eq: $id }) {\n      frontmatter {\n        title\n      }\n      body\n    }\n  }\n`;\n\nexport default Blog;\n```\n\n# Usage\n\nAt this point, you should have an idea of how to use gatsby-source-notion. To make your experience even better, you can also configure a few more things:\n\n```ts\n/* plugin options you can specify in `gatsby-config` */\ninterface PluginConfig {\n  /** access token, default to be the environment variable GATSBY_NOTION_TOKEN */\n  token?: string;\n  /** api version, default to be 2021-05-13 */\n  version?: string;\n  /** UUID of databases to be sourced, default to be `[]` i.e. none */\n  databases?: string[];\n  /** UUID of pages to be sourced, default to be `[]` i.e. none */\n  pages?: string[];\n  /** the number of api calls per seconds allowed for preview, 0 to disable preview default to be 2.5 */\n  previewCallRate?: number;\n  /** TTL settings for each API call types, default to cache database metadata and blocks */\n  previewTTL?: {\n    /** the number of seconds in which a database metadata will be cached, default to be 0 i.e. permanent */\n    databaseMeta?: number;\n    /** the number of seconds in which a metadata of a database's entries will be cached, default to be 0.5 */\n    databaseEntries?: number;\n    /** the number of seconds in which a page metadata will be cached, default to be 0.5 */\n    pageMeta?: number;\n    /** the number of seconds in which a page content will be cached, default to be 0 i.e. permanent */\n    pageContent?: number;\n  };\n}\n```\n\n# Preview Mode\n\nThis plugin ships with a preview mode by default and it is enabled.\nStart your development server and type on your Notion page to see the content get updated on the Gatsby website.\n\nUnder the hood, this plugin automatically pulls the page metadata from Notion regularly and checks for any updates using the `last_edited_time` property.\nWhen a change is detected, this plugin will reload the content automatically.\n\n**NOTE** To adjust the frequency of update, you can specify the maximum allowed number of API calls.\nThe higher the more frequently it checks for updates.\nThe actual frequency will be computed automatically according to your needs but be mindful of current limits for Notion API which is 3 requests per second at time of publishing.\n\n**NOTE** Unlike other integrations with preview, such as `gatsby-source-sanity`, this plugin can't sync any content from your Notion document that wasn't saved.\nNotion has autosaving, but it is delayed so you might not see an immediate change in preview.\nDon't worry though, because it’s only a matter of time before you see the change.\n\n![Preview Mode Demo](https://github.com/alvis/gatsby-source-notion/raw/master/assets/preview.gif)\n\n# Known Limitations\n\nAs this plugin relies on the the official Notion API which is still in beta, we share the same limitations as the API.\n\n- Currently, only text-based blocks can be extracted via this API.\n  i.e. Items such as embedded PDFs are not supported.\n- If you have a very long or sizing page, be aware that [the official Notion API has a limit of maximum size of 1000 block elements and 500kb](https://developers.notion.com/reference/errors#size-limits).  \n  Currently, there is no way we can get data beyond that.\n- Indentation is only supported for lists such as bullets, numbers and to-do lists.\n  Other text will not be indented due to the limitations of the markdown format.\n- Due to GraphQL’s limitation, property names with non-alphanumeric characters, such as a space ` ` etc will be converted to an underscore `_` automatically.\n  You may run into conflicts if you have two properties (e.g., `Property Name` and `Property_Name`) whose names are close but differ in these characters.\n\n## Unsupported Blocks\n\n- Sub Page\n- Call out\n- Video\n- Code Block\n- Coloured Text\n- Underlined Text\n\n## Image\n\nSince v3.3, `gatsby-source-notion` provided a limited support for images on a Notion page.\nNow, all images on a Notion page will be translated into the `![caption](url)` syntax and subsequently converted to a `img` element if you use `gatsby-plugin-mdx`.\n\nHowever, it has a caveat. Embedding images would probably be missing in your final web site.\nIt is because the embedded image URL returned from Notion is valid only for 1 hour.\n[This is a restriction from Notion.](https://developers.notion.com/reference/file-object#files-uploaded-to-notion-objects)\nAs gatsby would not download the image for further processing,\nyou simply cannot use Notion as your image host.\n\nPlugins like [gatsby-remark-images-anywhere](https://github.com/d4rekanguok/gatsby-remark-images-anywhere) would solve the issue.\nHowever, as of `2022-07-01` there is no similar plugin that supports Gatsby V4.\nLet us know if you find any.\n\n# Cover \u0026 Icon\n\nNow, cover image and icon are accessible as part of pages' metadata.\n\nFor cover image, the URL for it is exported via `coverImage`.\nFor Icon, if it is an image, its URL will be supplied in `iconImage`;\nif it is an emoji, its value will be supplied in `iconEmoji`.\n\nThey can also be found within the frontmatter of the MDX export.\n\n# FAQ\n\n1. How can I specify different databases and pages for different environments, such as those used by staging, or production?\n   You can specify the database or page UUIDs in the `GATSBY_NOTION_DATABASES` and `GATSBY_NOTION_PAGES` environment variables, separated by a comma.\n\n2. I encountered a 404 error from the plugin, what happened?\n   You may forget to grant the integration access to the database or page specified in the config.\n   Check if you've given it permissions, or if any of the UUIDs contain typos.\n\n3. What can I do if I don't want to permanently delete a post but just hide it for awhile?\n   You can create a page property (for example, a publish double checkbox) and use this information in your page creation process.\n   If you're in the development mode with preview enabled, you should be able to see the removal in near real-time.\n\n4. Since the introduction of access capabilities in Notion API in Dec 2021,\n   some content may be unexpectedly missing from the return due to access control granted to the API client.\n   Make sure the API client has `read` permission to all of the content you want to output.\n\n# About\n\nThis source plugin is built on the official Notion API.\nIf you are interested in using it as well, here is a [Postman collection](https://www.postman.com/notionhq/workspace/notion-s-public-api-workspace/overview) you can explore.\nAlso follow the [official API documentation](https://developers.notion.com/reference/intro) to learn more about how to use it.\n\n### Contributing\n\nAny new ideas? or got a bug? We definitely would love to have your contribution!\n\nFeel free to open a discussion, report a bug or ask for a new feature via [issues](https://github.com/alvis/gatsby-source-notion/issues).\n\nFurther, read the [contribution guide](https://github.com/alvis/gatsby-source-notion/blob/master/CONTRIBUTING.md) for the detail of the code structure and useful commands etc.\n\n### License\n\nCopyright © 2021, [Alvis Tang](https://github.com/alvis). Released under the [MIT License](LICENSE).\n\n[![license](https://img.shields.io/github/license/alvis/gatsby-source-notion.svg?style=flat-square)](https://github.com/alvis/gatsby-source-notion/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falvis%2Fgatsby-source-notion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falvis%2Fgatsby-source-notion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falvis%2Fgatsby-source-notion/lists"}