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

> Discover how Omarchy's theme template system renders .tpl files into application configs. Learn about placeholder substitution, user vs. built-in templates, and dynamic configuration.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: internals
- Published: 2026-08-30

---

**Omarchy's theme template system renders `.tpl` files into application configs by substituting `{{ key }}` placeholders with values from a theme's [`colors.toml`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L32)】.

## 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`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L95)】.

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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L30)】.

## 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`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L60)】.

## 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`:

```lua
-- 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`](https://github.com/omacom/omarchy/blob/main/themes/catppuccin/colors.toml):

```toml
accent = "#f5c2e7"
surface0 = "#313244"

```

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

```lua
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`:

```conf
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`](https://github.com/omacom/omarchy/blob/main/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:

```bash

# 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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L32)】.
- **Double-brace syntax** (`{{ key }}`) enables referencing any value defined in the theme's [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) file【[docs/theming.md#L95](https://github.com/omacom/omarchy/blob/quattro/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L30)】.
- **Testing infrastructure** via [`test/shell.d/theme-staging-test.sh`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L32)】.

### 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`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L30)】.

### 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`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/docs/theming.md#L60)】.