[ui] entry as an ES module and calls its exported
register function with a per-plugin API object. The same object is also
available globally as window.myrax[<plugin id>].
web/plugin.js
register may be async — the panel awaits it. If it throws, the panel shows
a “Plugin failed” toast with the error message and keeps running.
sidebar
| Key | Meaning |
|---|---|
mount(node) | full control — you get an empty container, return a cleanup function |
html | static HTML string |
render() | function returning an HTML string |
myrax.routes.add(route) takes the same object — use it for pages that should
exist without a sidebar entry, then navigate to them yourself.
Icon formats
| Value | Treated as |
|---|---|
<svg ...> | inline SVG — use stroke="currentColor" / fill="currentColor" so it follows the theme |
https://..., data:..., /path | image URL as-is |
icons/mark.svg | file inside your plugin, served from /addons/{id}/ |
| empty | the default plug icon |
toast
navigate
plugin:<id>:<value> — pass either form.
styles
Stylesheets listed in the manifest load automatically; these are for dynamic cases:/addons/{id}/ with the same ?v= cache
busting as your entry. Everything you inject is tagged with
data-myrax-plugin="<id>" and removed when the plugin is disabled.
layout
Shorthands overstyles.inject for hiding panel chrome:
refresh
Talking to your backend
The browser never reaches your runtime directly — go through the panel’s authenticated proxy:Theme tokens
Plugin DOM lives inside the panel, so its CSS variables are yours:--bg, --panel, --panel-2, --text, --muted, --line and the rest.
Build on them and both themes work without extra code.