Contributing to the Plugin System
This page is about improving the plugin system itself: the host, the API, the marketplace, and these docs. For writing a plugin, start at Getting Started; for publishing one, see Publishing.
Where the code lives
All host code is in hamidfzm/glyph:
| Area | Path |
|---|---|
| Loader, host, registries, types | src/lib/plugins/ |
| Worker sandbox (protocol, bootstrap, bridge) | src/lib/plugins/sandbox/ |
| Marketplace client (fetch, updates, sha256 verify) | src/lib/plugins/marketplace.ts |
| React wiring (provider, consent, toasts, styles) | src/contexts/PluginsProvider.tsx, src/components/plugins/ |
| Manage Plugins UI | src/components/plugins/PluginsModal.tsx |
| Rust commands (scan, install, uninstall) | src-tauri/src/commands/plugins.rs |
This repo holds the per-plugin registrations under plugins/<id>/ (plus the official plugins' source), the schemas, the generated index.json and catalog, and the docs. The template holds the scaffold and types.
How the system was built
The delivery plan lived in hamidfzm/glyph#109, shipped as phases:
- Foundation: loader (data-URL ESM import), host with per-plugin disposer bags, Rust install/list/uninstall, Manage Plugins modal
- A: Markdown pipeline: remark/rehype plugins, fenced code-block renderers
- B: Trust: declared permissions, install consent, permission-gated workspace API
- C/D: Surface growth: sidebar panels, settings panels, exporters, per-plugin settings, translations,
addStyles, spell-check dictionaries - E: Distribution hardening: index CI validation, sha256 download verification, and the opt-in worker sandbox
All phases are complete; new work is incremental API/proposal-driven.
Proposing new API surface
- Open a feature issue on hamidfzm/glyph describing the contribution point (what a plugin registers, what the host renders/runs, what can go wrong on unload).
- Every registration must return a disposer and route through the plugin's
DisposerBag, so unload removes exactly that plugin's contributions. - Decide the sandbox story up front: can the API cross a
postMessageboundary? If not (DOM mounts, React components), it stays main-context only and the docs must say so. - Bump the pinned
PLUGIN_API_VERSION(exact-match until 1.0, see hamidfzm/glyph#415) and ship, in the same PR series: host code + tests,api-reference.mdmarker, templatetypes/glyph.d.ts, a recipe, andindex.schema.jsonif the manifest changed.
Gates
The app repo enforces, on every PR (Husky pre-commit and CI):
pnpm typecheck && pnpm check && pnpm test
cd src-tauri && cargo clippy --all-targets -- -D warnings
Codecov patch coverage must stay green; run pnpm test:coverage before pushing. This repo runs validate.yml on every PR: schema validation, sorted unique ids, https URLs, and a catalog entry for every published id.