Creating HTML View Plugins (using AI)
This guide helps you create HTML view plugins for NotePlan using AI. There are two approaches depending on your setup.
In this article:
- Option A: Using the NotePlan MCP Server (Recommended)
- Option B: Using Any AI Tool (Manual Setup)
- Plugin File Structure
- Lifecycle Events (v3.21+)
- Real-World Example: Stock Ticker Plugin
Option A: Using the NotePlan MCP Server (Recommended)
The NotePlan MCP server is the easiest way to create plugins. It connects AI assistants directly to NotePlan, so they can create, update, reload, and screenshot plugins automatically.
Compatible AI tools:
- Claude Code — Terminal-based AI coding assistant
- Claude Desktop — Desktop AI assistant with MCP support
- Codex — OpenAI’s coding agent
- Any AI tool that supports the Model Context Protocol
When you use the MCP server, the AI handles everything:
- Creates the plugin folder with all required files
- Writes index.html, styles.css, app.js as separate files
- Generates plugin.json with the new plugin.type: "html" format
- Generates the script.js backward-compatibility shim automatically
- Reloads plugins and launches the view so you can see it instantly
Just describe what you want and the AI takes care of the rest. To iterate, describe changes and the AI updates the files and reloads.
For setup instructions, see How to Install the NotePlan MCP Server.
Option B: Using Any AI Tool (Manual Setup)
If you’re not using the MCP server, you can use any AI tool (Cursor, ChatGPT, etc.) to generate the plugin files. You’ll need to set up the file structure yourself and tell the AI what to create.
Prerequisites
- NotePlan 3.20 or later (3.21+ for the new HTML plugin format)
- Any AI coding assistant (Cursor, ChatGPT, Claude, etc.)
No JavaScript experience required — the AI will generate the code for you.
Step 1: Download the Plugin Template
Download the plugin template ZIP file and extract it.

The template includes:
- getting-started.md — basic setup instructions (you or your AI can read this)
- plugin.json — plugin metadata and configuration
- script.js — example plugin code with HTML view examples
- API documentation files — reference for the AI
Step 2: Install the Plugin
Move the extracted plugin folder into NotePlan’s Plugins directory and rename it.

- Open NotePlan
- Go to Settings → AI & Plugins
- Click Open Plugins Folder
- Copy
np.myplugininto the Plugins folder - Rename it, for example to
em.LinearCalendar(using your initials is recommended)
Step 3: Ask the AI to Build Your Plugin

Open the plugin folder in your AI tool and ask it to create an HTML view plugin. You can use this prompt as a starting point:
I want to create a NotePlan plugin using the provided template and API files.
Plugin name: YOUR_PLUGIN_NAME
Plugin description: SHORT DESCRIPTION OF WHAT THE PLUGIN DOESPlease set this up as an HTML View plugin that:
- Opens a visible HTML view in the main NotePlan editor area
- Adds one clear command to launch this HTML view
- Updates plugin.json and script.js with a suitable name, description, command structure
Context:
- Read the file getting-started.md to learn about NotePlan plugins
- Find in this project a template plugin.json and script.js file to modify
- Read the included API documentation files like HTMLView.md, NotePlan.md, etc.
Step 4: Launch Your Plugin

In NotePlan, press CMD + J, then type /. Type your plugin name or command name to find it.
Once launched, your plugin appears in the sidebar and opens in the main editor area. To iterate, describe changes to the AI, let it update the code, then click the Reload button next to the plugin title.
Plugin File Structure
Starting with NotePlan 3.21, plugins can use a cleaner format where HTML, CSS, and JavaScript live in separate files.
New Format: plugin.type: "html" (NotePlan 3.21+)
NotePlan loads index.html directly — no JavaScript wrapper needed. Your plugin folder looks like this:
np.myPlugin/
plugin.json ← plugin metadata with "plugin.type": "html"
index.html ← your HTML file
styles.css ← CSS, linked via <link> in index.html
app.js ← JavaScript, linked via <script> in index.html
script.js ← backward-compat shim (see below)
How the Files Connect
plugin.json is the entry point. It tells NotePlan how to load the plugin:
{
"plugin.id": "np.myPlugin",
"plugin.name": "My Plugin",
"plugin.description": "Description of the plugin",
"plugin.author": "Your Name",
"plugin.version": "1.0.0",
"plugin.icon": "star",
"plugin.iconColor": "blue-500",
"plugin.type": "html",
"plugin.html": "index.html",
"plugin.sidebarView": true,
"plugin.sidebarTitle": "My Plugin",
"plugin.script": "script.js",
"plugin.commands": [
{
"name": "My Plugin",
"description": "Opens the plugin view",
"jsFunction": "myPlugin",
"sidebarView": {
"title": "My Plugin",
"icon": "star",
"iconColor": "blue-500"
}
}
]
}
Key fields:
"plugin.type": "html"— tells NotePlan 3.21+ to load the HTML file directly"plugin.html": "index.html"— which HTML file to load"plugin.sidebarView": true— show this plugin in the sidebar"plugin.sidebarTitle"— (optional) sidebar display title, falls back to plugin.name if not set"plugin.script"and"plugin.commands"— needed for backward compatibility with NotePlan < 3.21
index.html is your plugin’s UI. It’s a standard HTML file that references your CSS and JS:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Hello from my plugin!</h1>
<div id="content"></div>
<script src="app.js"></script>
</body>
</html>
styles.css and app.js are standard CSS and JavaScript files. Nothing special — they’re loaded by the browser just like any web page.
Backward Compatibility: The script.js Shim
If you want your plugin to also work on NotePlan versions older than 3.21, you need a script.js file. This is a small wrapper that embeds your index.html content and displays it using the legacy HTMLView.showInMainWindow() API.
The shim simply embeds the index.html — since the legacy path writes a temp file in the same plugin folder, <link href="styles.css"> and <script src="app.js"> still resolve correctly. No need to inline the CSS or JS.
Example script.js:
// Backward-compat shim for NotePlan < 3.21
// If using the new plugin.type: "html" format, this file is only
// loaded by older NotePlan versions. Edit index.html instead.
globalThis.myPlugin = async function() {
const html = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Hello from my plugin!</h1>
<div id="content"></div>
<script src="app.js"></script>
</body>
</html>`;
await HTMLView.showInMainWindow(html, "My Plugin", {
"id": "main:np.myPlugin:My Plugin",
"icon": "star"
});
};
The jsFunction in plugin.json must match the function name in script.js (in this example, "myPlugin" matches globalThis.myPlugin).
If you’re using the MCP server, script.js is generated automatically. If you’re writing the plugin manually or with an external AI, tell the AI to create this file as well.
Lifecycle Events (v3.21+)
When a plugin view is shown or hidden — for example, when the user switches between a note and your plugin — NotePlan dispatches DOM events to your HTML view. This lets you refresh data or pause timers without a full reload.
Available events:
onViewDidAppear— fired when your plugin view becomes visible againonViewWillDisappear— fired when your plugin view is about to be hidden
These fire in all display modes: main view, split view, and standalone windows.
Usage:
window.addEventListener('onViewDidAppear', () => {
// Refresh data, resume timers, etc.
refreshData();
});
window.addEventListener('onViewWillDisappear', () => {
// Pause timers, save state, etc.
pauseUpdates();
});
These work alongside the existing notePlanBridgeReady event:
notePlanBridgeReadyfires once when the NotePlan API bridge is first initializedonViewDidAppearfires each time the view becomes visible (not on first load)onViewWillDisappearfires each time the view is about to be hidden
Real-World Example: Stock Ticker Plugin
The Stock Ticker plugin is a complete example of the new HTML plugin format with separated files:
np.stockTicker/
plugin.json ← plugin.type: "html" + legacy shim fields
index.html ← HTML shell (~900B) with <link> and <script> tags
styles.css ← all CSS (7.6KB)
app.js ← all JavaScript (25KB)
script.js ← backward-compat shim (1.2KB)
Browse the source on GitHub to see exactly how the files are structured and connected.