xPulse
🇩🇪 DE

API

init(options = {})

import theme from '@xpulse/theme';
await theme.init();
// Mit Optionen
await theme.init({ root: process.cwd(), force: false });

Baut das CSS-Bundle, schreibt den Cache, registriert die HTTP-Routen und hängt sich in http:response:before ein — ab dann werden CSS-Bundle, Anti-FOUC-Script und theme.js automatisch in jede HTML-Antwort injiziert. themeAssets() im Template ist damit optional.

Option Typ Beschreibung Default
root string Basis-Verzeichnis – bestimmt wo nach src/themes/ gesucht wird process.cwd()
force boolean Cache ignorieren und Bundle neu aufbauen false

init() ist idempotent – mehrfache Aufrufe werden ignoriert.


href()

theme.href();
// → '/_theme/css/xpulse.css'

URL des gebündelten CSS (Base + Components + alle Themes, minifiziert).

scriptHref()

theme.scriptHref();
// → '/_theme/theme.js'

URL des Browser-Runtime-Scripts (Theme-Toggle, Token-Editor).


current()

theme.current();
// → 'dark'

Aktuelles Default-Theme laut Config (theme.default in xpulse.json).

available()

theme.available();
// → ['dark', 'light']

Alle Themes die im gebündelten CSS per [data-theme="..."]-Selektor entdeckt wurden.

allowed()

theme.allowed();
// → ['dark', 'light']

Subset von available(), gefiltert durch theme.allow in xpulse.json. Wenn theme.allow leer oder nicht gesetzt – identisch mit available().

has(name)

theme.has('dark'); // → true
theme.has('foo'); // → false

Prüft ob ein Theme im Bundle bekannt ist.


set(name)

theme.set('light'); // → true
theme.set('foo'); // → false (unbekannt)

Setzt das aktuelle Theme. Gibt false zurück wenn das Theme unbekannt oder nicht in allowed() ist.

toggle()

theme.toggle();

Wechselt zwischen den zwei erlaubten Themes. Gibt false zurück wenn allowed() nicht exakt 2 Einträge hat.


Registrierte Routen

Route Beschreibung
GET /_theme/css/xpulse.css Minifiziertes All-in-One-CSS-Bundle
GET /_theme/theme.js Browser-Runtime-Script

Template-Methoden

`themeAssets()`

{% themeAssets() %}

Rendert:

`themeSwitcher()`

{% themeSwitcher() %}

Rendert keinen Output wenn allowed() nur 1 Theme enthält. Bei genau dark + light → kompakter Mond/Sonne-Toggle-Button. Bei mehr als 2 Themes → <select>-Dropdown.

`themeTokenEditor()`

{% themeTokenEditor() %}

Live-Editor für ausgewählte :root-Tokens. Setzt CSS Custom Properties direkt im Browser und speichert Overrides in localStorage.


Discovery

Theme-Namen werden aus dem gebündelten CSS per Regex ermittelt:

[data-theme="dark"] → 'dark'
[data-theme="light"] → 'light'

CSS-Quelldateien werden in dieser Reihenfolge gebündelt:

1. public/css/base.css
2. public/css/components/*.css (via @import in components.css)
3. public/css/themes/*.css (Built-in Themes)
4. src/themes/*.css (App-Overrides, optional)

Caching

Das Bundle wird in var/cache/theme/xpulse.css gecacht.

{
"theme": {
"cache": {
"enabled": true,
"ttl": 0
}
}
}

ttl: 0 = kein Ablauf. ttl: 3600 = Cache nach 1 Stunde ungültig.


Events

Bundle-Build

Event Payload Wann
themes:load:start Build beginnt
theme:basics:loaded base.css geladen
theme:components:loaded Alle Component-CSS geladen
theme:loaded { name } Einzelnes Theme-CSS geladen
themes:concatenated Alle Parts zusammengefügt
themes:minified Bundle minifiziert
themes:cached { path } Bundle auf Disk geschrieben
themes:load:end Build abgeschlossen
theme:ready { theme, available } init() vollständig

Cache

Event Payload Wann
themes:cache:hit { path } Gültiger Cache-File gefunden
themes:cache:miss Bundle wird neu gebaut
themes:cache:loaded { serveCount } Bundle-Request bedient

Laufzeit

Event Payload Wann
theme:changed { from, to } set() / toggle() erfolgreich
theme:warning { type, … } Ungültiges/verbotenes Theme, Toggle-Fehler
theme:error { type } Keine Themes im Bundle gefunden
de/api.md 2026-03-26