Skip to content

Theming

FanFest supports full visual customization through a two-layer theming system. Admins can customize every color in the interface using the built-in theme editor, apply community-specific themes, or select from pre-built theme presets.

Theming Architecture

Two-Layer System

FanFest themes operate on two token layers:

  1. V1 (legacy) --- 12 brand tokens (--brand-primary, --brand-bg-main, etc.) that control the high-level brand palette. These are the original theming tokens and are still read by older components.

  2. V2 (design tokens) --- 64 granular tokens covering Background, Surface, Fill, Text, Border, and Icon categories. These provide fine-grained control over every UI element. See the Design Tokens reference for the full list.

Both layers are stored together in a single theme configuration record. When a theme is loaded, both V1 and V2 tokens are applied as CSS custom properties on the root element, so all components --- legacy and current --- render correctly.

Theme Hierarchy

Themes apply at three levels, with more specific levels overriding broader ones:

  1. Channel theme --- The default theme for the entire channel. Set by the Admin in Channel Settings.
  2. Community theme --- An optional override for a specific community within the channel. When a fan selects a community, its theme replaces the channel theme.
  3. Show theme --- A per-show override chosen during show creation. The Host can pick the channel theme, a community theme, or a fully custom theme for each show.

When the frontend loads, the theme store fetches the appropriate theme via the getBrandTheme GraphQL query and injects all token values as CSS custom properties.

Theme Editor

The built-in theme editor is available to Admins in Channel Settings. It provides a visual interface for customizing all 64 V2 design tokens with live preview.

Accessing the Theme Editor

  1. Navigate to your Channel Settings page
  2. Open the Appearance or Theme section
  3. Click Customize Theme to open the color editor modal

How It Works

The editor organizes tokens into sections matching the design token categories:

  • Background --- bg, bg_secondary
  • Surface --- surface, surface_hover, surface_secondary, surface_secondary_hover, surface_accent
  • Fill --- All 20 fill tokens (brand, dark, status, medal colors)
  • Text --- All 14 text tokens
  • Border --- All 15 border tokens
  • Icon --- All 8 icon tokens

Each token is displayed with its CSS custom property name (e.g., --fill-brand), a hex color input field, and a color picker circle. You can type hex values directly or use the visual picker.

The editor validates input in real time --- invalid hex values are highlighted and cannot be saved.

Saving Themes

When you click Save, the editor calls the upsertBrandTheme GraphQL mutation, which persists all token values to the database. The theme store then refetches the active theme so the entire interface updates immediately.

Community Themes

Each community within a channel can have its own theme. This is useful for sports organizations where each fan community (team) has distinct brand colors.

How Community Themes Work

  • Every community is automatically assigned a theme configuration when the channel loads community themes
  • Admins can customize each community's theme independently through Channel Settings
  • When a fan selects a community, the theme switches to that community's colors
  • The community theme overrides the channel theme across all surfaces

Setting a Community Theme

  1. Go to Channel Settings
  2. Navigate to the Communities section
  3. Select a community to customize
  4. Use the theme editor to set that community's colors

Show Themes

When creating a show, the Host can choose which theme to apply:

  • Channel theme --- Use the channel's default colors
  • Community theme --- Select from any community theme available on the channel via a dropdown
  • Custom theme --- Pick a custom background tint color for that specific show

The show theme is saved via the upsertShowTheme GraphQL mutation and applies only to that show's viewer experience.

Programmatic Theming

Fetching the Active Theme

graphql
query BrandTheme($channel_id: String, $community_id: String) {
  getBrandTheme(channel_id: $channel_id, community_id: $community_id) {
    ... on BrandTheme {
      id
      fill_brand
      fill_brand_hover
      bg
      bg_secondary
      text
      text_secondary
      # ... all 64 V2 tokens + 12 V1 tokens
    }
    ... on NotFoundError {
      error
    }
  }
}

Pass channel_id to get the channel theme, or community_id to get a community-specific theme.

Updating a Theme

graphql
mutation UpsertBrandTheme($data: UpsertBrandThemeInput!) {
  upsertBrandTheme(data: $data) {
    id
  }
}

The UpsertBrandThemeInput accepts all 64 V2 token fields plus the 12 V1 legacy fields as hex color strings. Pass the theme id to update an existing theme, or omit it to create a new one.

Admin Permission Required

The upsertBrandTheme mutation requires Admin permissions on the channel.

Applying Tokens in Code

Tokens are applied as CSS custom properties on the root element by the theme store. To use them:

In CSS:

css
.my-component {
  background: var(--fill-brand);
  color: var(--text-on-brand);
}

In Tailwind:

html
<div class="bg-fill-brand text-text-on-brand border border-border-brand">
  Themed content
</div>

Reading values in JavaScript:

javascript
const brandColor = getComputedStyle(document.documentElement)
  .getPropertyValue('--fill-brand')
  .trim();

Theme Defaults

When no custom theme is configured, FanFest uses a default dark theme with the following key values:

TokenDefaultDescription
--bg#100B1EDeep purple-black background
--fill-brand#875AF9FanFest indigo (primary brand)
--text#FFFFFFWhite primary text
--fill-success#0DD32DGreen
--fill-critical#ED3024Red
--fill-warning#FF8D3AOrange

See the full default value table in Design Tokens.

Released under the MIT License.