Skip to main content

Plugin System

The @noxion/notion-renderer includes a render-time plugin system that layers on top of the standard block overrides API. It allows for deep customization of block data, text content, and rendering logic without modifying the core renderer.


Installation

Plugins are passed to the NotionRenderer component via the plugins prop.

import { NotionRenderer, createMermaidPlugin } from '@noxion/notion-renderer';

const plugins = [
createMermaidPlugin({ theme: 'dark' })
];

function MyPage({ recordMap }) {
return (
<NotionRenderer
recordMap={recordMap}
plugins={plugins}
/>
);
}

RendererPlugin Interface

The RendererPlugin interface defines the hooks available for customizing the rendering lifecycle.

export interface RendererPlugin {
/** Unique name for the plugin */
name: string;
/** Execution priority. Lower numbers run first. */
priority?: PluginPriority | number;
/** Intercept block rendering and return a custom component */
blockOverride?(args: BlockOverrideArgs): BlockOverrideResult | null;
/** Modify block data before it reaches the renderer */
transformBlock?(args: TransformBlockArgs): Block;
/** Transform raw text before decorations are applied */
transformText?(args: TransformTextArgs): TextTransformResult;
/** Called when a block starts rendering */
onBlockRender?(args: TransformBlockArgs): void;
/** Called after a block has finished rendering */
onBlockRendered?(args: TransformBlockArgs): void;
/** Optional plugin-specific configuration */
config?: Record<string, unknown>;
}

Plugin Hooks

HookWhen CalledReturn TypeUse Case
blockOverrideBefore rendering a blockBlockOverrideResult | nullIntercept specific block types to render custom React components.
transformBlockBefore blockOverrideBlockModify block properties or content before they are processed.
transformTextBefore decoration renderingTextTransformResultInject custom components or modify text (e.g., wikilinks, hashtags).
onBlockRenderStart of block rendervoidAnalytics, logging, or side effects before rendering.
onBlockRenderedEnd of block rendervoidPost-render side effects or cleanup.

RendererPluginFactory

Most plugins are distributed as factories to allow for configuration.

export type RendererPluginFactory<Options = void> = Options extends void
? () => RendererPlugin
: (options: Options) => RendererPlugin;

Plugin Priority

The execution order is determined by the priority property. Plugins with lower priority values execute first.

export enum PluginPriority {
FIRST = 0,
NORMAL = 50,
LAST = 100,
}
note

If multiple plugins provide a blockOverride, the first one to return a non-null result wins.


Error Isolation

The renderer wraps plugin calls in try/catch blocks. If a plugin fails, it will log a warning to the console but will not crash the entire rendering process. The renderer will simply proceed to the next plugin or the default rendering logic.


Writing a Custom Plugin

Custom plugins can combine multiple hooks to create complex behaviors.

import { RendererPlugin, PluginPriority } from '@noxion/notion-renderer';

const myCustomPlugin: RendererPlugin = {
name: 'custom-mention',
priority: PluginPriority.NORMAL,

blockOverride: ({ block }) => {
if (block.type === 'callout' && block.format?.page_icon === '💡') {
return {
component: MyCustomCallout,
props: { theme: 'highlight' }
};
}
return null;
},

transformText: ({ text }) => {
if (text.includes('@admin')) {
return {
text,
replacements: [{
start: text.indexOf('@admin'),
end: text.indexOf('@admin') + 6,
component: <Badge color="red">Admin</Badge>
}]
};
}
return { text, replacements: [] };
}
};

Combining with blockOverrides

The plugins system works alongside the legacy blockOverrides prop. The execution order is:

  1. plugins.transformBlock
  2. plugins.blockOverride (if any returns a component, it is used)
  3. blockOverrides prop (if no plugin intercepted the block)
  4. Default renderer components

Executor Functions

These functions are used internally by the renderer but are exported for advanced use cases.

FunctionDescription
resolveBlockRendererIterates through plugins to find a blockOverride.
executeBlockTransformsRuns all transformBlock hooks sequentially.
executeTextTransformsRuns all transformText hooks and collects replacements.
applyTextTransformsApplies collected text replacements to a string, returning a ReactNode[].

Type Exports

TypeDescription
BlockOverrideArgsArguments passed to blockOverride.
BlockOverrideResultExpected return type for blockOverride.
TransformBlockArgsArguments passed to transformBlock.
TransformTextArgsArguments passed to transformText.
TextReplacementDefines a component insertion point in text.
TextTransformResultResult of a text transformation.