Theming
read as.mdA @guuey/chat theme is data, not CSS — a serializable token object you can keep in code, in config, or in a database. The React kit projects it as --guuey-chat-* CSS custom properties on the transcript root; the React Native tier maps the same object to style values. One schema, two projections.
The schema
Section titled “The schema”interface GuueyChatTheme { name: string; /** BOTH palettes always present — mode is the consumer's runtime choice. */ colors: { light: GuueyChatPalette; dark: GuueyChatPalette }; typography: { fontFamily?: string; monoFontFamily?: string; scale?: number }; shape: { radius: "none" | "soft" | "round"; density: "compact" | "comfortable"; };}
interface GuueyChatPalette { accent: string; // primary action + user bubble onAccent: string; // text on accent ink: string; // primary text inkMuted: string; // secondary text surface: string; // bubbles, cards canvas: string; // page background behind the transcript canvasMuted: string; // grouped/collapsed rows, wells error: string;}Both palettes are always present in a theme; which one paints is the mode prop ("light" / "dark") — so switching modes is a runtime choice, never a second theme object.
The two shipped themes
Section titled “The two shipped themes”DEFAULT_CHAT_THEME— brand-neutral and polished; what you get without configuring anything. Designed to sit inside your product without announcing guuey.GUUEY_CHAT_THEME— the guuey visual identity (the widget’s shipped palette). Use it when you want the surface to read as guuey.
import { GUUEY_CHAT_THEME } from "@guuey/chat";
<GuueyChat endpointUrl="…" appId="…" theme={GUUEY_CHAT_THEME} mode="dark" />;Your own theme
Section titled “Your own theme”resolveTheme merges a partial theme over the default per token — supply only what you change:
import { resolveTheme, type GuueyChatTheme } from "@guuey/chat";
const brandTheme: GuueyChatTheme = resolveTheme({ name: "acme", colors: { light: { accent: "#7c3aed", onAccent: "#ffffff" }, dark: { accent: "#a78bfa" }, }, shape: { radius: "round", density: "compact" },});
<GuueyChat endpointUrl="…" appId="…" theme={brandTheme} mode="dark" />;Every token you omit falls back to the default theme’s value — a half-configured theme can never produce an unreadable surface.
The evolution promise
Section titled “The evolution promise”The schema is built to be stored: parsing is lenient (unknown keys pass through rather than failing), changes to the schema are additive-only, and every new token ships with a default fallback — so a theme object saved today keeps parsing against every future version of the package.
That posture is what makes the theme safe to store as platform data — which is exactly what per-app theme configuration does.
Theme the hosted surfaces
Section titled “Theme the hosted surfaces”You can set a theme once per app in the console: your app’s Design page on platform.guuey.com has a theme editor over this same schema, with a live transcript preview, validated on save. Every surface guuey hosts for the app picks it up — the embedded widget, the app’s standalone page, and Portal chat — with no redeploy.
The editor lives on the app’s Design page in the console; branding and the distribution tabs are covered on the same docs page — Design & distribution.
Your own @guuey/chat mounts are unaffected: the theme prop you pass always wins on surfaces you render yourself.
Fine-grained control
Section titled “Fine-grained control”The projection is ordinary CSS custom properties, so anything the token schema doesn’t express can be adjusted in your own stylesheet against the kit’s class names — or by replacing a component slot entirely. Prefer tokens first: they’re what survives schema evolution, and what the console’s per-app theme stores.