š§š¼āš Don't mind us, we are still working on this site using NotionCMS!
Like this project? Sponsor us on GitHub:
ā”ļøā”ļøā”ļø Get Started ā”ļøā”ļøā”ļø
NotionCMS plugins are a powerful way to extend what you can do with the Notion as headless CMS model. Letās take a tour of the NotionCMS plugin API, how they slot into the overall architecture and most importantly, how you can build your own to take advantage of Notion by leveraging NotionCMS tooling any way you please.
If you havenāt read the getting started guide, you should start there!
Here is a list of NotionCMS core plugins:
Head/SEO
Linker
Images
If none of those do the trick, NotionCMS provides a friendly plugin API so read on and craft your own!
If you are familiar with the Notion API SDK you know that you can query a database but the results of that query doesnāt give you everything you need. You also have to query individual pages to gather the āblocksā of content that get transformed into HTML.
NotionCMS peforms those queries in two stages and takes 2 passes at putting together the final tree structure. On the first pass we query the database and link together the parent pages to their children to build the skeleton of the tree. On the second pass we pull down the block content for each page and stash it in the correct location in the tree. This multi-pass approach means that there are a few places where you may want to hook into to do some data transformations, so weāll go through each hook in detail next.
Notion plugins run in almost the sequence they are defined in the NotionCMS
configuration and allow you to pull in common data at certain places within the phases of putting the CMS tree together. Depending which hook you use, you will have access to different data. Plugins of the same hook will run one after another and feed the previous plugins output into the next running plugin.
š§āš
Tip: NotionCMS plugins serialize/deserialize functions too so you can save those as data in the Page
structure. This is helpful for things like building template functions etc (see ncms-plugin-templates
for an example). Keep in mind the general limitations of serialized functions. For best results they should be pure functions.
If you are using Typescript with a capital T, here are the Plugin types you will see:
type PluginPassthrough = Blocks | CMS | Page | string
interface Plugin {
name: string,
hook: 'pre-tree' | 'pre-parse' | 'post-parse' | 'during-tree' | 'post-tree'
exec: (context: PluginPassthrough) => PluginPassthrough
}
There are 5 plugin hooks that you can use in NotionCMS and each is best used for accomplishing a particular goal.
pre-tree
during-tree
pre-parse
post-parse
post-tree
import
export
The pre-tree
hook runs after weāve hit the Notion database and assembled the tree skeleton but before weāve pulled the content in at all. Data you have available here are: routes
, name
, slug
, authors
, tags
, otherProps
, and possibly the coverImage
if one is set.
This is probably the hook youāll reach for the least often but if you wanted to perform tree-level changes before any heavy data insertion happens this might be where you do it. Filtering data from the tree here will mean that it wonāt get pulled in during the next hooks so do your filtering operations here.
The input argument available for this hook is the CMS
object.
The during-tree
hook runs during the process of pulling in the block content from Notion. A plugin defined to run on this hook will run once per node in the tree and have access to that nodeās data. This includes the content
pulled from Notion and at this point already parsed as HTML (if you want to do pre- or post- parsing operations only, take a look at the post-
and pre-parse
hooks below).
The data you have available at your disposal here also includes an array of the nodeās ancestors in _ancestors
. This is useful if you want to check for a property existing only on an ancestral node in order to perform some action on the current node.
The input argument to this hook is a Page
object.
The pre-parse
hook runs just before the Notion blocks are transformed into HTML.
The input argument to this hook is a Blocks
object. This refers to the blocks that come directly from the Notion API, so anything you might want to do to the raw Notion data, you can do here.
The pre-parse
hook runs just after the Notion blocks are transformed into HTML. So if you donāt care about blocks or any of the other higher-level tree node data and want to perform just some operations on the HTML string, this is the hook for you!
The input argument to this hook is a string
comprised of html.
The post-tree
hook is the final hook and gives you access to the entire assembled tree structure, content in the form of HTML and all. This would be the best hook to use for any sort of cleanup, restructuring that requires information embedded inside the blocks content itself (otherwise use pre-tree
).
The input argument available for this hook is the CMS
object.
// tbd
// tbd
As mentioned before, plugins run in the sequence they are defined, however, the hook they use in their definitions plays a big role in when they run so keep that in mind when ordering them. For instance, you might have an order like this:
const cmsWithPlugins = new NotionCMS({
//...
plugins: [
pluginA(), // hook is 'during-tree'
pluginB(), // hook is 'pre-tree'
pluginC() // hook is 'during-tree'
]
})
Then the order the plugins will actually run is this: pluginB
, pluginA
, pluginC
, since the pre-tree
hook runs before the during-tree
one.
Here is the general structure you will follow for plugins:
import {/*some types*/} from '@agency-kit/notion-cms'
export default function () {
return {
name: 'ncms-plugin-custom',
hook: 'during-tree',
exec: (context: PageContent): PluginPageContent => {
// Do your sweet sweet transforms here
}
}
}
We provide a recommended starter kit for writing NotionCMS plugins in TS. You can find that here: https://github.com/agency-kit/notion-cms-plugin-starter (still private as of writing)
We have a convention for naming NotionCMS plugins: ncms-plugin-x
where x is the descriptive name of the plugin you are publishing. This makes it easier for others to find helpful plugins and grow the community!
we make notionware. 2023 \c\