# How the Hyprland Theme Template Generates Configuration in Basecamp/Omarchy

> Learn how the Hyprland theme template in Basecamp/Omarchy generates its configuration. Discover its Quickshell rendering pipeline and colors.toml integration.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-20

---

**The Hyprland theme template in Basecamp/Omarchy uses a Quickshell-based rendering pipeline that reads theme variables from [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml), merges user overrides, and outputs a concrete [`hyprland.lua`](https://github.com/basecamp/omarchy/blob/main/hyprland.lua) configuration file when you run `omarchy-refresh-config`.**

Omarchy's theming system treats Hyprland configuration as a **templated artifact** rather than static configuration. This approach, implemented in the `basecamp/omarchy` repository, lets you swap entire color palettes and layout behaviors by changing your active theme—without manually editing Hyprland rules. The core mechanism lives in `default/themed/hyprland.lua.tpl`, a Lua template peppered with double‑curly‑brace placeholders like `{{ colors.accent }}` and `{{ decoration.rounding }}`.

## The Five-Step Hyprland Config Generation Pipeline

### 1. Theme Selection via [`config/theme.toml`](https://github.com/basecamp/omarchy/blob/main/config/theme.toml)

Omarchy determines which theme to apply by reading your active theme from [`config/theme.toml`](https://github.com/basecamp/omarchy/blob/main/config/theme.toml). This file points to a subdirectory under `themes/*/`, where the actual color definitions reside. When you switch themes, this pointer changes—and subsequent refreshes pull from a different [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml).

### 2. Loading Theme Variables from [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml)

Every theme directory contains a [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) file that defines palette entries: `accent`, `background`, `foreground`, `alert`, and more. These become available to the template as `colors.*` variables. The structure is flat and predictable, making it straightforward to author new themes without touching template logic.

### 3. Collecting Runtime and Toggle Values

Beyond static colors, Omarchy injects **dynamic state** into the rendering context:

- **Layout values**: Current gap sizes (`gaps.out`, `gaps.in`), border widths
- **Decoration state**: Corner `rounding`, `blur` settings, shadow toggles
- **Hyprland feature flags**: `misc.disable_autoreload`, `misc.debug`, and other runtime toggles

These values populate a Lua table that the Quickshell engine references during rendering. The table structure mirrors the nested configuration in Hyprland itself, so template authors can write intuitive placeholders like `{{ decoration.rounding }}`.

### 4. Template Rendering via Quickshell

The `omarchy-refresh-config hypr/hyprland.lua` command drives the actual generation. Internally, this helper:

1. Loads the selected theme's [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml)
2. Merges any user-defined overrides
3. Assembles the complete variable table (colors + runtime values)
4. Feeds the template file into the **Quickshell templating engine**

Quickshell processes standard `{{ variable }}` substitutions and handles conditional blocks with `{% if … %}` syntax. This lets the template conditionally emit configuration lines based on feature flags—omit blur settings when disabled, include debug logging only when explicitly toggled, and so on.

### 5. Writing the Final Configuration

The rendered output lands at `~/.config/hypr/hyprland.lua`, replacing any previous generated version. Omarchy preserves user customizations through a **separate override file**: [`hyprland.local.lua`](https://github.com/basecamp/omarchy/blob/main/hyprland.local.lua). This file is not templated—Omarchy leaves it untouched, letting you maintain persistent manual adjustments alongside the auto-generated core configuration.

## Key Files in the Hyprland Template System

| File | Purpose |
|------|---------|
| `default/themed/hyprland.lua.tpl` | Master template with placeholders for colors, gaps, decorations, and toggles |
| `bin/omarchy-refresh-config` | CLI helper that orchestrates theme loading, variable merging, and Quickshell rendering |
| `themes/*/colors.toml` | Theme-specific color palettes referenced by the template |
| [`docs/theming.md`](https://github.com/basecamp/omarchy/blob/main/docs/theming.md) | Comprehensive documentation of Omarchy's theming architecture |
| [`migrations/1781485962.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1781485962.sh) | Migration script that relocates legacy Hyprland overrides before template rendering |

## Practical Usage: Refreshing Your Hyprland Config

Generate or update your Hyprland configuration from the current theme:

```bash

# Render hyprland.lua from template using active theme values

omarchy-refresh-config hypr/hyprland.lua

```

After running this, reload Hyprland (typically `hyprctl reload`) to pick up the new configuration.

## What the Template Looks Like: `hyprland.lua.tpl` Excerpt

```lua
-- Omarchy-generated Hyprland config – do not edit manually
{{# Theme-wide settings #}}

misc = {
  disable_autoreload = {{ misc.disable_autoreload }},
  debug = {{ misc.debug }},
},

{{# Color palette #}}

$foreground = "{{ colors.foreground }}";
$background = "{{ colors.background }}";
$accent     = "{{ colors.accent }}";

{{# Gap and decoration values #}}

gaps_out = {{ gaps.out }};

decoration = {
  rounding = {{ decoration.rounding }},
  blur = {{ decoration.blur }},
};

```

When `omarchy-refresh-config` executes, these placeholders resolve to concrete values—for example, `disable_autoreload = false`, `gaps_out = 5`, `rounding = 12`—producing a valid, ready-to-use Hyprland configuration.

## Handling Configuration Migrations

The [`migrations/1781485962.sh`](https://github.com/basecamp/omarchy/blob/main/migrations/1781485962.sh) script ensures seamless upgrades. If you've previously maintained Hyprland overrides in legacy locations, this migration runs before template rendering to relocate them into the standardized [`hyprland.local.lua`](https://github.com/basecamp/omarchy/blob/main/hyprland.local.lua) path. This prevents loss of custom work and maintains compatibility with Omarchy's generated-output workflow.

## Summary

- **Template-driven approach**: Hyprland config lives in `hyprland.lua.tpl` with `{{ placeholder }}` syntax for dynamic values
- **Quickshell rendering**: `omarchy-refresh-config` processes templates through the Quickshell engine, substituting variables from theme and runtime sources
- **User override preservation**: Manual customizations survive in [`hyprland.local.lua`](https://github.com/basecamp/omarchy/blob/main/hyprland.local.lua), kept separate from generated output
- **Migration safety**: Legacy overrides are automatically relocated before new templates render

## Frequently Asked Questions

### How do I change the Hyprland accent color without editing template files?

Change your active theme in [`config/theme.toml`](https://github.com/basecamp/omarchy/blob/main/config/theme.toml) to point at a different `themes/*/colors.toml`, then run `omarchy-refresh-config hypr/hyprland.lua`. The new `accent` value from that theme's colors will populate the generated configuration automatically.

### What happens to my manual Hyprland edits when I refresh?

Direct edits to `~/.config/hypr/hyprland.lua` are overwritten. To preserve customizations, place them in `~/.config/hypr/hyprland.local.lua`—Omarchy leaves this file untouched and typically sources it from the generated configuration.

### Can I add new template variables for my own Hyprland settings?

Yes. Define new values in your theme's data source or extend the variable collection logic in `bin/omarchy-refresh-config`, then reference them in `hyprland.lua.tpl` using `{{ your.variable }}` syntax. Quickshell will substitute them during the next refresh.

### Does the template support conditional configuration blocks?

Yes. The Quickshell engine supports `{% if condition %}` … `{% endif %}` blocks alongside `{{ variable }}` substitutions. This lets you emit or suppress configuration sections based on boolean flags in the variable table.