Admin templates & the WASM client
The admin’s look is not baked into the binary. Every /cms page is rendered from a plain Handlebars file in your site’s hbs/cms/, and WHICH file renders a section is declared in the menu item itself (hbs, plus form.hbs for the row page) — name the templates whatever you like. Only two names are fixed: cms/login and cms/invite, the pre-session sign-in pages.
Context of every admin render
menu — the items this visitor’s role may open (the layout builds its nav from it); session — user_id, role, is_admin; title. Page-specific variables:
| page | variables |
|---|---|
| a section with a list view | columns, id_col, rows, total, next_cursor, section (the item path — build links as /cms{{section}}/{{id}}), has_form |
| the row page (/cms/{path}/new and /{id}) | fields (name, widget, required, max_length, value), row, mode, action, delete_action |
| the built-in users view | rows: id, login, role, created_at, soe |
| the built-in media view | rows: id, url, ext, size, created |
| login, invite | bare: true — no session yet, the layout hides the sidebar |
Generic by default
This site ships generic cms/list and cms/form templates that render ANY section from that context — point several menu items at the same files, or write a custom template per section. Admin templates wrap themselves in the admin skeleton partial ({{#> _cms}} here) like any page.
One hard rule
Raw triple-braced output ({{{…}}}) is forbidden in every template the admin pages reach: those pages show data submitted through public forms, and unescaped output would run it as a script in the admin’s browser. The server scans the admin set at start and reload, and cms check names the offending file and line.
The WASM sign-in client
The sign-in, invite and password pages carry scripts for a reason: passwords never leave the browser. The cryptography (the OPAQUE protocol) runs in a WASM module embedded in the binary and served at /static/wasm/cmsnap_wasm.js; the scripts in static/js/cms-*.js load it and talk to the /cms/login, /cms/invite and /cms/passwd endpoints. Restyle these pages freely — just keep the script includes, or there is no way to sign in.