Skip to main content
Custom blocks are in private alpha:
  • Do not discuss publicly or share with anyone outside your workspace.
  • Access must be enabled per workspace. Installing the SDK does not grant access.
  • These APIs may experience breaking changes without notice.
A block should look like part of the page it sits in and should be as tall as its content. Both are cooperative: the SDK exposes Notion’s design tokens, and the block reports the height it wants rather than setting it.

Design tokens

NotionTokenScope makes Notion’s design tokens available to descendants and keeps them in sync as the host’s appearance changes. Pair it with the @notionhq/custom-blocks/nds.css import so the block matches the page it sits in, including dark mode and high contrast.

Theme and contrast

Use design tokens to style the block. When your code needs the current appearance, use a getter, subscription, or React hook. Theme is "light" or "dark". Contrast mode is "standard" or "high". The getter and subscription names below are methods on customBlock. Import React hooks from @notionhq/custom-blocks/react. Getters read the current value after initialization. Subscriptions can register earlier. They deliver the initial value once initialized, then later changes. React hooks keep components current when called inside NotionCustomBlock. See app context for examples and subscription cleanup.

Sizing

React blocks wrapped in NotionCustomBlock resize automatically to fit their content. In a framework-neutral frontend, call customBlock.autoResize({ target }) after initCustomBlock() resolves, passing the element whose height should drive the iframe. Notion clamps automatically reported heights to a minimum of 100 pixels and a maximum of 10,000 pixels. To cap automatic sizing at a shorter height, set max-height and overflow-y on #root:
If a viewer drags the block’s resize handle, the manually set height takes precedence over automatic content sizing. Automatic sizing resumes when the viewer chooses Fit content.