Themery is a starter template for building and publishing your own Neovim colorscheme plugin. It comes with an example theme ("themery") demonstrating:
- Centralized palette with semantic slots
- Treesitter, UI, and popular plugin highlight groups
- Lualine, Snacks.nvim, Noice.nvim, Neo-tree, todo-comments integrations
Fork it, rename it, swap the palette values, and you have a new theme.
- Opinionated yet minimal structure (one palette → many modules)
- Semantic color slots (change intent, not 200 hex codes)
- Clearly commented palette explaining usage of each key
- Modular apply() functions—remove what you don't need
- Ready for local development via
lazy.nvim
- Fork this repo (or use "Use this template")
- Rename occurrences of
themery
to your theme name (e.g.moonlightedge
) - Rename directory
lua/themery/
→lua/moonlightedge/
- Edit
lua/moonlightedge/colors.lua
palette values - Load locally with a path plugin spec in your Neovim config
- Tweak highlight logic if desired (Treesitter, plugins, etc.)
- Add screenshots & publish to GitHub (name your repo moonlightedge.nvim) + a tag
Assume your new theme name is moonlightedge
(replace with yours):
Rename the main module directory:
mv lua/themery lua/moonlightedge
Search & replace the name inside the repo.
Update the README accordingly.
Open lua/<yourtheme>/colors.lua
. Each palette key has a comment describing intent. Adjust hex values but try to preserve roles:
Slot | Role Summary | Examples of Usage |
---|---|---|
bg0 | Deepest backdrop | (rare) overlays, max contrast bases |
bg1 | Main editor background | Normal text background |
bg2 | Secondary surface | CursorLine, popup, selection, subtle panels |
bg3 | Elevated/UI surface | StatusLine, TabLineSel, titles |
fg0 | Max contrast text | Headings, markup headings |
fg1 | Primary text | Normal fg |
fg2 | Secondary text | Comments alt, dimmer text |
fg3 | Tertiary/meta | LineNr, subtle info |
selbg | Visual selection bg | Visual, matches |
selfg | Foreground inside selection | Visual text |
comment | Comment text | @comment, Comment |
color1 | Error / strong semantic | Error, statements, removed lines |
color2 | Primary accent / success | Mode badges, added lines |
color3 | Attention / highlight | TODO, search, matches |
color4 | Constants / modified | Constants, modified, neutral warm accent |
color5 | Types / secondary | @type, replace mode |
color6 | Keywords / structural | Keywords, directives, visual mode accent |
uic1 | Structural UI / borders | Win separators, borders, guides |
Tips:
- Start with backgrounds & primary foreground first (bg1, fg1)
- Ensure WCAG-ish contrast for
fg1
onbg1
(~4.5:1+ preferred) - Keep semantic intent coherent if you later recolor accents
- You can repurpose slots, but document it so users know your intent
Clone your fork somewhere, e.g. ~/Developer/moonlightedge
then in your Neovim lazy.nvim
setup:
{ dir = '~/Developer/moonlightedge', name = 'moonlightedge', priority = 1000, lazy = false, config = function()
vim.cmd.colorscheme 'moonlightedge'
end }
Reload Neovim or run :Lazy sync
.
During iteration:
- Edit palette →
:colorscheme moonlightedge
to reapply - Inspect highlights:
:hi SomeGroup
or:Telescope highlights
Modules under lua/<theme>/
:
colors.lua
— palette + core highlight groupstreesitter.lua
— semantic treesitter groups (@
prefixed)lualine.lua
— lualine theme table (returned, not applied directly)noice.lua
,snacks.lua
,neotree.lua
,todo-comments.lua
— plugin integrations
Remove any integrations you don’t use. Safe: delete file + remove require("<theme>.<module>").apply()
lines in colors.lua
.
Add new ones by creating a file and following the same pattern:
local colors = require('<theme>.colors').palette
local M = {}
function M.apply()
local p = colors
vim.api.nvim_set_hl(0, 'NewPluginGroup', { fg = p.color2, bg = p.bg2 })
end
return M
Call it from colors.lua
inside M.apply()
.
When you’re ready:
- Pick a final name (avoid collisions on GitHub & existing themes)
- Update README title, description, examples
- Remove unused integrations (trim bloat for users)
- Add screenshots (see below)
- Run a quick highlight audit (
:Telescope highlights
or:Inspect
with Treesitter) - Tag a release:
git tag -a v0.1.0 -m "Initial release" && git push --tags
After publishing to GitHub at user/moonlightedge.nvim
:
return {
{ "user/moonlightedge.nvim", lazy = false, priority = 1000 },
{
"LazyVim/LazyVim",
opts = {
colorscheme = "moonlightedge",
},
},
}
If you need more slots, prefer semantic names over vague ones:
-- Add near the bottom
accent_info = '#3A9AD9' -- informational messages
accent_hint = '#7FB069' -- subtle suggestions
Document them with comments.
If you improve structure (new semantic slot ideas, helper utilities) feel free to open a PR here.
Original example theme name: themery
(retained for reference). Replace everywhere when creating your own.
Happy theming! 🎨
MIT – use freely in your own theme projects.