base16-pro-max.nvim ✨

July 3, 2026 · View on GitHub

Base16 for modern Neovim — not just colors.

Most Base16 plugins stop at 16 colors + syntax.

base16-pro-max goes beyond: transparency, dimmed inactive panes, semantic aliases, live blends, overrides, and first-class plugin integrations.

Paste any Base16 palette (Rose-pine, Catppuccin, Tokyo Night…) and instantly get a fully-featured, modern theme—no extra themes, no hacks, no switching plugins.

demo

🌈 Why base16-pro-max.nvim is different

FeatureWhy it matters?
Semantic color aliasesbg, fg, red, blue — no more base0X confusions. (Following the base16 guideline)
Modern colorscheme plugin featuresdim_inactive_windows, transparency, blends.
Highlight overridesChange any group or plugin color on-the-fly.
Plugin integrationsMini, Blink, RenderMarkdown, Which-key, Flash, Gitsigns, Grug-far, Undo-glow, and more — opt-in, zero bloat.
Function-powered paletteDynamic colors using Lua functions (cursorline = function(c) return blend(c.bg, c.fg, 0.07) end).
Runtime validationHelpful errors before your screen turns pink.
Fast startupAggressive caching; only recomputes what you change.
YAML & JSON schema loadingLoad any Base16 YAML or JSON scheme directly — no manual color copying required.

Note

This plugin does not ship individual themes — paste your favourite Base16 hex codes or grab 200+ ready-made ones from tinted-theming/schemes.

🚀 Installation

Using lazy.nvim:

{
  "y3owk1n/base16-pro-max.nvim",
  config = function()
    require("base16-pro-max").setup({ --[[ your config ]] })
    vim.cmd.colorscheme("base16-pro-max")
  end
}

Using packer.nvim:

use {
  "y3owk1n/base16-pro-max.nvim",
  config = function()
    require("base16-pro-max").setup({ --[[ your config ]] })
    vim.cmd.colorscheme("base16-pro-max")
  end
}

⚡ Quick Start

Note

All features and integration are disabled by default, feel free to enable them in your config.

Using manual colors

-- Minimal setup with Kanagawa-inspired colors
{
  "y3owk1n/base16-pro-max.nvim",
  priority = 1000,
  config = function()
    require("base16-pro-max").setup {
      colors = {
        base00 = "#1f1f28", base01 = "#2a2a37", base02 = "#3a3a4e",
        base03 = "#4e4e5e", base04 = "#9e9eaf", base05 = "#c5c5da",
        base06 = "#dfdfef", base07 = "#e6e6f0", base08 = "#ff5f87",
        base09 = "#ff8700", base0A = "#ffaf00", base0B = "#5fff87",
        base0C = "#5fd7ff", base0D = "#5fafff", base0E = "#af87ff",
        base0F = "#d7875f",
      },
      styles = { italic = true, transparency = true },
      plugins = { enable_all = true },
    }
    vim.cmd.colorscheme "base16-pro-max"
  end,
}

Using Base16 YAML/JSON schemes

-- Load from a Base16 scheme file (YAML or JSON)
{
  "y3owk1n/base16-pro-max.nvim",
  priority = 1000,
  config = function()
    local parser = require("base16-pro-max.parser")

    require("base16-pro-max").setup {
      -- Load colors from YAML file
      colors = parser.get_base16_colors("~/.config/nvim/schemes/gruvbox-dark.yaml"),
      styles = { italic = true, transparency = true },
      plugins = { enable_all = true },
    }
    vim.cmd.colorscheme "base16-pro-max"
  end,
}

Or with a JSON palette (e.g. from Stylix):

{
  "y3owk1n/base16-pro-max.nvim",
  priority = 1000,
  config = function()
    local parser = require("base16-pro-max.parser")

    require("base16-pro-max").setup {
      -- Load colors from Stylix palette.json
      colors = parser.get_base16_colors("~/.config/stylix/palette.json"),
      styles = { italic = true, transparency = true },
      plugins = { enable_all = true },
    }
    vim.cmd.colorscheme "base16-pro-max"
  end,
}

That’s it—no extra themes to install, no generated files, no external build step.

📁 YAML & JSON Scheme Support

The plugin includes a high-performance YAML and JSON parser specifically designed for Base16 schemes.

Note

This feature is an optional helper and wont be loaded if the module is not required.

Loading from Files

local parser = require("base16-pro-max.parser")

-- Basic usage: load colors from a YAML file
local colors = parser.get_base16_colors("~/path/to/scheme.yaml") -- or `yml` extension

-- Or load from a JSON file (e.g. Stylix palette.json)
local colors = parser.get_base16_colors("~/.config/stylix/palette.json")

require("base16-pro-max").setup({
  colors = colors,
  -- your other config...
})

File format

Your YAML and JSON files should follow the standard Base16 format:

YAML

scheme: "Rosé Pine Moon"
author: "Emilia Dunfelt <edun@dunfelt.se>"
slug: "rose-pine-moon"
base00: "232136"
base01: "2a273f"
base02: "393552"
base03: "6e6a86"
base04: "908caa"
base05: "e0def4"
base06: "e0def4"
base07: "56526e"
base08: "eb6f92"
base09: "f6c177"
base0A: "ea9a97"
base0B: "3e8fb0"
base0C: "9ccfd8"
base0D: "c4a7e7"
base0E: "f6c177"
base0F: "56526e"

Tinted-theming/schemes with indentation is also supported, e.g:

system: "base16"
name: "Gruvbox dark"
author: "Tinted Theming (https://github.com/tinted-theming), morhetz (https://github.com/morhetz/gruvbox)"
variant: "dark"
palette:
  base00: "#282828"
  base01: "#3c3836"
  base02: "#504945"
  base03: "#665c54"
  base04: "#928374"
  base05: "#ebdbb2"
  base06: "#fbf1c7"
  base07: "#f9f5d7"
  base08: "#cc241d"
  base09: "#d65d0e"
  base0A: "#d79921"
  base0B: "#98971a"
  base0C: "#689d6a"
  base0D: "#458588"
  base0E: "#b16286"
  base0F: "#9d0006"

JSON

{
  "scheme": "Rosé Pine Moon",
  "author": "Emilia Dunfelt <edun@dunfelt.se>",
  "slug": "rose-pine-moon",
  "base00": "232136",
  "base01": "2a273f",
  "base02": "393552",
  "base03": "6e6a86",
  "base04": "908caa",
  "base05": "e0def4",
  "base06": "e0def4",
  "base07": "56526e",
  "base08": "eb6f92",
  "base09": "f6c177",
  "base0A": "ea9a97",
  "base0B": "3e8fb0",
  "base0C": "9ccfd8",
  "base0D": "c4a7e7",
  "base0E": "f6c177",
  "base0F": "56526e"
}

palette nesting (as generated by Stylix) is also supported:

{
  "palette": {
    "base00": "#282828",
    "base01": "#3c3836",
    "base02": "#504945",
    "base03": "#665c54",
    "base04": "#928374",
    "base05": "#ebdbb2",
    "base06": "#fbf1c7",
    "base07": "#f9f5d7",
    "base08": "#cc241d",
    "base09": "#d65d0e",
    "base0A": "#d79921",
    "base0B": "#98971a",
    "base0C": "#689d6a",
    "base0D": "#458588",
    "base0E": "#b16286",
    "base0F": "#9d0006"
  }
}

Cache Management

local parser = require("base16-pro-max.parser")

-- Clear all cached data
parser.clear_cache()

-- Get cache statistics
local stats = parser.get_cache_stats()
print(vim.inspect(stats))

-- Cache is automatically saved on VimLeavePre
-- Cache location: vim.fn.stdpath("cache") .. "/base16_cache/schemes_cache.lua"

Gruvbox Dark:

gruv-box-dark

require("base16-pro-max").setup({
  colors = {
    base00 = "#282828", base01 = "#3c3836", base02 = "#504945",
    base03 = "#665c54", base04 = "#928374", base05 = "#ebdbb2",
    base06 = "#fbf1c7", base07 = "#f9f5d7", base08 = "#cc241d",
    base09 = "#d65d0e", base0A = "#d79921", base0B = "#98971a",
    base0C = "#689d6a", base0D = "#458588", base0E = "#b16286",
    base0F = "#9d0006",
  },
})

Nord:

nord

require("base16-pro-max").setup({
  colors = {
    base00 = "#2e3440", base01 = "#3b4252", base02 = "#434c5e",
    base03 = "#4c566a", base04 = "#d8dee9", base05 = "#e5e9f0",
    base06 = "#eceff4", base07 = "#8fbcbb", base08 = "#bf616a",
    base09 = "#d08770", base0A = "#ebcb8b", base0B = "#a3be8c",
    base0C = "#88c0d0", base0D = "#81a1c1", base0E = "#b48ead",
    base0F = "#5e81ac",
  },
})

Rose Pine Moon

rose-pine-moon

require("base16-pro-max").setup({
  colors = {
    base00 = "#232136", base01 = "#2a273f", base02 = "#393552",
    base03 = "#6e6a86", base04 = "#908caa", base05 = "#e0def4",
    base06 = "#e0def4", base07 = "#56526e", base08 = "#eb6f92",
    base09 = "#f6c177", base0A = "#ea9a97", base0B = "#3e8fb0",
    base0C = "#9ccfd8", base0D = "#c4a7e7", base0E = "#f6c177",
    base0F = "#56526e",
  },
})

Catppuccin Macchiato

catppuccin-macchiato

require("base16-pro-max").setup({
  colors = {
    base00 = "#24273a", base01 = "#1e2030", base02 = "#363a4f",
    base03 = "#494d64", base04 = "#5b6078", base05 = "#cad3f5",
    base06 = "#f4dbd6", base07 = "#b7bdf8", base08 = "#ed8796",
    base09 = "#f5a97f", base0A = "#eed49f", base0B = "#a6da95",
    base0C = "#8bd5ca", base0D = "#8aadf4", base0E = "#c6a0f6",
    base0F = "#f0c6c6",
  },
})

Need more? Tinted Theming has 200+ schemes; paste the hex values and you’re done.

⚙️ Configuration

Anatomy

SectionPurpose
colorsRequired – the 16 Base16 hex codes.
stylesToggles: italics, bold, transparency, dim-inactive, blend intensities.
color_groupsRemap semantic roles (what “function” or “error” looks like).
highlight_groupsAdd / override any Neovim highlight group.
pluginsEnable integrations (or enable_all = true).
setup_globalsSetup vim.g globals (e.g., vim.g.terminal_color_*).
before_highlightLua hook to mutate every highlight right before it’s applied.

Default Configuration

require("base16-pro-max").setup({
  -- Base16 colors (required)
  colors = {
    base00 = "#000000", -- Default background
    base01 = "#000000", -- Lighter background (status bars)
    base02 = "#000000", -- Selection background
    base03 = "#000000", -- Comments, line highlighting
    base04 = "#000000", -- Dark foreground (status bars)
    base05 = "#000000", -- Default foreground
    base06 = "#000000", -- Light foreground
    base07 = "#000000", -- Lightest foreground
    base08 = "#000000", -- Red (variables, errors)
    base09 = "#000000", -- Orange (integers, constants)
    base0A = "#000000", -- Yellow (classes, search)
    base0B = "#000000", -- Green (strings, success)
    base0C = "#000000", -- Cyan (support, regex)
    base0D = "#000000", -- Blue (functions, info)
    base0E = "#000000", -- Purple (keywords, changes)
    base0F = "#000000", -- Brown (deprecated)
  },

  -- Style options
  styles = {
    italic = false,                    -- Enable italic text
    bold = false,                      -- Enable bold text
    transparency = false,              -- Transparent background
    use_cterm = false,                 -- Use cterm colors
    dim_inactive_windows = false,      -- Dim inactive windows
    blends = {
      subtle = 10,                     -- Barely visible (10%)
      medium = 15,                     -- Noticeable (15%)
      strong = 25,                     -- Prominent (25%)
      super = 50,                      -- Very prominent (50%)
    },
  },

  -- Plugin integrations
  plugins = {
    enable_all = false,                -- Enable all supported plugins
  },

  -- Setup vim.g globals
  setup_globals = {
    terminal_colors = false,           -- Set terminal colors (`vim.g.terminal_color_*`)
    base16_gui_colors = false,         -- Set base16 gui colors (`vim.g.base16_gui*`)
  },

  -- Semantic color groups
  color_groups = {
    backgrounds = {
      normal = "bg",
      dim = "bg_dim",
      light = "bg_light",
      selection = "bg_light",
      cursor_line = function(function_refs) return function_refs.blend_fn(function_refs.colors.bg_light, function_refs.colors.bg, 0.6) end,
      cursor_column = function(function_refs) return function_refs.blend_fn(function_refs.colors.bg_dim, function_refs.colors.bg, 0.3) end,
    },
    foregrounds = {
      normal = "fg",
      dim = "fg_dim",
      dark = "fg_dark",
      light = "fg_light",
      bright = "fg_bright",
      comment = "fg_dark",
      line_number = function(function_refs) return function_refs.blend_fn(function_refs.colors.fg_dim, function_refs.colors.bg, 0.7) end,
      border = "fg_dim",
    },
    syntax = {
      variable = "fg",
      constant = "brown",
      string = "green",
      number = "orange",
      boolean = "orange",
      keyword = "purple",
      function_name = "blue",
      type = "yellow",
      comment = "fg_dark",
      operator = "cyan",
      delimiter = "fg_dark",
      deprecated = "brown",
    },
    states = {
      error = "red",
      warning = "yellow",
      info = "blue",
      hint = "cyan",
      success = "green",
    },
    diff = {
      added = "green",
      removed = "red",
      changed = "orange",
      text = "blue",
    },
    git = {
      added = "green",
      removed = "red",
      changed = "orange",
      untracked = "brown",
    },
    search = {
      match = "yellow",
      current = "orange",
      incremental = "orange",
    },
    markdown = {
      heading1 = "red",
      heading2 = "orange",
      heading3 = "yellow",
      heading4 = "green",
      heading5 = "cyan",
      heading6 = "blue",
    },
    modes = {
      normal = "blue",
      insert = "green",
      visual = "yellow",
      visual_line = "yellow",
      replace = "cyan",
      command = "red",
    },
  },

  -- Additional highlight groups
  highlight_groups = {},

  -- Pre-highlight callback
  before_highlight = nil,
})

Color Reference

Base16 Semantic Aliases

The purpose is based of tinted theming scheme

AliasRawPurpose
bgbase00Default background
bg_dimbase01Lighter background (status bars)
bg_lightbase02Selection background
fg_dimbase03Comments, line highlighting
fg_darkbase04Dark foreground (status bars)
fgbase05Default foreground
fg_lightbase06Light foreground
fg_brightbase07Lightest foreground
redbase08Variables, errors, markup deletion
orangebase09Numbers, constants, attributes
yellowbase0AClasses, search, markup bold
greenbase0BStrings, success, markup insertion
cyanbase0CSupport, regex, markup quotes
bluebase0DFunctions, info, headings
purplebase0EKeywords, changes, markup italic
brownbase0FDeprecated, embedded languages

Advanced Usage

Loading Colors from Multiple Sources

local parser = require("base16-pro-max.parser")

-- Option 1: Load from YAML file
local colors = parser.get_base16_colors("~/schemes/gruvbox.yaml")

-- Option 2: Load from a JSON file (e.g. Stylix palette.json)
local colors = parser.get_base16_colors("~/.config/stylix/palette.json")

-- Option 3: Mix parsed colors with manual overrides
local colors = vim.tbl_extend("force",
  parser.get_base16_colors("~/schemes/base.yaml"),
  {
    base08 = "#ff0000", -- Override red
    base0B = "#00ff00", -- Override green
  }
)

-- Option 4: Conditional loading
local colors = {}
local condition = some_condition() -- e.g., vim.fn.filereadable
if condition then
  colors = parser.get_base16_colors("~/schemes/custom.yaml")
else
  -- Fallback to manual colors
  colors = {
    base00 = "#1f1f28", base01 = "#2a2a37", -- ...
  }
end

require("base16-pro-max").setup({ colors = colors })

Overrides Color Groups

require("base16-pro-max").setup({
  colors = { --[[ your base16 colors ]] },
  color_groups = {
    syntax = {
      -- Use a different color for functions
      function_name = "cyan", -- Use semantic alias
      operator = "base0A",    -- Use raw base16 color
      -- Use a custom function for comments
      -- Using function, you can access the raw colors and blend functions
      -- `function_refs.colors` -> semantic color palette
      -- `function_refs.blend_fn` -> blend colors function
      --
      -- NOTE: To understand more, refer to the source code on how these are being used for color_groups
      comment = function(function_refs)
        return function_refs.blend_fn(function_refs.colors.fg_dim, function_refs.colors.bg, 0.8)
      end,
    },
  },
})

Custom Highlight Groups

You can either do it in table or function format.

-- Table format
-- In table format, you can use the semantic aliases and apply anything from `vim.api.keyset.highlight`
require("base16-pro-max").setup({
  colors = { --[[ your base16 colors ]] },
  highlight_groups = {
    -- Custom highlight using base16 colors
    MyCustomHighlight = {
      fg = "red",          -- Use semantic alias
      bg = "base01",       -- Use raw base16 color
      bold = true,
    },
    -- Link to existing highlight
    MyOtherHighlight = { link = "Function" },
  },
})
-- Function format
-- In function format, you have more access to the raw functions
-- `function_refs.get_group_color_fn` -> get colors from color groups
-- `function_refs.get_bg_fn` -> get background color (or transparent)
-- `function_refs.blend_fn` -> blend colors
-- `function_refs.styles_config` -> styles configuration
-- `function_refs.colors` -> semantic color palette
--
-- NOTE: To understand more, refer to the source code on how these are being used to apply highlights in a consistent
-- way
require("base16-pro-max").setup({
  colors = { --[[ your base16 colors ]] },
  highlight_groups = function(function_refs)
    return {
      MyCustomHighlight = {
        fg = function_refs.get_group_color_fn("syntax", "function_name", function_refs.colors),
        bg = function_refs.get_bg_fn(function_refs.get_group_color_fn("backgrounds", "normal", function_refs.colors)),
        bold = function_refs.styles_config.bold,
      },
      MyOtherHighlight = { link = "Function" },
    }
  end,
})

Style Variations

-- Dark theme with transparency and italics
require("base16-pro-max").setup({
  colors = { --[[ dark colors ]] },
  styles = {
    transparency = true,
    italic = true,
    bold = true,
    dim_inactive_windows = true,
  },
})

-- Light theme with subtle blends
require("base16-pro-max").setup({
  colors = { --[[ light colors ]] },
  styles = {
    blends = {
      subtle = 5,
      medium = 10,
      strong = 15,
      super = 25,
    },
  },
})

Plugin Integration

require("base16-pro-max").setup({
  colors = { --[[ your colors ]] },
  plugins = {
    -- Enable all supported plugins
    enable_all = true,
    -- Or enable specific plugins
    nvim_mini_mini_icons = true,
    saghen_blink_cmp = true,
    folke_which_key_nvim = true,
  },
})

API Reference

local base16_pro_max = require("base16-pro-max")
local parser = require("base16-pro-max.parser")

-- Setup the plugin (required)
base16_pro_max.setup(config)

-- Apply the colorscheme
vim.cmd.colorscheme("base16-pro-max")

-- Get semantic color palette
local colors = base16_pro_max.colors()

-- Get specific color
local red = base16_pro_max.get_color("red")
local bg = base16_pro_max.get_color("bg")

-- Get multiple colors
local palette = base16_pro_max.get_colors({"red", "blue", "green"})

-- Get raw base16 colors
local raw = base16_pro_max.raw_colors()

-- Get color from groups
local error_color = base16_pro_max.get_group_color("states", "error")

-- Blend colors
local blended = base16_pro_max.blend_colors("#ff0000", "#000000", 0.5)

-- Validate colors
local valid, missing = base16_pro_max.validate_colors(my_colors)

-- Parser API (.yaml, .yml, .json)
local colors = parser.get_base16_colors("path/to/scheme.yaml")
local colors = parser.get_base16_colors("path/to/palette.json")
parser.clear_cache()
local stats = parser.get_cache_stats()

🔌 Supported Plugins

  • Mini.nvim: Icons, Diff, Files, Pick, Statusline
  • Blink.cmp: Completion menu styling
  • RenderMarkdown: Enhanced markdown rendering
  • Undo Glow: Undo visualization
  • Grug Far: Search and replace
  • Which Key: Key binding hints
  • Flash: Jump navigation
  • Gitsigns: Git signs
  • Telescope: Fuzzy finders
  • Fzf: Fuzzy finders
  • Lualine: Lualine statusline (add options.theme = "base16-pro-max" to your lualine configuration)

Why Only These Few Plugins?

The current plugin integrations reflect my personal Neovim setup - these are the plugins I use daily and can thoroughly test. Rather than adding superficial support for plugins I don't use, I've focused on providing high-quality integrations for my actual workflow.

Want support for your favorite plugin? I welcome pull requests! The plugin architecture makes it straightforward to add new integrations. Check out the existing implementations in the codebase as examples, and feel free to contribute support for additional plugins.

🩺 Troubleshooting

Colors not applying correctly:

  • Ensure your terminal supports true color: set termguicolors in Neovim
  • Check that all required base16 colors (base00-base0F) are provided
  • Verify color format is valid hex (e.g., #ffffff)

YAML/JSON loading issues:

  • Verify the file exists and is readable
  • Ensure the file follows Base16 format with base00-base0F keys
  • JSON files should be valid JSON (no trailing commas)
  • Check file permissions and path expansion (~ should work)
  • Use absolute paths if relative paths cause issues

Performance issues:

  • Color caching should handle most cases automatically
  • YAML files are cached automatically with mtime checking
  • If you modify colors frequently, call require("base16")._invalidate_cache() manually
  • There's a bench.lua script in the repo root that you can run with nvim --headless -l ./bench.lua to get the benchmark results.

Plugin integrations not working:

  • Ensure the plugin is installed and loaded before base16
  • Check that the plugin integration is enabled in your config
  • Some plugins may override highlights - load base16 after them

Validation errors:

  • Read error messages carefully - they indicate exactly what's wrong
  • Use the default configuration as a reference
  • Check function returns in color_groups are valid hex colors

Development

Architecture

The plugin is structured in several key modules:

  • Validation (V): Comprehensive configuration validation
  • Utility (U): Color manipulation, caching, and helper functions
  • Highlight Setup: Modular highlight group definitions
  • Plugin Integration: Extensible plugin support system
  • API: Public interface for programmatic access

Adding Plugin Support

  1. Add plugin option to Base16.Config.Plugins type in init.lua
  2. Add the plugin into M.plugin_map in plugins/init.lua
  3. Create a corresponding plugin file in plugins folder and set it up like others
  4. Do not specify colors directly in highlight groups, add the colors to default_config.color_groups instead if really needed and use it.
  5. If there's a need for extra setup, add it to the help section at @mod base16-pro-max.plugins
  6. Test with actual plugin usage
  7. Submit pull request with documentation

Color Group Architecture

The plugin uses a hierarchical color system:

Base16 Raw Colors (base00-base0F)

Semantic Aliases (bg, fg, red, blue, etc.)

Color Groups (backgrounds, syntax, states, etc.)

Highlight Groups (Normal, Function, Error, etc.)

This allows for consistent theming while maintaining flexibility.

📝 Contributing

We welcome contributions! Here's how to get started:

Contribution Guidelines

  • Follow existing code style and patterns
  • Add appropriate type annotations
  • Include validation for new configuration options
  • Test with real plugin usage scenarios
  • Update documentation for new features
  • Write clear commit messages

Areas for Contribution

  • Plugin integrations: Support for additional Neovim plugins
  • Documentation: Examples, tutorials, migration guides
  • Testing: Automated testing, edge case coverage
  • Features: Features that are common for theme plugins (e.g., dimmed inactive panes and more)
  • Performance: Optimization improvements

License

MIT License - see LICENSE file for details.

Acknowledgments

  • Base16 Project for the color specification
  • Mini.nvim for inspiration on plugin architecture
  • Rosepine for inspiration on the modern colorscheme features
  • The Neovim community for feedback and contributions
  • All contributors who help improve this plugin