Neovim's Lua API is the biggest reason to switch from Vim. Unlike Vimscript, Lua is a real programming language — fast, composable, and with first-class support in Neovim 0.10+.
This guide builds a Neovim config from zero using lazy.nvim, the modern plugin manager that loads plugins on-demand for instant startup.
By the end, you'll have a config that boots in under 50ms and rivals any IDE.
Install Neovim 0.10 or later. On macOS: brew install neovim. On Linux: use your distro's package manager or build from source.
:version)Create the config directory structure:
~/.config/nvim/
├── init.lua # Entry point
├── lua/
│ ├── core/ # Options, keymaps, autocmds
│ │ ├── init.lua
│ │ ├── options.lua
│ │ └── keymaps.lua
│ └── plugins/ # Plugin specs
│ └── init.luaThe magic of lazy.nvim is that it bootstraps itself. Put this in init.lua and lazy.nvim installs itself on first launch:
-- bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git", "clone", "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git", lazypath
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup("lua/plugins")Now create plugin specs in lua/plugins/. Each file returns a table — lazy.nvim loads them automatically:
-- lua/plugins/telescope.lua
return {
"nvim-telescope/telescope.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
keys = {
{ "ff", "Telescope find_files", desc = "Find files" },
{ "fg", "Telescope live_grep", desc = "Live grep" },
},
} The key to a great config is modular keymaps. Put your keybindings in lua/core/keymaps.lua and require them from init.lua.
<leader>ff — find files (Telescope)<leader>fg — live grep<leader>e — toggle file explorer (nvim-tree)gd — go to definition (LSP)K — hover documentation (LSP)<C-h/j/k/l> — navigate splitsSet core options in lua/core/options.lua:
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.termguicolors = true
vim.opt.scrolloff = 8
vim.opt.signcolumn = "yes"Once your base config is solid, add these power-user touches:
very_lazy event loading to defer plugin startup until first usecond = function() ... end to conditionally load plugins:Lazy profile to see which plugins slow down startup. Target under 50ms total.Common config issues and fixes:
:Mason shows available serversvim.opt.termguicolors = true before loading your colorscheme:Lazy sync to install/update all plugins:luafile % to test the current file, or use luacheck:Lazy profile to find the culpritYour Neovim config is now a living project. Here's what to explore: