How to Customize Sniffnet's Appearance with Custom Themes: A Complete Guide

Create a TOML file containing six hexadecimal color values and load it through the Appearance settings page, or set the style_path field in your configuration file to apply a custom theme automatically.

Sniffnet's interface is controlled by a flexible style system centered on the StyleType enum, which maps predefined palettes or user-defined TOML configurations to the application's visual elements. Whether you want to match your system theme or create a unique look for network monitoring, you can customize Sniffnet's appearance without modifying source code. This guide walks you through the architecture, file formats, and implementation details found in the GyulyVGC/sniffnet repository.

How Sniffnet's Theme System Works

The StyleType Enum and Palette Architecture

The theme engine revolves around the StyleType enum defined in src/gui/styles/types/style_type.rs, which includes variants for built-in themes like A11yDark and DraculaLight, plus a Custom(CustomPalette) variant for user-defined schemes. Each theme maps to a Palette struct containing six core color fields that drive the entire UI appearance according to the implementation in src/gui/styles/types/palette.rs. The system separates declaration from rendering: color definitions live in TOML files, while runtime representation uses the CustomPalette wrapper found in src/gui/styles/types/custom_palette.rs.

When loaded, the palette automatically generates a PaletteExtension through Palette::generate_palette_extension, which computes derived UI parameters including button colors, night-mode detection, and alpha transparency values. This architecture ensures that custom themes automatically adapt UI components without requiring manual adjustments to every widget style.

Creating Your Custom Theme File

Required TOML Structure

Custom themes require a TOML file with exactly six hexadecimal color values. The Palette::from_file function in src/gui/styles/types/palette.rs validates these entries at load time, accepting both #RRGGBB and #RRGGBBAA formats.

Create a file (e.g., my_theme.toml) with these required keys:

  • primary: Background and main UI elements
  • secondary: Incoming connections and headers
  • outgoing: Outgoing connections visualization
  • starred: Favorite items and star indicators
  • text_headers: Header and footer text colors
  • text_body: Body text and button labels

Example Custom Theme

Reference the built-in themes in resources/themes/ (such as catppuccin.toml) for complete implementations. A minimal custom theme looks like this:

primary       = "#1e1e2e"
secondary     = "#f5e0dc"
outgoing      = "#f5c2e7"
starred       = "#f9e2af"
text_headers  = "#cba6f7"
text_body     = "#d9e0ee"

Save this file anywhere on your filesystem; Sniffnet reads the absolute path stored in the configuration to locate your theme.

Loading and Applying Custom Themes

Via the Appearance Settings Page

The settings interface in src/gui/pages/settings_style_page.rs provides a "Custom style" button that triggers a file dialog. When selected, the path generates a Message::LoadStyle(path) event that updates Settings.style_path and wraps the loaded palette in StyleType::Custom.

The UI previews your theme immediately using:

let custom_palette = Palette::from_file(custom_path);
if let Some(palette) = custom_palette {
    // Preview the freshly-loaded file
    palette
}

The is_custom_toml_style_set flag tracks whether a custom theme is active, allowing the application to display the current palette or the preview based on selection state.

Via Configuration File

For automatic loading at startup, edit ~/.config/sniffnet/settings.toml and set the absolute path:

style_path = "/absolute/path/to/my_theme.toml"

During initialization in src/gui/sniffer.rs, the application executes:

self.conf.settings.style_path.clone_from(&path);
self.conf.settings.style = StyleType::Custom(CustomPalette::from_palette(palette));

This applies your custom theme before the main window renders, eliminating the need to use the GUI file picker on every launch.

Validating and Debugging Theme Changes

After loading, verify the active palette at runtime by checking the StyleType variant:

if let StyleType::Custom(custom) = sniffer.conf.settings.style {
    println!("Custom palette loaded: {:?}", custom.palette);
}

The PaletteExtension computed by CustomPalette::from_palette automatically adjusts button colors and night-mode flags based on your primary color brightness. If colors fail to load, check that all six keys are present in your TOML file and that hex values are properly formatted, as Palette::from_file returns None for invalid inputs.

Summary

  • Sniffnet uses a StyleType enum in src/gui/styles/types/style_type.rs to manage both built-in and custom themes through the Custom variant.
  • Create TOML files with six required color keys (primary, secondary, outgoing, starred, text_headers, text_body) and valid hex values.
  • Apply themes via GUI using the Appearance settings page, or set style_path in ~/.config/sniffnet/settings.toml for automatic startup loading.
  • Runtime validation occurs through Palette::from_file, which returns None for malformed files and automatically generates derived UI parameters via PaletteExtension.

Frequently Asked Questions

What file format does Sniffnet use for custom themes?

Sniffnet uses TOML files with six specific color keys. According to the implementation in src/gui/styles/types/palette.rs, the file must define primary, secondary, outgoing, starred, text_headers, and text_body using hexadecimal color values. The loader accepts standard #RRGGBB or #RRGGBBAA formats and validates each entry during the Palette::from_file call.

Where does Sniffnet store the active custom theme path?

The active theme path persists in the Settings struct's style_path field, defined in src/gui/types/settings.rs. When you select a custom theme through the GUI, the application updates this field and saves it to ~/.config/sniffnet/settings.toml. The Sniffer implementation in src/gui/sniffer.rs reads this path at startup to initialize the custom palette before rendering the interface.

Can I switch between built-in and custom themes without restarting Sniffnet?

Yes. The Appearance settings page in src/gui/pages/settings_style_page.rs handles live theme switching. When you load a custom TOML file, the application immediately dispatches Message::LoadStyle to update the configuration and rebuilds the UI with the new palette. You can switch back to built-in variants like A11yDark or DraculaLight through the same interface without closing the application.

How does Sniffnet validate my custom theme colors?

Validation occurs in Palette::from_file within src/gui/styles/types/palette.rs. The function attempts to parse each TOML entry as a valid hex color and returns None if any key is missing or malformed. Once loaded, CustomPalette::from_palette generates a PaletteExtension that automatically calculates derived properties like button colors and night-mode detection, ensuring your theme remains functional even if you only specify the six base colors.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →