an enhancer/customiser for the all-in-one productivity workspace


Before creating a mod, read the Contributing guide for instructions on setting up a development environment and the guidelines that must be followed for a mod to be accepted by the notion-enhancer.

In its most basic form, a notion-enhancer mod is a folder containing a mod.json file. This file defines mod metadata, scripts & styles:

namedisplay namestring
ida unique uuidv4 identifier (generated via e.g. uuidgen or
versiona semver version number (MAJOR.MINOR.PATCH e.g. "0.5.2")string
environments (optional)the environments the mod may run in - available environments are linux, win32, darwin and extension (leave blank for any)string[]
descriptiona summary of the features provided by the mod (inline markdown available)string
preview (optional)the relative filepath of a screenshot demonstrating the mod (should be in the same directory as the mod.json and have a non-generic name, e.g. my-mod.png instead of preview.png)string
tagsmod categorisation (e.g. automation) - must include at least one of core, extension, theme or integration (themes must also include either dark or light)string
authorsan array of authorsauthor[]
css.frame (optional)an array of relative filepaths to .css filesstring[]
css.client (optional)an array of relative filepaths to .css filesstring[] (optional)an array of relative filepaths to .css filesstring[]
js.frame (optional)an array of relative filepaths to .mjs files (see the Renderer Scripts section)string[]
js.client (optional)an array of relative filepaths to .mjs files (see the Renderer Scripts section)string[] (optional)an array of relative filepaths to .mjs files (see the Renderer Scripts section)string[]
js.electron (optional)an array of relative .cjs sources & Electron targets (see the Electron Scripts section)electron[]
optionsan array of optionsoptions[]


Though all mods are made the same way, they are separated conceptually. This forces mods to focus on doing one thing well and makes configuration easier and safer.

Core mods cannot be disabled (e.g. the menu), and are depended on by other parts of the notion-enhancer. Most mods should not have the core tag.

Extensions are general feature-enhancing mods.

  • They should contain JavaScript.
  • They may contain some supporting CSS.
  • They should not change any CSS variables.
  • They must have the extension tag.

Themes override Notion's default colour palette.

  • They should primarily change the available CSS theming variables.
  • They may contain some supporting CSS.
  • They should not contain layout changes or remove/hide UI elements.
  • They may only use JavaScript to set user-configured colour values.
  • They must have the theme tag.
  • They must have either the dark tag or light tag. If there are both light and dark variants of the same theme they should be separated out into their own mods.

Integrations are extensions that use the unofficial notion API to access and modify Notion content.

  • They should not do anything without explicit user interaction.
  • They must be thoroughly tested to ensure they won't break the user's workspace.
  • They must update Notion content.
  • They may contain some supporting CSS.
  • They should not change any CSS variables.
  • They must have the integration tag.


Mod authors are listed in the notion-enhancer menu and on the notion-enhancer website. Multiple authors may be listed, e.g. if you are porting a feature from elsewhere to the notion-enhancer.

If you are just contributing a minor bugfix to an existing mod, do not add yourself to the author's list.

nameauthor namestring
email (optional)an email for e.g. emergency contact relating to the modstring
avatarthe author's profile picturestring

Scripts & Styles

Scripts and styles can be loaded into a few different renderer processes:

  • The frame is the parent renderer within which the Notion web client is loaded. This is only available within the app, and is e.g. where the tabs mod places its tab bar.
  • The client is the Notion web client, the same in the app and browser.
  • The menu is the notion-enhancer menu, the same in the app and browser.


Themes should override the available CSS theming variables in the document :root with a class specifying their mode, e.g.

:root.light { --theme--bg: #93b8e7; } /* or */ :root.dark { --theme--bg: #0f111a; }

Themes should override all colour variables - e.g. if card backgrounds and text colours have been changed, but the main background colour is still the default Notion colour, the theme is incomplete and will not be merged into the notion-enhancer.

Renderer Scripts

The default exports of mod scripts in renderer processes are called with 2 arguments:

  • api is an object containing the notion-enhancer helper API.

  • db is an instance of the notion-enhancer's database scoped to the current mod.

    To save data to the database, run await db.set(['path', 'of', 'keys], newValue).

    To get data from the database, run await db.get(['path', 'of', 'keys], fallbackValue).

    Mod options are saved to this database and automatically fallback to the value provided in the mod.json file (e.g. to get an option with the key display_mode, run await db.get(['display_mode'])).

export default async function (api, db) { // }

Electron Scripts

Scripts inserted into the main Electron process should be defined in the mod.json file with the following properties:

sourcea relative filepath to a .cjs filestring
targeta filepath to one of the Notion app's .js files, relative to the resources/app directorystring

These receive an additional 2 arguments:

  • __exports is a reference to the target/parent script's module.exports object, and can be modified to override exports from the parent script.
  • __eval is a function that can be called with a single string to execute as JavaScript in the parent scope, e.g. to modify/override non-exported variables and functions. This string should never be dynamic (see eval()).
module.exports = async function (api, db, __exports, __eval) { // };


Mod options are configurable through the notion-enhancer menu and accessibe through the mod database (see above). A few base properties should be provided with all options in the mod.json file:

typethe option type (see below)string
keythe mod database key to access/set the option value tostring
labelthe option's display namestring
tooltip (optional)an extended description of what the option will affect (inline markdown available, bold text will be black and normal text will be grey)string
environments (optional)the environments the option will be configurable in - available environments are linux, win32, darwin and extension (leave blank for any)string
  • Option type: toggle

    valuethe default on/off state of the toggleboolean
  • Option type: select

    valuesan array of selectable values, with the first value as the defaultstring[]
  • Option type: text

    valuethe default value of the text inputstring
  • Option type: number

    valuethe default value of the number inputnumber
  • Option type: hotkey

    Record user keypresses to create hotkey accelerators for handling with api.web.addHotkeyListener.

    valuethe default hotkey accelerator e.g. Ctrl+Shift+Xstring
  • Option type: color

    rgba() color pickers.

    valuethe default rgba colorstring
  • Option type: file

    Accept file uploads that are stored in the database as { filename: string, content: blob | string }.

    extensionsallowed file extensions e.g. .jsonstring[]

For working examples of existing mods, check out the notion-enhancer/repo repository. A mod.json generator and graphical theme builder are work-in-progress.

Edit this page