Every file your plugin needs should be in the built package/. Lomi does not start a development server, fetch npm dependencies or use the author’s source directory.
Include a stylesheet
Section titled “Include a stylesheet”Declare "stylesheets": ["view.css"] in plugin.json and include that file in the configuration’s assets:
import { defineConfig } from '@lomi-dev/plugin-cli';
export default defineConfig({ assets: ['view.css', 'images', 'LICENSE'],});Create images before building, or remove it from the list. Missing declared assets fail the build. Stylesheets load before activate() and are removed on deactivation. They are not automatically scoped or placed in Shadow DOM.
Match the Lomi theme
Section titled “Match the Lomi theme”Use a plugin-owned root class and application semantic tokens:
.lomi-workspace-info { box-sizing: border-box; padding: 16px; color: var(--color-surface-text); background: var(--color-surface); overflow-wrap: anywhere;}
.lomi-workspace-info button { font: inherit; color: inherit; background: transparent; border: 1px solid var(--color-outline); border-radius: 6px; padding: 8px 12px;}
.lomi-workspace-info button:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px;}Avoid global body, button, * selectors or token changes on :root: the shared document also contains Lomi and other plugins. Keep visible focus, field labels and accessible button names. Test light and dark appearances and narrow panels.
Images and local files
Section titled “Images and local files”Inside activate(), obtain a URL using context.assetUrl('images/icon.svg') and pass it to the component. This validates path syntax and constructs the installed revision URL; the call itself does not verify file existence. Include the file in assets.
Paths are relative to the package root, without a leading /. Do not persist the returned URL in session state: it contains a revision that may change on update. Calculate it again after activation. Do not construct plugin: or plugin.localhost URLs yourself.
CSS paths are relative to the stylesheet, for example url('./images/icon.svg') for root-level view.css. Validation checks local url() and @import references. External URLs, missing files, % encoding, queries and fragments in those references are rejected; data: is allowed. JavaScript paths constructed at runtime cannot be statically verified.
Dependencies and dynamic imports
Section titled “Dependencies and dynamic imports”Additional libraries must run in a browser. The build bundles them into ESM. Do not import node:fs, other Node modules, private Lomi files or source outside the author project.
Use literal dynamic imports:
const details = await import('./details');The corresponding src/details.ts must exist. The bundler may emit a separate chunk; share the entire package/, not just dist/index.js. Constructing an import path from a variable is unsupported. new URL(..., import.meta.url) does not replace explicitly including assets.
React, React DOM, react-dom/client, JSX modules and the main SDK export share the host runtime. Do not include another React copy. react-dom/server and SDK tooling subpaths are not plugin runtime entry points; use them only in author-side Node scripts.
Include a theme
Section titled “Include a theme”Add this inside contributes:
{ "themes": [ { "id": "example.workspace-info.theme", "path": "theme" } ]}path is a directory: create theme/theme.jsonc and add theme to assets. The theme template provides a complete starting point. See Creating a theme for the format.
Themes become available after package import without executing JavaScript. Package-owned themes are read-only; users can duplicate them. Disabling code does not remove a theme. Before uninstalling, switch away from any active color or icon themes supplied by the package.
Plugin-specific tokens
Section titled “Plugin-specific tokens”A theme can define owner-specific tokens. For example.workspace-info and token surface, include a fallback:
.lomi-workspace-info { background: var(--plugin-example-dworkspace-hinfo-surface, var(--color-surface));}ID encoding replaces - with -h, then . with -d. Not every theme defines plugin tokens, so a fallback is necessary. Theme assets and CSS explains their declaration.