You will build
Sharpening Log, a small Tool for ACME's workshop: its own sidebar entry, admin screen and API route, written inside the admin.
You need
- A Super Admin account (editing Tool code needs the plugins develop permission)
- A site under a process manager such as PM2, so it can restart itself
- Some JavaScript
Tools are plugins
In the code a Tool is a plugin: a folder under plugins/ with a manifest, a server file and optional screens.
Step 1: Scaffold it
Open Marketplace and click New plugin (the + in the banner). Enter a display name Sharpening Log; the slug sharpening-log is made as you type. Add a description, author and icon, and create it.
Domma CMS copies its template into plugins/sharpening-log/:
plugin.json the manifest - name, version, sidebar entry, routes, screens
plugin.js server routes and lifecycle hooks
config.js default settings
admin/views/index.js the admin screen
admin/templates/index.html
admin/css/index.css
docs/guide.md the user guide shown under Documentation
It is created switched on. Restart (the Marketplace offers it) and Sharpening Log is in the sidebar.
Step 2: Add an API route
On the Marketplace, right-click the Tool and choose View source. The built-in code editor lists its files; a chip on each says whether saving it needs a restart (server files) or not (admin files).
Open plugin.js and add a route:
export default async function plugin(fastify, options) {
const {authenticate} = options.auth;
const BASE = '/api/plugins/sharpening-log';
fastify.get(`${BASE}/due`, {preHandler: [authenticate]}, async () => {
return {items: [
{tool: 'Bevel-edge chisel 12mm', last: '2026-09-01'},
{tool: 'No. 4 smoothing plane', last: '2026-08-14'}
]};
});
}
Save with Ctrl+S and click Restart server in the bar that appears. authenticate means only signed-in users may call it; requirePermission, requireRole and requireAdmin are there for tighter rules.
Step 3: Show it on the screen
Open admin/views/index.js. The view's onMount runs when the screen opens, with Domma's helpers to hand - H for requests, T for tables, E for toasts and dialogs:
export const indexView = {
templateUrl: '/plugins/sharpening-log/admin/templates/index.html',
async onMount($container) {
const res = await H.get('/api/plugins/sharpening-log/due');
T.create($container.find('#items-table').get(0), {
data: res.items,
columns: [{key: 'tool', title: 'Tool'}, {key: 'last', title: 'Last sharpened'}]
});
I.scan();
}
};
Admin files need no restart - reload the screen and the table is there. The admin wraps your screen in its standard banner with the Tool's name and version.
Step 4: Give it a sidebar badge
In plugin.json, add "countUrl": "/api/plugins/sharpening-log/_count" to the sidebar entry, and a matching route that answers {count: 2, label: '2 due'}. The sidebar shows the number and refreshes it every minute - the same badges the built-in Tools use.
Step 5: Add settings without writing a form
List the settings in plugin.json:
"settingsSchema": [
{"key": "intervalDays", "label": "Sharpen every (days)", "type": "number", "min": 7, "max": 180},
{"key": "remind", "label": "Send reminders", "type": "boolean"}
]
Put their defaults in config.js. The Tool's details panel in the Marketplace now has a Configure form built from them, and your code reads the saved values from options.settings. Mark a field "secret": true and it is masked in the browser.
Step 6: Take it further
The same hooks power every Domma Tool:
registerShortcode- your own[shortcode]for pagesnotifyandregisterNotificationSource- notices in the admin bell, on a scheduleregisterSitemapSource,registerCalendarSource,registerComponentpermissionsandroles/*.jsonin the manifest - your own permission area and rolesrequiresanduses- declare which Tools yours depends on
When it is ready, Export .dcmsplugin from the Marketplace gives you one file to install on another site with Install from file.
What you built
A real Tool, written in the admin: a sidebar entry, a protected API route, a screen with a table, a live badge and a settings form - the same building blocks as every Tool in the Marketplace.
Keep going
- The full reference: Documentation > Tutorials > Writing a Plugin in the admin, and
docs/plugin-development.md - Switching Tools on and off
- Ship a public JSON API in five minutes - when you need data without code
Try it on your own site
Everything in this tutorial is free. One command gets you a site to follow along on.