docs themes.md

Themes are server-owned and account-selected

A LEMC theme supplies the compiled CSS, icons, and images for an account’s web interface. The server owns the installed files; an account admin chooses which installed theme the account uses.

A teammate or agent should not need server filesystem access just to inherit the team’s visual language.

Can a user or agent upload a theme?

Not through LEMC today. Current releases do not expose a browser upload, theme-upload API, or lemcli themes push command. A basic member or cookbook author cannot install or activate a theme.

This is an important product boundary: theme files load as same-origin interface assets and affect everyone in the account. For now, the server operator installs those files. An account admin can then activate an installed theme in the browser or through lemcli. An agent can perform that selection only when its credential has account-admin authority.

Authority map

ActorWhat they can do todayWhat they cannot do
Server operatorInstall or replace a theme under persistent server assets.Does not choose an account theme unless also acting as its admin.
Account adminSelect an installed theme in Account Settings or with lemcli.Cannot upload theme files through LEMC.
Member or cookbook authorInherit the account’s current theme.Cannot install or activate an account theme with basic cookbook authority.
AgentRead or set the selected theme through structured CLI output when its identity is an account admin.Gets no special theme authority for being an agent and has no upload command.

Pattern: theme the LEMC workflow your team already uses

A corporate theme changes LEMC’s logo, colors, icons, background, and typography without replacing the application underneath. The signed-in identity, app metadata, Individual/Shared/ACL scope tabs, page wiki, recipe action, monitor, and durable result remain in the same familiar places.

  • Identity and discovery: the navbar shows the signed-in teammate while app ACLs decide which apps and actions that identity can see.
  • Context and action: each app page keeps its wiki, uploaded wiki images, declared form inputs, and bounded recipe action together. The wiki can explain exactly what every recipe button does before a teammate runs it.
  • Progress and proof: the monitor, events, logs, terminal result, and artifacts stay attached to the job after the theme changes.

The homepage’s Cloud Casserole example gives the fake user Maya access to a People Operations app, then applies the company logo, layered blue palette, and clean sans-serif application type. Its five-second automatic crossfade introduces the change. Only after it completes do the compact previous and next controls appear on either side of the caption below the iframe. Their restrained outline and shallow shadow separate them from the caption without covering the preview. They switch immediately so an operator can compare both presentations without losing the app context. Finance Reporting, Leadership Briefing, and Web Filter Review can remain separate apps with separate ACLs for the teams that need them.

Teammates use that branded LEMC web UI. Agents use the same action contract through lemcli and receive the same task identity, events, artifacts, and terminal result. The theme changes presentation; it never grants permission by itself.

Create the theme with a natural-language agent

You do not need to hand-style every page. Give Codex, Grok, Kimi, or another agent a company logo, the primary and accent colors, accessibility requirements, and a short description of the desired feel. Ask it to start from the built-in default or banilla theme tree, preserve the required file layout, and return a reviewable bundle.

A useful brief can be this small:

Theme name: acme
Logo assets: ./brand/
Primary color: #243b64
Accent color: #f2a900
Direction: calm, technical, and familiar to our operations team

Adapt the built-in default theme. Map the supplied logo and colors,
preserve every required asset, check desktop and mobile layouts,
check readable contrast, and return the bundle plus a changed-file list.
Do not install or activate it.

The agent helps create the files; it receives no special LEMC authority. A server operator reviews and installs the bundle, then an account admin selects it. Teammates who only know the web UI inherit the result the next time they load the account.

Operator: install the bundle

Theme names may contain letters, numbers, and hyphens. Install the complete bundle under the environment’s persistent asset tree:

<LEMC_DATA>/<LEMC_ENV>/assets/themes/<theme-name>/public/
├── css/
│   ├── compiled.css
│   └── icons.css
└── imgs/
    ├── 16x16.ico
    ├── 32x32.ico
    ├── 64x64.ico
    ├── 128x128.ico
    ├── 256x256.ico
    └── placeholder.png

A theme may include the additional backgrounds, logos, and other images referenced by its CSS. Start from the built-in default or banilla public tree so the expected interface assets remain present.

With the repository’s production Compose layout, LEMC_DATA=/app/data is backed by ./data on the host, so an installed theme lives at:

./data/production/assets/themes/acme/public/

Stage the entire directory before activation. LEMC discovers installed theme directories from the asset tree; the built-in themes are restored there at server startup without deleting a separately named custom theme.

Admin or authorized agent: select it

In the browser, open Account → Settings, choose the installed name under Theme, and save. The route is protected by account-administration authority.

An account-admin agent uses the same account setting through structured CLI output:

lemcli account settings get --format=json
lemcli account settings set --theme acme --format=json

The CLI changes the selected name; it does not transfer or validate a bundle. Verify the theme is fully installed before selecting it. To roll back, select a known built-in theme:

lemcli account settings set --theme default --format=json

Verify and retain it

  1. Hard-refresh an authenticated account page and confirm the selected CSS and icons return HTTP 200.
  2. Check Account Settings with lemcli account settings get --format=json.
  3. Exercise desktop and mobile pages before inviting the team back in.
  4. Keep the custom theme under persistent LEMC_DATA and include the assets tree in backup and restore operations.

What a governed upload should require

A first-party upload flow is a reasonable future capability, but it is not available in current releases. It should be an account-admin or narrower theme-publisher operation with one API shared by web and lemcli, not an unrestricted file upload.

  • a manifest, version, content digest, file-count limit, and total-size limit;
  • safe archive extraction with path, symlink, and file-type validation;
  • no HTML or JavaScript payloads, plus explicit CSS and image policy;
  • immutable staging and preview before a separate publish and activate decision;
  • an audit event naming the publisher, digest, account, previous theme, and rollback target.

Giving an automation agent host filesystem access is not a substitute for that governed upload contract.