Setting Up lazy.nvim in Neovim: A Complete Guide

Learn how to properly set up lazy.nvim plugin manager in Neovim, including understanding Neovim's runtime path and lua module system.

nvimlazy.nvimluaneovimeditor

Setting Up lazy.nvim in Neovim

Setting up lazy.nvim can be confusing at first, especially understanding how Neovim’s module system works. This guide will walk you through the process step by step.

Understanding Neovim’s Module System

When you see this in your init.lua:

-- ~/.config/nvim/init.lua
require("config.lazy")

You might think you need to create a config.lazy.lua file — but that’s not quite right.

Or maybe config/lazy.lua — almost, but not quite!

Key Concepts

Neovim only looks into lua files to require inside of folders that have lua/ as a top-level folder.

This lua folder must be in the runtime path.

You can check your runtime paths with:

:echo nvim_list_runtime_paths()

Therefore, we need to create a lua folder in our config directory.

Step-by-Step Setup

1. Create the Directory Structure

:!mkdir -p lua/config

This creates the lua/config directory structure that Neovim expects.

2. Create the lazy.lua File

Create ~/.config/nvim/lua/config/lazy.lua:

:e lua/config/lazy.lua

3. Add the Bootstrap Code

Here’s the complete setup for lazy.lua:

-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)

-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"

-- Setup lazy.nvim
require("lazy").setup({
  spec = {
    -- import your plugins
    { import = "plugins" },
  },
  -- Configure any other settings here. See the documentation for more details.
  -- colorscheme that will be used when installing plugins.
  install = { colorscheme = { "habamax" } },
  -- automatically check for plugin updates
  checker = { enabled = true },
})

How It Works

  1. Bootstrap Phase: The script checks if lazy.nvim exists in the data directory. If not, it clones the repository.

  2. Runtime Path: The script prepends the lazy.nvim path to Neovim’s runtime path using vim.opt.rtp:prepend(lazypath).

  3. Leader Keys: Setting mapleader and maplocalleader before loading lazy.nvim ensures that plugin key mappings work correctly.

  4. Plugin Configuration: The require("lazy").setup() call initializes lazy.nvim with your plugin specifications.

Directory Structure

Your final directory structure should look like this:

~/.config/nvim/
├── init.lua
└── lua/
    └── config/
        └── lazy.lua

When you run require("config.lazy") from init.lua, Neovim will:

  1. Look for a lua/ folder in your config directory
  2. Find config/lazy.lua inside that folder
  3. Execute that file

Next Steps

After setting up lazy.nvim, you’ll want to:

  1. Create a lua/plugins/ directory for your plugin configurations
  2. Add plugin specs in lua/plugins/init.lua or individual files
  3. Use lazy.nvim’s lazy loading features to optimize startup time

References

Common Issues

Issue: “module not found”

Solution: Make sure your lua/ folder is in the correct location (~/.config/nvim/lua/) and that the file path matches the require statement.

Issue: Leader key not working

Solution: Make sure you set vim.g.mapleader before calling require("lazy").setup().

Issue: Plugins not loading

Solution: Check that your plugin specs are in the correct location (lua/plugins/) and that you’re importing them correctly in the lazy setup.


Happy Neovim configuring! 🚀