Icons in templates
Menus, view tabs and section templates name their icons as Lucide names (ShoppingCart,
Users, FileText). In the backend app a React component resolves that string. A
server-rendered page has no React, so the same name is drawn by the lucide() template global.
lucide(name)
Section titled “lucide(name)”<span class="tile">{{ lucide('ShoppingCart', size=18) }}</span>It returns an inline <svg>, already marked safe — no |safe needed, and no escaping to
undo. It is installed on every module template environment alongside t, image and money,
so a theme, an app-store section or a report gets it without importing anything.
| argument | default | what it does |
|---|---|---|
name | — | Lucide icon name. PackageIcon, LucidePackage, package and package-icon all resolve to Package. |
size | 24 | Width and height in px. The viewBox is always 0 0 24 24, so the drawing scales. |
stroke_width | 1.8 | Lucide’s own default is 2; 1.8 reads better at small tile sizes. |
css_class | "" | Class on the <svg> itself. |
Colour comes from CSS, not from an argument
Section titled “Colour comes from CSS, not from an argument”The icon renders with stroke="currentColor" and no fill, so it takes the colour of whatever
it sits inside:
<span class="tile" style="background: {{ app.menu_color }}"> {{ lucide(app.icon, size=18) }}</span>.tile { color: #fff; } /* the icon follows */.tile:hover { color: var(--theme-primary); }That is deliberate — an icon whose colour is baked into its markup cannot respond to a hover state, a dark mode, or the theme’s palette.
An unknown name renders nothing, not an error
Section titled “An unknown name renders nothing, not an error”If the name is not a Lucide icon, lucide() returns an empty string. Your container still
renders and is simply empty, rather than the page failing over a decoration.
The practical consequence: wrap the call in the element you want to see either way. If the tile is what carries the background and border, put the call inside the tile — not the other way round.
Two things follow from this:
- A typo renders silently. Validate authored names the same way the view gate does rather than relying on the page to complain.
- Only the icons this repo references ship with geometry, so a name that is a real Lucide icon but appears nowhere in any module’s YAML has no path data on the server and draws nothing. If you name icons somewhere the scan does not look (a database value, a computed string), reference them once in your module’s YAML so they are included.