CSS Variable Theming
The --hg-* CSS custom property namespace, defined variables, default values, and theme injection mechanism.
HyperGen uses CSS custom properties (CSS variables) to bridge the host application's design system into the sandboxed iframe. All HyperGen theme variables live in the --hg-* namespace.
How Theme Injection Works
- The host application collects its design tokens (colors, fonts, spacing, radii) and maps them to
--hg-*variables. - The host sends a
hg:themepostMessage to the iframe with avarsobject containing the CSS variable key-value pairs. - The iframe's postMessage bridge sets each variable on
document.documentElement.style, making them available to all content viavar(--hg-*). - Agent-generated HTML references these variables in its CSS, inheriting the host's visual design.
Host: "My primary color is #7c3aed"
│
├── Maps to: --hg-accent: #7c3aed
│
└── postMessage({ type: "hg:theme", vars: { "--hg-accent": "#7c3aed" } })
│
└── Iframe: document.documentElement.style.setProperty("--hg-accent", "#7c3aed")
│
└── Agent CSS: background: var(--hg-accent) → renders as #7c3aedDefined Variables
Color Variables
| Variable | Required | Default | Description |
|---|---|---|---|
--hg-surface | MUST | #ffffff | Primary background surface color. |
--hg-surface-elevated | SHOULD | #f9fafb | Elevated surfaces (cards, popovers, modals). |
--hg-text | MUST | #111827 | Primary text color. |
--hg-text-muted | SHOULD | #6b7280 | Secondary / muted text color. |
--hg-accent | MUST | #7c3aed | Accent / brand color for interactive elements (buttons, links). |
--hg-accent-fg | MUST | #ffffff | Foreground color for text on accent-colored backgrounds. |
--hg-border | MUST | #e5e7eb | Border and separator color. |
--hg-background | MAY | transparent | The iframe body background. Defaults to transparent so the host background shows through. |
Typography Variables
| Variable | Required | Default | Description |
|---|---|---|---|
--hg-font-family | SHOULD | system-ui, -apple-system, sans-serif | Base font family. |
--hg-font-mono | SHOULD | ui-monospace, monospace | Monospace font family for code blocks. |
--hg-font-size | MAY | 16px | Base font size. |
--hg-line-height | MAY | 1.5 | Base line height. |
Spacing Variables
| Variable | Required | Default | Description |
|---|---|---|---|
--hg-space-1 | SHOULD | 4px | Extra-small spacing (tight gaps, icon padding). |
--hg-space-2 | SHOULD | 8px | Small spacing (element gaps, compact padding). |
--hg-space-4 | SHOULD | 16px | Medium spacing (section padding, card padding). |
--hg-space-8 | SHOULD | 32px | Large spacing (section margins, major separators). |
Shape Variables
| Variable | Required | Default | Description |
|---|---|---|---|
--hg-radius | SHOULD | 8px | Default border radius. |
--hg-radius-sm | MAY | 4px | Small border radius (chips, badges). |
--hg-radius-lg | MAY | 12px | Large border radius (cards, modals). |
Required vs Optional Variables
The host application MUST provide the five required color variables (--hg-surface, --hg-text, --hg-accent, --hg-accent-fg, --hg-border). These are the minimum needed for agent-generated UI to be visually coherent with the host.
All other variables are SHOULD or MAY. When a variable is not provided by the host, agents MUST use the var() fallback syntax with the default value:
/* Good: fallback ensures the UI works without theme injection */
background: var(--hg-surface-elevated, #f9fafb);
border-radius: var(--hg-radius, 8px);
font-family: var(--hg-font-family, system-ui, -apple-system, sans-serif);Default Theme
The reference implementation provides a default light theme. Implementations MAY use different defaults as long as they provide all required variables.
:root {
/* Colors (required) */
--hg-surface: #ffffff;
--hg-surface-elevated: #f9fafb;
--hg-text: #111827;
--hg-text-muted: #6b7280;
--hg-accent: #7c3aed;
--hg-accent-fg: #ffffff;
--hg-border: #e5e7eb;
/* Typography */
--hg-font-family: system-ui, -apple-system, sans-serif;
--hg-font-mono: ui-monospace, monospace;
--hg-font-size: 16px;
--hg-line-height: 1.5;
/* Spacing */
--hg-space-1: 4px;
--hg-space-2: 8px;
--hg-space-4: 16px;
--hg-space-8: 32px;
/* Shape */
--hg-radius: 8px;
--hg-radius-sm: 4px;
--hg-radius-lg: 12px;
}Theme Updates
The host MAY send multiple hg:theme messages during the iframe's lifetime. Each message is additive — it sets the specified variables without clearing previously set ones.
Common scenarios:
- Dark mode toggle: The host re-sends all color variables with dark-mode values.
- User preference change: The host updates a subset of variables (e.g., accent color only).
- Initial + deferred: The host sends required variables immediately, then optional variables after loading its full theme.
// Toggle to dark mode
controller.setTheme({
"--hg-surface": "#1a1a2e",
"--hg-surface-elevated": "#16213e",
"--hg-text": "#e0e0e0",
"--hg-text-muted": "#9ca3af",
"--hg-accent": "#8b5cf6",
"--hg-accent-fg": "#ffffff",
"--hg-border": "#374151",
});Agent Usage Guidelines
Agents SHOULD use --hg-* variables in all generated CSS to ensure visual consistency with the host:
<style>
.result-card {
background: var(--hg-surface-elevated, #f9fafb);
color: var(--hg-text, #111827);
border: 1px solid var(--hg-border, #e5e7eb);
border-radius: var(--hg-radius, 8px);
padding: var(--hg-space-4, 16px);
font-family: var(--hg-font-family, system-ui, sans-serif);
}
.result-card h2 {
color: var(--hg-text, #111827);
margin: 0 0 var(--hg-space-2, 8px);
}
.result-card .muted {
color: var(--hg-text-muted, #6b7280);
}
.result-card button {
background: var(--hg-accent, #7c3aed);
color: var(--hg-accent-fg, #ffffff);
border: none;
border-radius: var(--hg-radius-sm, 4px);
padding: var(--hg-space-2, 8px) var(--hg-space-4, 16px);
cursor: pointer;
}
</style>Agents SHOULD NOT:
- Use hardcoded color values for primary UI elements (backgrounds, text, borders, buttons).
- Define their own color scheme that ignores
--hg-*variables. - Override
--hg-*variables on:root(this conflicts with the host's theme injection).
Agents MAY use custom CSS variables (not in the --hg-* namespace) for component-internal values like animation durations or specific layout dimensions.
Extending the Variable Namespace
Implementations that need additional theme variables beyond those defined here SHOULD use a sub-namespace:
--hg-x-myapp-sidebar-width: 280px;
--hg-x-myapp-header-height: 64px;The --hg-x- prefix indicates an extension variable. Standard HyperGen variables MUST NOT use the --hg-x- prefix.
postMessage Protocol
All postMessage types exchanged between the HyperGen host application and the sandboxed iframe, with exact JSON shapes and origin validation rules.
Agent Authoring Guidelines
Best practices for AI agents generating HyperGen-compatible HTML fragments: HTMX attributes, CSS theming, self-containment, and accessibility.