Open-source project
AlexvZyl/nordic.nvim avatar
AlexvZyl/nordic.nvim

Nordic: a warmer, darker Nord for Neovim with a Lua palette layer

🌒 Nord for Neovim, but warmer and darker. Supports a variety of plugins and other platforms.

1,073 stars71 forksLuaMIT

At a glance

What is it?
nordic.nvim is a Neovim colorscheme that starts from Nord, darkens it and leans on the Aurora palette, with a runtime setup layer that lets you override palette entries and highlights in Lua. It suits users who find stock Nord too cold, and it suits them less if they want a theme with no configuration surface at all.
Who is it for?
Adopt nordic.nvim if you already use Nord and want a darker, warmer variant that you can still adjust at runtime through on_palette, after_palette and on_highlight, because the whole point of the project is that layer rather than a fixed set of highlights. Do not adopt it if you want a theme that ships no Lua configuration surface, or if you need the plugin and platform integrations verified, since the author states plainly that not every listed integration is one they use.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 173 days ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Nordic changes about Nord

Nordic is a Neovim colorscheme based on Nord, and the project describes the difference in one line: use Nord, but add some darker colors and use the Aurora palette more prominently than Nord themes usually do. The stated result is a colorscheme that is soft on the eyes.

That is a design position rather than a feature list. Nord is a polar palette, blue and white with a cold cast, and its two accent families are frost and aurora. Nordic keeps the structure but pushes the background darker and gives aurora a larger share of the assignments, which is why the palette file in the repository defines more than the base Nord entries. For someone who likes Nord's restraint but finds it cold on a long evening of reading code, that is the entire pitch, and there is no configuration needed to get it.

The project is small and single purpose. It is Lua, it is a colorscheme, and the repository top level holds lua/, colors/, platforms/, doc/ and assets/ directories along with a platforms.sh script. Licence is MIT. The last push to the repository was on 2026-05-03, and the tagged releases are 0.2.0 from 2026-02-08 and 0.1.0 from 2024-09-24.

The palette is assembled in Lua at load time

Most colorschemes ship a static vim colors file. Nordic instead keeps its palette in Lua and builds it when the scheme loads, which is what makes the configuration layer possible.

The base palette lives in lua/nordic/colors/nordic.lua, and extra colors together with their use cases are generated in lua/nordic/colors/init.lua. A small utility module, nordic.utils, provides a blend function that mixes a foreground color into a background by a given ratio, and the documentation uses it to show how a caller can derive a new color rather than hardcoding a hex value.

Plugin integration lives in lua/nordic/groups/integrations, one file per supported plugin. The theme therefore does not monkey patch third party code. It defines highlight groups for those plugins and the plugin picks them up through the normal Neovim highlight mechanism, which is the conventional approach and the reason a colorscheme can support a plugin without depending on it.

The palette is also reachable from user config, which is the hook the README uses to explain the ordering requirement described later in this article.

Installing Nordic with lazy.nvim, packer.nvim or vim-plug

Nordic is a normal Neovim plugin, so it is installed with whichever plugin manager you already use. The README gives the block for each of three managers.

With lazy.nvim, the plugin is declared with a config function that loads the colorscheme, and the priority is set to 1000 so the scheme is in place before other plugins paint their own highlights:

lua
{
    'AlexvZyl/nordic.nvim',
    lazy = false,
    priority = 1000,
    config = function()
        require('nordic').load()
    end
}

With packer.nvim the declaration is a single line, and with vim-plug it is a Plug line pinned to the main branch:

vim
Plug 'AlexvZyl/nordic.nvim', { 'branch': 'main' }

After the plugin is loaded you switch to the scheme the usual way, either with the Vim command or from Lua:

vim
colorscheme nordic
lua
vim.cmd.colorscheme('nordic')
-- or
require('nordic').load()

For lualine, the theme name goes into the options table:

lua
require('lualine').setup({
    options = {
        theme = 'nordic'
    }
})

The README does not give a separate install step for the status line, so this is a configuration addition rather than another download.

Three callbacks that expose the palette and the highlights

Nordic uses its default values unless setup is called, and setup takes three callbacks plus a set of feature flags. The callbacks are the interesting part because they define the order in which the theme is assembled.

on_palette runs first and can override colors in the base palette. after_palette runs second and can override colors in the extended palette, and it receives the result of the first callback, which is why the example for it calls nordic.utils and derives a color from the palette. on_highlight runs last and receives the finished highlight table, so it can change individual highlight groups, such as rewriting the colors of TelescopePromptTitle, or stripping italic from every highlight group at once.

The example given for on_palette is minimal, reassigning palette.black0 and pointing palette.green.base at palette.cyan.base:

lua
require('nordic').setup({
    on_palette = function(palette)
        palette.black0 = "#BF616A"
        palette.green.base = palette.cyan.base
    end,
})

This is a real difference of approach compared with editing a colors file. A static scheme forces you to fork it or override each group by hand after loading, while Nordic lets you treat the palette as a value you can compute on before it becomes highlights.

Transparency, cursorline blending and the reduced_blue switch

The remaining setup options are feature flags, and two of them have consequences worth understanding rather than just toggling.

The transparent table has two independent switches, bg for the editor background and float for floating windows, and both default to false. bright_border is separate and off by default, and it enables a brighter border on floating windows. bold_keywords defaults to false while italic_comments defaults to true, so the theme ships with italic comments on and bold keywords off.

reduced_blue defaults to true and the comment says it reduces the overall amount of blue in the theme, diverging from base Nord. That is the option that makes the scheme read as less cold, and it is on out of the box, which means adopting Nordic without any setup is not the same as adopting Nord with a darker background.

The cursorline and visual blocks are the most configurable part. Both take bold, bold_number, theme and blend. The theme value accepts dark or light, and blend is the ratio at which the cursorline or selection background is mixed with the buffer background, defaulting to 0.85. The visual selection color itself is not a setting, it is derived in the palette, which is why the after_palette example in the documentation recomputes palette.bg_visual from the orange base color.

Plugin styles that are chosen rather than computed

Several options exist to line the theme up with specific plugins, and they are simple enumerations rather than computations. The noice block takes a style of classic or flat, with classic as the default. The telescope block also takes classic or flat, but the default is flat, so the two plugins ship with different starting points.

leap has a single option, dim_backdrop, which controls whether the backdrop is dimmed while leap is active, and it defaults to false. ts_context has dark_background, which enables a dark background for the treesitter context window, and that one defaults to true.

The set of plugins with dedicated integration files is listed in the lua/nordic/groups/integrations directory, and the documentation sends readers there rather than repeating the list, so the list grows with the repository rather than with the README.

One caveat comes from the author directly. The note in the contributing section says the author does not personally use all of the platforms and plugins in the list, and invites pull requests when something is not right. That is an honest signal, and it means the integration files are contributed coverage rather than a promise of verified behaviour on every plugin.

Platform files are generated from a template system

Neovim color schemes usually have to be adjusted for terminals, and Nordic handles that with a directory of platform specific files, listed in the platforms directory of the repository. The project also ships platforms.sh at the top level, next to the platforms directory, which is the entry point for regenerating them.

The contributing note explains the arrangement: all of the platform files are generated using a template system, and the lua/nordic/platforms directory holds the machinery for it. That is a design decision with a practical consequence. Instead of hand maintaining a copy of the palette for every platform, the colors are produced from one source, so a change to the base palette propagates rather than needing to be repeated. The cost is that the platform files are build output, so a contributor editing a generated file directly will find the change overwritten.

The project also acknowledges folke/tokyonight as the example and template it followed for creating a Neovim theme, and credits a dotfiles repository for the screenshots and a palette preview tool for the palette image. The README is a working document rather than a marketing page, and it says that a wrong highlight, however small, should be reported as an issue or a pull request.

The ordering trap with require('nordic.colors')

The one documented footgun in the whole project concerns the palette accessor. The README gives a one line way to use the color palette elsewhere in your config, and then attaches a warning to it. Calling require('nordic.colors') before setup leaves you with colors that are wrong for your config.

The reason follows from the order described earlier. setup runs the palette callbacks and produces the extended palette, so a request for the palette that arrives before that has run sees a different or incomplete set of values. The fix is mundane and the fix is free: load the theme first, then read the palette.

This is the kind of detail that separates a theme with a configuration layer from a static colors file, and it is also a small tax on the user. A plugin that wants to match the theme, for example to colour its own borders, has to know whether Nordic has been set up yet. Nothing in the API enforces the ordering, so the constraint is carried by documentation rather than by code.

For someone who wants Nord's palette but not Nord's exact colours, the practical comparison is that plain Nord is fixed while Nordic gives a palette object to compute on. Someone who wants a theme that never needs a setup call should look elsewhere.

Editorial conclusion

Adopt nordic.nvim if you already use Nord and want a darker, warmer variant that you can still adjust at runtime through on_palette, after_palette and on_highlight, because the whole point of the project is that layer rather than a fixed set of highlights. Do not adopt it if you want a theme that ships no Lua configuration surface, or if you need the plugin and platform integrations verified, since the author states plainly that not every listed integration is one they use. Before configuring anything, call require('nordic.colors') only after setup, as the documentation warns the colors will otherwise be wrong for your config.

Frequently asked questions

How do I install nordic.nvim in Neovim?

It is a normal Neovim plugin, so you install it with your plugin manager. The README gives a lazy.nvim block with priority 1000 and a config function that calls require('nordic').load(), a packer.nvim one line declaration, and a vim-plug Plug line pinned to the main branch.

How do I change a single colour in nordic.nvim?

Call require('nordic').setup with the on_palette callback for base palette colours, after_palette for extended palette colours, or on_highlight for individual highlight groups. The documented example changes palette.black0 and reassigns palette.green.base.

Why do the colours look wrong when I use require('nordic.colors')?

The README warns that require('nordic.colors') must be called after setup, otherwise the colors might be wrong for your config, because setup is what builds the extended palette.

Does nordic.nvim support lualine and Telescope?

Yes. The README shows a lualine block with theme set to 'nordic' in options, and the setup options include a telescope block with a style of classic or flat, defaulting to flat. Plugin integrations live in the lua/nordic/groups/integrations directory.

Official sources

  1. AlexvZyl/nordic.nvim on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/alexvzyl-nordic-nvim.svg)](https://hysenlabs.com/projects/alexvzyl-nordic-nvim)

Was this useful?