Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
3.6 KiB
Build Your First Browser Extension
This tutorial walks through building a browser extension that renders custom code blocks, modeled on the CSV Table Viewer that ships with Armature.
Prerequisites: A running Armature instance, a text editor, and zip.
Step 1: Create the Directory
mkdir -p my-extension/js
Step 2: Write the Manifest
Create my-extension/manifest.json:
{
"id": "my-extension",
"title": "My Extension",
"version": "0.1.0",
"type": "extension",
"tier": "browser",
"author": "you",
"description": "Renders demo code blocks as styled HTML",
"permissions": [],
"settings": {}
}
- id -- unique identifier, used as the install key
- type --
extensionfor browser-only packages;fullorsurfacefor packages with backend routes - tier --
browserfor client-side JS;starlarkfor server-side scripting
Step 3: Write the Browser Script
Create my-extension/js/script.js. Browser extensions use the IIFE pattern
and register with the SDK through sw.renderers:
(function () {
'use strict';
function register() {
if (!window.sw?.renderers) return;
sw.renderers.register('demo-block', {
type: 'block',
priority: 10,
match(lang) {
return (lang || '').toLowerCase() === 'demo';
},
render(lang, code, container) {
container.innerHTML =
'<div style="padding:12px;background:var(--bg-secondary);' +
'border:1px solid var(--border);border-radius:8px">' +
'<strong>Demo:</strong> ' + code +
'</div>';
}
});
}
if (window.sw?._sdk) {
register();
} else {
document.addEventListener('sw:ready', register, { once: true });
}
})();
The IIFE wrapper keeps variables out of global scope. sw.renderers.register
takes a name and an options object: type: 'block' targets fenced code blocks,
match checks the language tag, and render receives the language, raw code,
and a container element. The sw:ready event fires once the SDK initializes;
if already loaded, register immediately. Use CSS variables like var(--bg-secondary)
and var(--border) to follow the active theme.
Step 4: Package It
cd my-extension
zip -r ../my-extension.pkg manifest.json js/
The .pkg format is a ZIP with manifest.json at the root. Optional
directories: js/, css/, assets/. If working inside packages/, use
the build script instead: bash build.sh my-extension.
Step 5: Install It
curl -X POST http://localhost:3000/api/v1/admin/packages/install \
-H "Authorization: Bearer <token>" \
-F "file=@my-extension.pkg"
You can also install through the Admin UI under the Packages section.
Step 6: Enable and Test
- Open the admin panel, navigate to Packages, confirm "My Extension" is enabled.
- Go to any markdown surface (Chat, Notes, etc.).
- Enter a fenced code block with the
demolanguage tag.
You should see styled output instead of a plain code block.
Going Further
- Add CSS -- create a
css/directory; stylesheets are injected automatically. - Post-renderers -- register with
type: 'post'to run after block renderers finish (the Mermaid extension uses this for async SVG rendering). - Settings -- declare a
settingsobject in the manifest for admin-configurable values. - Server-side logic -- set
tier: "starlark"and addscript.starfor backend API routes and database tables.
See PACKAGE-FORMAT.md for the full manifest spec and EXTENSION-GUIDE.md
for advanced patterns.