i99dash docs
Themes

ThemeSpec

The design-token document the car paints — colors, wallpaper, typography, shape, and gauge, with the hex rule and defaults.

ThemeSpec is the inline spec object inside a ThemeManifest — the design-token document the car consumes to build a Flutter ThemeData via AppTheme.fromSpec(). It is embedded in the catalog row so a tile can render a palette preview without downloading the bundle.

Omitting wallpaper, typography, shape, and gauge reproduces the car's default look exactly — the feature ships inert.

Top-level

FieldTypeRequiredDefaultNotes
schemaint ≥ 1no1Spec document version. Must equal the host's THEME_SCHEMA to be fully understood; a higher value tells the car to fall back to its built-in default theme.
brightness"light" | "dark"yesDrives the ThemeData base brightness.
colorsobjectyesThe color tokens. See Colors.
wallpaperobjectnoOptional wallpaper layer. See Wallpaper.
typographyobjectnoOptional font overrides. See Typography.
shapeobjectnoOptional corner-radius tokens. See Shape.
gaugeobjectnoOptional gauge skin. See Gauge.

The object is strict — an unknown key at any level fails validation (it is almost always a typo for one of the fixed fields).

The hex format rule

Every color value is a hex string matching ^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$ — that is, #RRGGBB or #AARRGGBB, case-insensitive. The 8-digit form is alpha-first (ARGB), matching the Flutter Color parser on the car.

Colors

The 8 surface keys map 1:1 onto the car's internal _Palette; the brand/semantic keys map onto the Material ColorScheme. All surfaces plus accent/secondary/error are required; warning and neutral are optional and fall back to the car's built-in values.

Surfaces (required)

KeyMaps toNotes
background_Palette backgroundThe base canvas behind everything.
surfaceLow_Palette low surfaceRecessed / lowest-elevation surface.
surfaceContainer_Palette containerDefault container/panel fill.
surfaceHigh_Palette high surfaceRaised / highest-elevation surface.
outline_Palette outlinePrimary border/divider color.
outlineVariant_Palette outline variantSubtler border/divider color.
onSurface_Palette on-surfacePrimary text/icon color on surfaces.
onSurfaceVariant_Palette on-surface variantSecondary/muted text on surfaces.

Brand / semantic

KeyRequiredMaps toDefault
accentyesColorScheme.primary (replaces direct AppColors.accent)
secondaryyesColorScheme.secondary
erroryesColorScheme.error
warningnoAppColors.warningcar built-in
neutralnoAppColors.neutralcar built-in

Wallpaper

Optional whole object; every field is an optional bundle-relative path the publish service rewrites to a CDN URL at submit time (identical to icon). Omit the object for "no wallpaper — paint the solid surface colors". Allowed extensions: PNG / JPEG / WebP / SVG.

KeyRequiredNotes
homenoPainted behind the home surface (light/default).
homeDarknoOptional dark-mode variant of the home wallpaper.
clusternoPainted behind the instrument-cluster surface.

Typography

Optional. v1 prefers system families (Inter / Cairo). Omit the whole object to inherit the host font (Inter/Cairo by locale).

KeyTypeDefaultNotes
familystring (1–64 chars)"Inter"Font family name.
bundledbooleanfalsetrue → the family ships in the bundle fonts/ dir. Reserved for a future host release; the car may ignore it in v1.

Shape

Optional corner-radius tokens. The defaults reproduce the car's exact current look, so omitting shape is zero visual change.

KeyTypeDefaultRange
cardRadiusnumber240–48 — card/panel corners.
buttonRadiusnumber140–48 — button corners.
inputRadiusnumber140–48 — text-input corners.

Gauge

Optional gauge skin. The car may ignore this in v1 — it is parsed and round-tripped so a future host can render it without a schema bump.

KeyTypeRequiredNotes
skinstring (1–32 chars)yesSkin identifier. The car maps known names to a painter and falls back to its default for unknown values.
ringColorhex colornoRing accent. Defaults to colors.accent on the car.

Full example

{
  "schema": 1,
  "brightness": "dark",
  "colors": {
    "background": "#07070D",
    "surfaceLow": "#0F1018",
    "surfaceContainer": "#13141C",
    "surfaceHigh": "#1A1C26",
    "outline": "#4B5064",
    "outlineVariant": "#24262F",
    "onSurface": "#F3F4F8",
    "onSurfaceVariant": "#8A90A4",
    "accent": "#22D3A8",
    "secondary": "#5B8CFF",
    "error": "#E76F51",
    "warning": "#F4A261",
    "neutral": "#6A7088"
  },
  "wallpaper": {
    "home": "./wallpaper/home.png",
    "homeDark": "./wallpaper/home-dark.png",
    "cluster": "./wallpaper/cluster.png"
  },
  "typography": { "family": "Inter", "bundled": false },
  "shape": { "cardRadius": 24, "buttonRadius": 14, "inputRadius": 14 },
  "gauge": { "skin": "neon", "ringColor": "#22D3A8" }
}

On this page