A self-contained plugin manager that lives inside TriliumNext. Install, update, and remove plugins with a single click — no external tools, no CLI, no wrappers.
Render Note → Fetch registry → Show cards → Install / Update / Uninstall
The Plugin Manager is a JS Frontend Render Note. On load, it fetches a plugin registry (a JSON file hosted anywhere public), renders a card-based UI, and lets you install, update, or remove plugins.
Two installation methods:
| Method | How it works | Token needed? |
|---|---|---|
sourceUrl (recommended) |
Downloads the .js/.jsx source directly and creates a code note |
❌ No |
zipUrl (fallback) |
Downloads a ZIP for manual import via Options → Import | ✅ Yes |
For the sourceUrl method, no ETAPI token is required — the plugin is created as a code note in one atomic backend call. No HTTP, no ZIP, no deadlock.
- Install plugins from a remote or local registry with one click
- Update detection — cards turn yellow when a newer version is available
- Uninstall — removes the plugin note cleanly
- Remote registry with automatic fallback to local note content
- Source indicator — shows remote/local source and last fetch time
- Dual mode —
sourceUrl(zero-config) orzipUrl(legacy) per plugin entry - Inherits the active TriliumNext theme via CSS variables
Plugin Manager ← Code note, MIME: application/javascript;env=frontend (paste the JS code)
├── plugin-registry ← Code note, MIME: application/json (registry JSON + config labels)
└── Installed ← Text note (receives installed plugins as child notes)
On plugin-registry:
| Label | Value | Required |
|---|---|---|
#pluginRegistry |
(no value — marks the note) | ✅ |
#registryUrl |
URL to your registry.json |
optional |
On Installed:
| Label | Value | Required |
|---|---|---|
#installedPlugins |
(no value — marks the note) | ✅ |
ℹ️
#etapiTokenand#triliumPortare no longer required when your registry usessourceUrlentries (recommended). They are only needed if you plan to install legacyzipUrl-based plugins.
- Create a Code note with MIME
application/javascript;env=frontend - Paste the contents of
trilium-plugin-manager-v4.js - Add a
~renderNoterelation pointing to the note where you want the panel to appear - Open the target note
Create a public GitHub Gist with a registry.json file. Copy the Raw URL and add it as #registryUrl on the plugin-registry note.
{
"plugins": [
{
"id": "weekly-planner",
"name": "Weekly Planner",
"version": "1.0.0",
"author": "your-github-username",
"description": "Weekly planning board with columns.",
"tags": ["productivity", "planning"],
"sourceUrl": "https://raw.githubusercontent.com/user/repo/main/planner.jsx",
"zipUrl": "https://github.com/user/repo/raw/main/planner.zip"
}
]
}| Field | Required | Description |
|---|---|---|
id |
✅ | Unique identifier — used to track installation state |
name |
✅ | Display name shown in the UI |
version |
✅ | Semver string (1.0.0) |
author |
Author name | |
description |
Short card description | |
tags |
Array of tag strings | |
homepage |
URL to the plugin's docs or repository — shows a "How to" button on the card | |
sourceUrl |
Raw URL to the .js/.jsx source file |
|
manifestUrl |
Raw URL to a manifest.json for multi-note plugins (see below) |
|
zipUrl |
Legacy URL to a Trilium export ZIP |
At least one of sourceUrl, manifestUrl or zipUrl must be provided.
A single .js or .jsx file. The Plugin Manager downloads it and creates one code note.
sourceUrl → download → create code note → done
For plugins that need multiple notes (widget + handler + config + render note). The manifestUrl points to a JSON file describing the notes to create:
{
"notes": [
{
"title": "My Plugin",
"type": "text",
"content": "Open this note to use the plugin."
},
{
"title": "My Plugin Code",
"type": "code",
"mime": "application/javascript;env=frontend",
"sourceUrl": "code.js"
}
],
"relations": [
{ "type": "renderNote", "from": "My Plugin", "to": "My Plugin Code" }
],
"labels": [
{ "note": "My Plugin Code", "name": "readOnly", "value": "" }
]
}Each note with sourceUrl fetches the source file (relative to the manifest URL). Labels and relations from the manifest are applied automatically.
manifestUrl → download manifest → for each note: create + apply labels → create relations → done
Downloads the ZIP to the user's browser for manual import via Options → Import. Requires an ETAPI token.
- Downloads the manifest JSON
- Creates all notes described in the manifest
- Applies labels and
~renderNoterelations - ✅ No token, no ZIP, no deadlock
- Backend downloads the source file via HTTPS
- Creates a
codenote with MIMEapplication/javascript;env=frontend - Sets
#pluginId,#pluginVersion,#pluginNamelabels - ✅ Done
- Downloads the ZIP to the user's browser
- User imports manually via Options → Import
On every load, the manager compares the version field in the registry against the #pluginVersion label on each installed note:
- Same version → green card,
✓ v1.0.0 - Registry is newer → yellow card,
↑ v0.5.0 → v1.0.0 - Not installed → default card + Install button
| File | Description |
|---|---|
trilium-plugin-manager-v4.js |
Main file — paste into a JS Frontend note |
trilium-plugin-manager-v4.html |
Legacy HTML version (kept for reference) |
registry.json |
Example registry with official plugins |
PLUGIN_DEV_GUIDE.md |
Guide for creating and publishing plugins |
MANIFEST_GENERATOR.md |
Fill-in-the-blank prompt to generate manifest.json |
- Plugin changelog field
- Startup update badge
- One-click "Export as plugin" helper note
MIT

