Senal-D-A-Gunaratna/matugen.nvim

github github
colorschemecolorscheme-creation
stars 31
issues 0
subscribers 0
forks 2
CREATED

UPDATED


matugen.nvim

A Material You colorscheme bridge for Neovim. Built as a drop-in solution that maps matugen's colors straight to Neovim highlight groups through a semantic palette, with minimal setup required


https://github.com/user-attachments/assets/5b9e40a9-a8e1-4b9b-badd-f4b667d55f5e


Requirements

Setup

1. Copy the template

Copy nvim-colors.json to your matugen templates folder

2. Add it to config.toml

[templates.neovim]
input_path = "~/.config/matugen/templates/nvim-colors.json"
output_path = "~/.cache/matugen/nvim-colors.json"
post_hook = "pkill -SIGUSR1 nvim"

3. Install with lazy.nvim

{
  "Senal-D-A-Gunaratna/matugen.nvim",
  lazy = false,
  priority = 1000,
  opts = {
    palette_path = "~/.cache/matugen/nvim-colors.json",
    -- load_theme = false,
    -- custom_templates = "~/.config/nvim/matugen-templates",
  },
},

By default, the plugin automatically loads the generated palette and sets itself as your active colorscheme — no extra vim.cmd.colorscheme(...) call needed

Set load_theme = false if you'd rather manage the colorscheme yourself and don't want the plugin to apply it automatically

4. Terminal opacity (optional)

Terminal opacity can be achieved on most other DEs/WMs too (window rules, compositor configs, etc) — this section covers the Hyprland-specific approach

For transparency in Neovim that doesn't affect your regular terminal, use hyprfade.nvim. Unlike a static Hyprland window rule, it toggles opacity only while Neovim is focused — and it works even when Neovim's window title doesn't update in time for a class/title match (e.g. launching from Yazi)

Or set a static rule yourself:

hl.window_rule({
  match = { class = "kitty", title = "nvim" },
  opacity = "0.7",
})

Live reload

The post_hook in config.toml reloads Neovim automatically on every matugen run. To trigger it manually:

pkill -SIGUSR1 nvim

or, from inside Neovim:

:MatugenReload

Fallbacks

The plugin always ends up with a usable theme, and tells you when it isn't rendering the palette you expected:

  • Palette file missing or unparseable — the built-in dark theme is used and you get a warning. Recovery is per color key: keys the palette provides are used as-is, only missing or non-hex ones take their color from the fallback, and the warning names them
  • A file in custom_templates fails to load — the built-in template of the same name is used and the whole theme renders from the fallback colors, because a customization you believe is active but isn't is worse than an obvious one. Fix the file and run :MatugenReload

:checkhealth matugen lists any failures and which palette is in use. See Creating Custom Templates for the full rules

Health check

:checkhealth matugen

Verifies your config, template parsing, active templates, and load status

Supported plugins

Built-in templates live in lua/matugen/templates:

Customization

Custom templates directory — set custom_templates to a directory of your own templates, layered on top of the built-in ones. Built-in templates are applied first and yours last, so a custom template only needs to set the highlight groups you want to change:

opts = {
  custom_templates = "~/.config/nvim/matugen-templates",
  palette_path = "~/.cache/matugen/nvim-colors.json",
}

Nothing is copied out of the plugin, so updates never overwrite your work. If the directory doesn't exist yet, it's created empty and you're notified. A file that matches a built-in template's name replaces it; the same name with a blank file disables it. A file that fails to load is reported as an error and ignored, so the built-in stays rather than silently losing its highlights — fix it and run :MatugenReload. Only the top level of the directory is scanned. Add a template by dropping a Lua file into that directory, then run :MatugenReload.

Tweaking colors doesn't require touching any plugin code. Edit your nvim-colors.json template directly — remap a semantic key to a different matugen color role (e.g. point cursor_block at tertiary instead of primary), adjust the alpha suffix on selection_bg/word_highlight, or swap in a hardcoded hex value. Run matugen again (or :MatugenReload) to see the change

Every highlight group comes from one semantic palette in lua/matugen/palette.lua, so adding a new plugin or UI component stays consistent

Cursor theming is done by shape, not mode:

Shape Cursors Palette key
Block Cursor, smCursor, TermCursor cursor_block
Beam iCursor, lCursor cursor_beam
Underline rCursor, oCursor cursor_underline

Block cursor colors work in any terminal. Per-shape colors need a terminal that honors cursor coloring (kitty, wezterm, foot); terminals that don't (GNOME Terminal, Alacritty) just get a plain cursor

Foreground pairing follows contrast needs: block cursors use high-contrast on_primary, while beam/underline cursors use the softer on_surface. Unfocused terminal windows get the dimmed TermCursorNC, matching the rest of the *NC groups

See Creating Custom Templates to extend it

Contributing

PRs welcome — new plugin support, bug fixes, anything that makes this better

Support

If you find this useful, consider giving it a ⭐ — it helps others discover the project

License

MIT