adamws/kle-ng

Community Color Themes — Submit Yours!

Open

#62 opened on Apr 11, 2026

 (2 comments) (0 reactions) (0 assignees)TypeScript (12 forks)auto 404
help wanted

Repository metrics

Stars
 (220 stars)
PR merge metrics
 (PR metrics pending)

Description

I recently added a color theme tool to kle-ng, and I'd love to grow a collection of community-contributed themes that ship with the app. If you've put together a theme you're happy with, share it here!


How themes work

A theme is a JSON object with a cascade of rules. Rules are evaluated in order — the last matching rule wins. The first rule typically has no matcher and acts as the default/fallback for all keys.

Full schema

interface Theme {
  name: string               // display name
  backgroundColor?: string   // keyboard background (hex)
  rules: ThemeRule[]
}

interface ThemeRule {
  name: string               // rule label shown in the UI
  matchers?: string          // matcher expression (omit = match all keys)
  colors: {
    color?: string           // keycap background (hex)
    defaultTextColor?: string  // default label color (hex)
    textColors?: {           // per-position overrides (positions 0–11)
      [position: number]: string
    }
  }
}

Matcher expression syntax

Matchers are small filter expressions that select which keys a rule applies to.

Concept Syntax Example
Numeric property width, height, x, y, rotation width >= 1.5
Comparison operators > >= < <= == != height == 2
Boolean flags decal, ghost, stepped, nub decal
Label equality label == "text" label == "Esc"
Label substring label contains "text" label contains "Shift"
Label regex label matches "pattern" label matches "^F\d+$"
Label by position label[n] operator "text" label[0] == "A"
Logical AND expr and expr width > 1 and not decal
Logical OR expr or expr ghost or stepped
Logical NOT not expr not (ghost or decal)
Grouping ( expr ) (width >= 6 or height >= 6)

Rule cascade: rules are listed lowest-priority first. The last rule whose matcher passes for a key wins. Put your catch-all default rule first; put narrow overrides last.


Example — Gruvbox (dark)

{
  "name": "Gruvbox (dark)",
  "backgroundColor": "#a89984",
  "rules": [
    {
      "name": "Default",
      "colors": { "color": "#2b2928", "defaultTextColor": "#ebdbb2" }
    },
    {
      "name": "Modifiers",
      "matchers": "width > 1 or height > 1",
      "colors": { "color": "#222222", "defaultTextColor": "#ebdbb2" }
    },
    {
      "name": "Space",
      "matchers": "width >= 4",
      "colors": { "color": "#2b2928", "defaultTextColor": "#ebdbb2" }
    },
    {
      "name": "Aqua Text",
      "matchers": "label matches \"([Ee]nter|[Cc]aps.*)\"",
      "colors": { "defaultTextColor": "#8ec07c" }
    },
    {
      "name": "Red Text",
      "matchers": "label matches \"([Ee]sc.*|[Ss]hift)\"",
      "colors": { "defaultTextColor": "#fb4934" }
    },
    {
      "name": "Purple Text",
      "matchers": "label matches \"([Tt]ab.*|[Bb]ack.*)\"",
      "colors": { "defaultTextColor": "#d3869b" }
    },
    {
      "name": "Green Text",
      "matchers": "label matches \"([Cc]trl|[Cc]ontrol|[Aa]lt.*|[Ww]in.*|[Mm]enu|[Ff]n)\"",
      "colors": { "defaultTextColor": "#b8bb26" }
    },
    {
      "name": "Decal Text",
      "matchers": "decal",
      "colors": { "defaultTextColor": "#000000" }
    }
  ]
}

Submission rules

  1. One theme per comment. Post each theme in its own comment so they stay easy to find and review.

  2. Valid JSON only. Your theme must be a single well-formed JSON object matching the schema above. Wrap it in a fenced code block tagged ```json.

  3. Required fields. Your theme must include:

    • name — a unique, descriptive display name
    • At least one rule with no matchers field (the default/fallback rule)
    • At least one color or defaultTextColor set in every rule's colors object
  4. Name your rules. Every rule needs a non-empty name string. Short labels like "Default", "Modifiers", "Accents" are fine.

  5. Hex colors only. All color values must be 6-digit hex strings (e.g. "#aabbcc"). No rgb(), no shorthand (#abc), no named colors.

  6. Credit your inspiration. If your theme is based on a popular color scheme (Dracula, Nord, Solarized, etc.), mention it in your comment. If it is your original work, say so.

  7. Include a screenshot. Attach a screenshot of the theme applied to ANSI 104 preset layout. This makes it much faster to review and decide whether to include the theme. Use Export -> Download PNG option. For example:

  1. Keep it general. Themes will be applied to arbitrary layouts, so matchers should target structural properties (width, height, flags) or common label patterns.

How submissions get included

Themes submitted here will be reviewed periodically. Themes that are visually distinct, well-structured, and have clear community interest will be added to the built-in theme list. I may make small adjustments (rule names, minor color tweaks) before merging and will credit contributors in the commit message.

There is no guarantee that every theme will be accepted — quality and variety are the main criteria.


I'm looking forward to seeing what you come up with!

Contributor guide