Your brand, no build step.
A daisyUI 5 theme is nothing but a block of CSS custom properties scoped to a data-theme selector — so ApiGlow can accept yours at runtime. Two channels exist, by design, and both take the daisyUI theme generator’s output as-is.
Channel 1: the config
Declare the theme in theme.custom; the app generates and injects its CSS at boot.
{
"theme": {
"default": "acme",
"available": ["acme", "light", "dark"],
"custom": [
{
"name": "acme",
"extends": "dark",
"tokens": {
"--color-primary": "#6d28d9",
"--color-primary-content": "#f5f3ff",
"--radius-box": "0.5rem"
}
}
]
}
}name— required,[a-z][a-z0-9-]*. Naming it after a built-in theme (light,dark, …) restyles that theme in place — the cheapest “keep light and dark, brand the primary” path.extends— optional, any built-in daisyUI theme to inherit from. The primary use case is “dark, but in our colors”: a handful of tokens. Without it, unset tokens fall back to the build’s default theme, so declare the full set — the generator emits every token anyway. Extending another custom theme is not supported.colorScheme— optional"light"or"dark", drives browser-provided UI (scrollbars, form controls). Inherited fromextendswhen absent.tokens— daisyUI 5 theme variables under their verbatim names: the twenty--color-*, the radii and sizes,--border,--depth,--noise. This is why generator output pastes straight in.
List the theme in theme.available too, or it is injected but not selectable.
Channel 2: your own CSS
Zero config beyond the listing: a plain block in the host page’s stylesheet, and the name in theme.available.
[data-theme="acme"] {
color-scheme: dark;
--color-primary: #6d28d9;
--color-primary-content: #f5f3ff;
/* …the rest of the daisyUI theme variables… */
}Undefined tokens fall back to the default theme’s values. When the goal is restyling a built-in theme name in place, prefer the config channel: it mirrors daisyUI’s own selectors, so it keeps working regardless of how daisyUI layers its styles.
Validation is lenient, on purpose
A theme is a styling concern, so nothing about it is allowed to break the page: an unknown token or an invalid value is skipped with a console warning, a custom name missing from available is flagged (likely a config mistake) but still injected, and a duplicate name warns and keeps the first. The worst a bad theme can do is look wrong.
In multi-spec
theme.custom is root-only — themes are global chrome, injected once at boot. A specs[] entry may still override theme.default and theme.available: a spec narrows what is selectable, it never defines a theme. Details in the multi-spec guide.
The rest of the branding story — product name, logo, footer links, and the one thing that always stays — lives on the Theming & branding feature page.