How Omarchy's Theme Template System Works: Dynamic Configuration Rendering

Omarchy's theme template system renders .tpl files into application configs by substituting {{ key }} placeholders with values from a theme's colors.toml, processing user templates in ~/.config/omarchy/themed/ before built-in ones in default/themed/.

Omarchy is a declarative Linux desktop configuration framework that manages dotfiles and application settings through a centralized theming engine. At the heart of this system lies a lightweight yet powerful template renderer that transforms static template files into dynamic configuration files based on the active color scheme. This article explains how Omarchy's theme template system works by examining the rendering pipeline, file precedence rules, and the specific implementation details found in the source code.

Template Files and Storage Locations

The template system recognizes two distinct locations for .tpl files. Built-in templates reside in default/themed/*.tpl within the repository, providing sensible defaults for applications like Hyprland, Kitty, and Alacritty. User templates live in ~/.config/omarchy/themed/*.tpl, allowing for personal customization without modifying core system files.

During the rendering process, the system always scans the user directory first, then falls back to the built-in location. If a user template generates an output file with the same name as a built-in template, the built-in version is automatically skipped. This ensures that user customizations take precedence over default configurations【docs/theming.md#L32-L38】.

Template Syntax and Color Substitution

Templates are plain text files that use double-brace syntax to reference color values. Any key defined in the active theme's colors.toml can be inserted using {{ key }}. For example, referencing the accent color requires simply writing {{ accent }} within the template body【docs/theming.md#L95-L97】.

This syntax is consistent across all template types, whether generating Lua configuration for Hyprland or terminal color schemes. The renderer performs a literal string substitution, replacing each placeholder with the corresponding hexadecimal color value or string from the theme's palette.

The Rendering Pipeline

The omarchy-theme-set-templates command (located in bin/omarchy-theme-set-templates) orchestrates the entire rendering workflow. The process follows four distinct stages:

  1. Theme Loading: The command reads themes/<name>/colors.toml to load the active color palette into memory.
  2. Template Discovery: It recursively collects all *.tpl files from ~/.config/omarchy/themed/ (if they exist) and subsequently from default/themed/.
  3. Placeholder Substitution: Each template undergoes processing where every occurrence of {{ key }} is replaced with the value from the loaded color scheme.
  4. Atomic Writing: Rendered content is written to the appropriate target configuration files (e.g., ~/.config/hypr/hyprland.conf).

The system includes safeguards against data loss by refusing to overwrite existing files that were not originally generated from templates, protecting hand-crafted configurations from accidental destruction【docs/theming.md#L30-L33】.

Color-Aware Denylist and Testing

Omarchy maintains strict separation between configuration "code" and color-only definitions through the INSTALLED_THEME_DENIED array defined in bin/omarchy-theme-set. This denylist tracks templates that emit only color information (such as terminal color schemes) versus those containing structural configuration code.

When contributing new templates to the repository, developers must classify each template appropriately and update the denylist accordingly. The validation logic resides in test/shell.d/theme-staging-test.sh, which executes focused tests to confirm that templates render correctly and that all colour-only templates are properly accounted for in the denylist【docs/theming.md#L60-L63】.

Practical Implementation Examples

The following examples demonstrate the complete workflow from template definition to rendered output.

Example 1: Creating a Hyprland Template

Create a built-in template at default/themed/hyprland.lua.tpl:

-- Hyprland decoration configuration
decoration {
    rounding = 10
    active_opacity = 0.95
    inactive_opacity = 0.85
    
    blur {
        enabled = true
        passes = 3
        new_optimizations = true
    }
    
    col.active_border = {{ accent }}
    col.inactive_border = {{ surface0 }}
}

Define the corresponding colors in themes/catppuccin/colors.toml:

accent = "#f5c2e7"
surface0 = "#313244"

After running omarchy-theme-set-templates, the generated ~/.config/hypr/hyprland.lua contains:

col.active_border = #f5c2e7
col.inactive_border = #313244

Example 2: User Override for Kitty Terminal

To override the default Kitty configuration without modifying system files, create ~/.config/omarchy/themed/kitty.conf.tpl:

font_family      {{ font_family }}
font_size        {{ font_size }}
background       {{ background }}
foreground       {{ foreground }}
cursor           {{ accent }}

Place the custom values in your user configuration's colors.toml or rely on the active theme. Executing the render command applies these changes immediately while preserving the original template for future theme switches.

Example 3: Executing the Render Command

To manually trigger template rendering after adding or modifying files:


# Render all templates for the currently selected theme

omarchy-theme-set-templates

# Verify specific outputs were generated

ls -la ~/.config/hypr/hyprland.conf
ls -la ~/.config/kitty/kitty.conf

Summary

  • Omarchy's theme template system uses .tpl files in default/themed/ and ~/.config/omarchy/themed/ to generate application configurations dynamically.
  • User templates take precedence over built-in ones; if both exist for the same output file, only the user version is processed【docs/theming.md#L32-L38】.
  • Double-brace syntax ({{ key }}) enables referencing any value defined in the theme's colors.toml file【docs/theming.md#L95】.
  • The omarchy-theme-set-templates command orchestrates loading, substitution, and atomic writing while protecting existing non-template files【docs/theming.md#L30】.
  • Testing infrastructure via test/shell.d/theme-staging-test.sh validates template correctness and maintains the color/code separation through the INSTALLED_THEME_DENIED denylist【docs/theming.md#L60】.

Frequently Asked Questions

Where should I place custom templates to override Omarchy's defaults?

Place your custom .tpl files in ~/.config/omarchy/themed/. The omarchy-theme-set-templates command processes this directory before falling back to the built-in default/themed/ location, ensuring your versions take precedence without modifying the core repository files【docs/theming.md#L32-L38】.

What syntax do I use to reference color values in a template?

Use double curly braces surrounding the key name exactly as it appears in the theme's colors.toml file, such as {{ background }} or {{ accent }}. The renderer substitutes these placeholders with the actual color values during the templating process【docs/theming.md#L95】.

How does Omarchy prevent overwriting my hand-written configuration files?

The rendering system maintains a registry of files it generates from templates. When omarchy-theme-set-templates runs, it checks whether an existing target file was previously created by the template system. If a file exists but was not generated from a template, the command skips that file to prevent destroying manual edits【docs/theming.md#L30-L33】.

How can I verify that my new template works correctly before committing?

Run the focused test suite located at test/shell.d/theme-staging-test.sh. This script validates that templates render without errors and checks that colour-only templates are properly listed in the INSTALLED_THEME_DENIED array. Execute the test after adding your template to ensure it integrates correctly with the denylist and produces valid output files【docs/theming.md#L60-L63】.

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 →