Skip to content

Branding

Avo's branding feature lets you customize the look and feel of your admin panel — logos, colors, color scheme, and chart colors. It supports two modes: static (you choose the theme once) and dynamic (users can switch themes on the fly).

Configuration

All branding options are configured through config.branding as a hash in your config/initializers/avo.rb file.

ruby
Avo.configure do |config|
  config.branding = {
    logo: "my_company/logo.png",
    logomark: "my_company/logomark.png",
    favicon: "my_company/favicon.ico",
    neutral: :slate,
    accent: :blue
  }
end

Logos

The logo option sets the main logo displayed in the sidebar on desktop screens.

ruby
config.branding = {
  logo: "my_company/logo.png"
}

Provide a logo_dark variant to display a different logo when the user is in dark mode.

ruby
config.branding = {
  logo: "my_company/logo.png",
  logo_dark: "my_company/logo_dark.png"
}

Mobile logomark

The logomark should be a square image used on smaller screens where the sidebar collapses.

ruby
config.branding = {
  logomark: "my_company/logomark.png",
  logomark_dark: "my_company/logomark_dark.png"
}

Favicon

Override the default favicon with your own .ico file. You can also provide a dark mode variant.

ruby
config.branding = {
  favicon: "my_company/favicon.ico",
  favicon_dark: "my_company/favicon_dark.ico"
}

Placeholder image

When a record doesn't have a cover image (e.g. in grid view), Avo shows a placeholder. You can customize it.

ruby
config.branding = {
  placeholder: "my_company/placeholder.svg"
}

Neutral theme

The neutral theme controls the base surface and border colors throughout the UI. You can set it using a predefined palette name or a custom color hash.

Predefined palettes

Choose from one of the built-in neutral palettes:

ruby
config.branding = {
  neutral: :slate
}
PaletteDescription
:slateCool blue-gray tones
:stoneWarm gray with a slight brown tint
:grayPure neutral gray
:zincCool gray with a hint of blue
:neutralPerfectly balanced gray
:taupeWarm gray with earthy undertones
:mauveGray with a subtle purple cast
:mistLight, airy blue-gray
:oliveGray with green-yellow undertones

Custom neutral colors

Pass a hash of shade values (using oklch or any CSS color format) for full control:

ruby
config.branding = {
  neutral: {
    25 => "oklch(0.99 0.01 240)",
    50 => "oklch(0.97 0.01 240)",
    100 => "oklch(0.94 0.01 240)",
    200 => "oklch(0.88 0.02 240)",
    300 => "oklch(0.80 0.02 240)",
    400 => "oklch(0.68 0.02 240)",
    500 => "oklch(0.55 0.02 240)",
    600 => "oklch(0.45 0.02 240)",
    700 => "oklch(0.37 0.02 240)",
    800 => "oklch(0.27 0.02 240)",
    900 => "oklch(0.20 0.02 240)",
    950 => "oklch(0.14 0.02 240)"
  }
}

You can also provide separate light and dark scales:

ruby
config.branding = {
  neutral: {
    light: {
      25 => "oklch(0.99 0.01 240)",
      50 => "oklch(0.97 0.01 240)",
      # ...
    },
    dark: {
      25 => "oklch(0.14 0.01 240)",
      50 => "oklch(0.18 0.01 240)",
      # ...
    }
  }
}

Accent color

The accent color is used for interactive elements like buttons, links, and highlights. Like neutrals, you can use a predefined color or a custom hash.

Predefined accent colors

ruby
config.branding = {
  accent: :blue
}

Available accent colors: red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose.

Custom accent colors

Provide three tokens — color (the main accent), content (text/icons on accent backgrounds), and foreground (alternative foreground):

ruby
config.branding = {
  accent: {
    color: "oklch(0.6 0.2 260)",
    content: "oklch(0.9 0.05 260)",
    foreground: "oklch(1.0 0 0)"
  }
}

With light/dark variants:

ruby
config.branding = {
  accent: {
    light: {
      color: "oklch(0.6 0.2 260)",
      content: "oklch(0.9 0.05 260)",
      foreground: "oklch(1.0 0 0)"
    },
    dark: {
      color: "oklch(0.7 0.2 260)",
      content: "oklch(0.3 0.05 260)",
      foreground: "oklch(0.1 0 0)"
    }
  }
}

Color scheme

Set the color scheme with scheme:

ruby
config.branding = {
  scheme: :auto # :auto | :light | :dark
}
ValueBehavior
:autoFollows the user's system preference (default)
:lightAlways starts in light mode
:darkAlways starts in dark mode

Users can always toggle between light, dark, and auto using the color scheme switcher in the sidebar.

Static vs. dynamic mode

Static mode (default)

In static mode, you lock the neutral theme and accent color in the initializer. Users can still switch between light/dark/auto, but they cannot change the color palette.

ruby
config.branding = {
  mode: :static,
  neutral: :stone,
  accent: :emerald
}

Dynamic mode

In dynamic mode, users get a theme picker in the sidebar that lets them choose their own neutral theme and accent color. Their preferences are persisted either in localStorage or in the database.

ruby
config.branding = {
  mode: :dynamic
}

Persistence

By default, theme preferences are stored in the browser's localStorage. To persist them in the database instead (so preferences follow users across devices), configure the persistence, load_settings, and save_settings options:

ruby
config.branding = {
  mode: :dynamic,
  persistence: :database, 
  load_settings: ->(current_user) { 
    current_user.theme_settings || {} 
  }, 
  save_settings: ->(settings:, current_user:) { 
    current_user.update!(theme_settings: settings) 
  } 
}

The settings hash contains up to three keys: color_scheme (light/dark/auto), neutral (theme name), and accent (accent color name).

INFO

When using database persistence, add a theme_settings JSON column (or similar) to your users table.

Chart colors

Customize the colors used in dashboard charts by passing an array of hex colors:

ruby
config.branding = {
  chart_colors: ["#0B8AE2", "#34C683", "#FFBE4F", "#FF7676", "#2AB1EE"]
}

WARNING

Chart colors must be hex values. They are forwarded directly to Chart.js.

Full example

ruby
Avo.configure do |config|
  config.branding = {
    # Logos
    logo: "my_company/logo.png",
    logo_dark: "my_company/logo_dark.png",
    logomark: "my_company/logomark.png",
    logomark_dark: "my_company/logomark_dark.png",
    favicon: "my_company/favicon.ico",
    placeholder: "my_company/placeholder.svg",

    # Theme
    mode: :dynamic,
    neutral: :slate,
    accent: :blue,
    scheme: :auto,

    # Chart colors
    chart_colors: ["#0B8AE2", "#34C683", "#FFBE4F", "#FF7676"],

    # Database persistence
    persistence: :database,
    load_settings: ->(current_user) {
      current_user.theme_settings || {}
    },
    save_settings: ->(settings:, current_user:) {
      current_user.update!(theme_settings: settings)
    }
  }
end

Options reference

OptionTypeDefaultDescription
mode:static :dynamic:staticWhether users can switch themes
scheme:auto :light :dark:autoColor scheme
neutralSymbol or HashnilNeutral palette — predefined name or custom colors
accentSymbol or HashnilAccent color — predefined name or custom tokens
persistence:localstorage :database:localstorageWhere to store user theme preferences
logoString"avo/logo.png"Desktop logo path
logo_darkStringnilDesktop logo for dark mode
logomarkString"avo/logomark.png"Mobile logo path
logomark_darkStringnilMobile logo for dark mode
faviconString"avo/favicon.ico"Favicon path
favicon_darkStringnilFavicon for dark mode
placeholderString"avo/placeholder.svg"Missing image placeholder
chart_colorsArray10 default hex colorsColors used in dashboard charts
load_settingsProcnilLambda to load theme settings from database
save_settingsProcnilLambda to save theme settings to database