LazyVim: Modern Neovim Configuration
LazyVim is a popular, pre-configured Neovim setup that provides a modern IDE-like experience out of the box. Built on top of lazy.nvim plugin manager, it offers sensible defaults, beautiful UI, and powerful features for developers.
What is LazyVim?
LazyVim is a Neovim configuration framework that includes: - Pre-configured plugins: Carefully selected and configured plugins - Lazy loading: Fast startup times with lazy.nvim - Modern UI: Beautiful interface with proper theming - LSP integration: Built-in Language Server Protocol support - Extensible: Easy to customize and extend - Well-documented: Comprehensive documentation and examples
Why Choose LazyVim?
- Zero configuration: Works great out of the box
- Fast startup: Optimized for performance
- Modern features: Latest Neovim capabilities
- Active development: Regular updates and improvements
- Great defaults: Sensible keybindings and settings
- Easy customization: Simple configuration structure
Installation
Prerequisites
# Neovim 0.9.0 or higher
nvim --version
# Install Neovim if needed
# Ubuntu/Debian
sudo apt install neovim
# Arch Linux
sudo pacman -S neovim
# SUSE/openSUSE
sudo zypper install neovim
# Gentoo
sudo emerge app-editors/neovim
Required Dependencies
# Git (required)
git --version
# Node.js (for LSP servers)
node --version
npm --version
# Python (for some plugins)
python3 --version
pip3 --version
# Ripgrep (for telescope)
rg --version
# fd (for telescope)
fd --version
# Install missing dependencies
# Ubuntu/Debian
sudo apt install git nodejs npm python3 python3-pip ripgrep fd-find
# Arch Linux
sudo pacman -S git nodejs npm python python-pip ripgrep fd
# SUSE/openSUSE
sudo zypper install git nodejs npm python3 python3-pip ripgrep fd
# Gentoo
sudo emerge dev-vcs/git net-libs/nodejs dev-lang/python sys-apps/ripgrep sys-apps/fd
Installation Steps
# Backup existing Neovim configuration
mv ~/.config/nvim ~/.config/nvim.bak
mv ~/.local/share/nvim ~/.local/share/nvim.bak
mv ~/.local/state/nvim ~/.local/state/nvim.bak
mv ~/.cache/nvim ~/.cache/nvim.bak
# Clone LazyVim starter template
git clone https://github.com/LazyVim/starter ~/.config/nvim
# Remove .git folder to make it your own
rm -rf ~/.config/nvim/.git
# Start Neovim (plugins will install automatically)
nvim
Initial Setup and Configuration
First Launch
When you first start LazyVim:
- Plugin Installation: Plugins install automatically
- Mason Setup: Language servers install automatically
- Treesitter: Syntax parsers download automatically
- Health Check: Run
:checkhealth
to verify setup
Basic Configuration Structure
~/.config/nvim/
├── init.lua # Entry point
├── lua/
│ ├── config/
│ │ ├── autocmds.lua # Auto commands
│ │ ├── keymaps.lua # Key mappings
│ │ ├── lazy.lua # Plugin manager setup
│ │ └── options.lua # Neovim options
│ └── plugins/
│ ├── example.lua # Example plugin config
│ └── ... # Your plugin configurations
└── stylua.toml # Lua formatter config
Basic Options Configuration
-- ~/.config/nvim/lua/config/options.lua
-- LazyVim auto format
vim.g.autoformat = true
-- LazyVim picker to use
-- Can be one of: telescope, fzf
vim.g.lazyvim_picker = "telescope"
-- LazyVim root dir detection
-- Each entry can be:
-- * the name of a detector function like `lsp` or `cwd`
-- * a pattern or array of patterns like `.git` or `lua`.
-- * a function with signature `function(buf) -> string|string[]`
vim.g.root_spec = { "lsp", { ".git", "lua" }, "cwd" }
-- LazyVim automatically configures lazygit:
-- * theme, based on the active colorscheme.
-- * editorPreset to nvim-remote
-- * enables nerd font icons
-- Set to false to disable.
vim.g.lazygit_config = true
-- Options are automatically loaded before lazy.nvim startup
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
-- Add any additional options here
-- Line numbers
vim.opt.relativenumber = true -- Relative line numbers
vim.opt.number = true -- Print line number
-- Tabs / Indentation
vim.opt.tabstop = 2 -- 2 spaces for tabs (prettier default)
vim.opt.shiftwidth = 2 -- 2 spaces for indent width
vim.opt.expandtab = true -- expand tab to spaces
vim.opt.autoindent = true -- copy indent from current line when starting new one
-- Line wrapping
vim.opt.wrap = false -- disable line wrapping
-- Search settings
vim.opt.ignorecase = true -- ignore case when searching
vim.opt.smartcase = true -- if you include mixed case in your search, assumes you want case-sensitive
-- Cursor line
vim.opt.cursorline = true -- highlight the current cursor line
-- Appearance
vim.opt.termguicolors = true
vim.opt.background = "dark" -- colorschemes that can be light or dark will be made dark
vim.opt.signcolumn = "yes" -- show sign column so that text doesn't shift
-- Backspace
vim.opt.backspace = "indent,eol,start" -- allow backspace on indent, end of line or insert mode start position
-- Clipboard
vim.opt.clipboard:append("unnamedplus") -- use system clipboard as default register
-- Split windows
vim.opt.splitright = true -- split vertical window to the right
vim.opt.splitbelow = true -- split horizontal window to the bottom
-- Turn off swapfile
vim.opt.swapfile = false
Custom Keymaps
-- ~/.config/nvim/lua/config/keymaps.lua
-- Keymaps are automatically loaded on the VeryLazy event
-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
-- Add any additional keymaps here
local keymap = vim.keymap -- for conciseness
-- General keymaps
keymap.set("i", "jk", "<ESC>", { desc = "Exit insert mode with jk" })
keymap.set("n", "<leader>nh", ":nohl<CR>", { desc = "Clear search highlights" })
-- increment/decrement numbers
keymap.set("n", "<leader>+", "<C-a>", { desc = "Increment number" }) -- increment
keymap.set("n", "<leader>-", "<C-x>", { desc = "Decrement number" }) -- decrement
-- window management
keymap.set("n", "<leader>sv", "<C-w>v", { desc = "Split window vertically" }) -- split window vertically
keymap.set("n", "<leader>sh", "<C-w>s", { desc = "Split window horizontally" }) -- split window horizontally
keymap.set("n", "<leader>se", "<C-w>=", { desc = "Make splits equal size" }) -- make split windows equal width & height
keymap.set("n", "<leader>sx", "<cmd>close<CR>", { desc = "Close current split" }) -- close current split window
keymap.set("n", "<leader>to", "<cmd>tabnew<CR>", { desc = "Open new tab" }) -- open new tab
keymap.set("n", "<leader>tx", "<cmd>tabclose<CR>", { desc = "Close current tab" }) -- close current tab
keymap.set("n", "<leader>tn", "<cmd>tabn<CR>", { desc = "Go to next tab" }) -- go to next tab
keymap.set("n", "<leader>tp", "<cmd>tabp<CR>", { desc = "Go to previous tab" }) -- go to previous tab
keymap.set("n", "<leader>tf", "<cmd>tabnew %<CR>", { desc = "Open current buffer in new tab" }) -- move current buffer to new tab
-- Move text up and down
keymap.set("v", "J", ":m '>+1<CR>gv=gv", { desc = "Move text down" })
keymap.set("v", "K", ":m '<-2<CR>gv=gv", { desc = "Move text up" })
-- Stay in indent mode
keymap.set("v", "<", "<gv", { desc = "Indent left" })
keymap.set("v", ">", ">gv", { desc = "Indent right" })
-- Keep last yanked when pasting
keymap.set("v", "p", '"_dP', { desc = "Paste without yanking" })
Auto Commands
-- ~/.config/nvim/lua/config/autocmds.lua
-- Autocmds are automatically loaded on the VeryLazy event
-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua
-- Add any additional autocmds here
local function augroup(name)
return vim.api.nvim_create_augroup("lazyvim_" .. name, { clear = true })
end
-- Highlight on yank
vim.api.nvim_create_autocmd("TextYankPost", {
group = augroup("highlight_yank"),
callback = function()
vim.highlight.on_yank()
end,
})
-- resize splits if window got resized
vim.api.nvim_create_autocmd({ "VimResized" }, {
group = augroup("resize_splits"),
callback = function()
local current_tab = vim.fn.tabpagenr()
vim.cmd("tabdo wincmd =")
vim.cmd("tabnext " .. current_tab)
end,
})
-- go to last loc when opening a buffer
vim.api.nvim_create_autocmd("BufReadPost", {
group = augroup("last_loc"),
callback = function(event)
local exclude = { "gitcommit" }
local buf = event.buf
if vim.tbl_contains(exclude, vim.bo[buf].filetype) or vim.b[buf].lazyvim_last_loc then
return
end
vim.b[buf].lazyvim_last_loc = true
local mark = vim.api.nvim_buf_get_mark(buf, '"')
local lcount = vim.api.nvim_buf_line_count(buf)
if mark[1] > 0 and mark[1] <= lcount then
pcall(vim.api.nvim_win_set_cursor, 0, mark)
end
end,
})
-- close some filetypes with <q>
vim.api.nvim_create_autocmd("FileType", {
group = augroup("close_with_q"),
pattern = {
"PlenaryTestPopup",
"help",
"lspinfo",
"man",
"notify",
"qf",
"query",
"spectre_panel",
"startuptime",
"tsplayground",
"neotest-output",
"checkhealth",
"neotest-summary",
"neotest-output-panel",
},
callback = function(event)
vim.bo[event.buf].buflisted = false
vim.keymap.set("n", "q", "<cmd>close<cr>", { buffer = event.buf, silent = true })
end,
})
-- wrap and check for spell in text filetypes
vim.api.nvim_create_autocmd("FileType", {
group = augroup("wrap_spell"),
pattern = { "gitcommit", "markdown" },
callback = function()
vim.opt_local.wrap = true
vim.opt_local.spell = true
end,
})
-- Auto create dir when saving a file, in case some intermediate directory does not exist
vim.api.nvim_create_autocmd({ "BufWritePre" }, {
group = augroup("auto_create_dir"),
callback = function(event)
if event.match:match("^%w%w+://") then
return
end
local file = vim.loop.fs_realpath(event.match) or event.match
vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p")
end,
})
Plugin Configuration
Adding Custom Plugins
-- ~/.config/nvim/lua/plugins/example.lua
return {
-- Add your custom plugins here
{
"folke/flash.nvim",
event = "VeryLazy",
opts = {},
keys = {
{
"s",
mode = { "n", "x", "o" },
function()
require("flash").jump()
end,
desc = "Flash",
},
{
"S",
mode = { "n", "o", "x" },
function()
require("flash").treesitter()
end,
desc = "Flash Treesitter",
},
},
},
-- Disable default plugins
{ "folke/flash.nvim", enabled = false },
-- Override plugin configuration
{
"nvim-telescope/telescope.nvim",
opts = {
defaults = {
layout_strategy = "horizontal",
layout_config = { prompt_position = "top" },
sorting_strategy = "ascending",
winblend = 0,
},
},
},
}
Language-Specific Configurations
-- ~/.config/nvim/lua/plugins/languages.lua
return {
-- Python
{
"nvim-treesitter/nvim-treesitter",
opts = function(_, opts)
if type(opts.ensure_installed) == "table" then
vim.list_extend(opts.ensure_installed, { "python" })
end
end,
},
{
"neovim/nvim-lspconfig",
opts = {
servers = {
pyright = {},
ruff_lsp = {},
},
},
},
-- JavaScript/TypeScript
{
"nvim-treesitter/nvim-treesitter",
opts = function(_, opts)
if type(opts.ensure_installed) == "table" then
vim.list_extend(opts.ensure_installed, { "javascript", "typescript", "tsx" })
end
end,
},
{
"neovim/nvim-lspconfig",
opts = {
servers = {
tsserver = {},
eslint = {},
},
},
},
-- Go
{
"nvim-treesitter/nvim-treesitter",
opts = function(_, opts)
if type(opts.ensure_installed) == "table" then
vim.list_extend(opts.ensure_installed, { "go", "gomod", "gowork", "gosum" })
end
end,
},
{
"neovim/nvim-lspconfig",
opts = {
servers = {
gopls = {},
},
},
},
-- Rust
{
"nvim-treesitter/nvim-treesitter",
opts = function(_, opts)
if type(opts.ensure_installed) == "table" then
vim.list_extend(opts.ensure_installed, { "rust", "toml" })
end
end,
},
{
"neovim/nvim-lspconfig",
opts = {
servers = {
rust_analyzer = {},
},
},
},
}
Essential LazyVim Features
File Explorer (Neo-tree)
# Default keymaps
<leader>fe # Open file explorer
<leader>fE # Open file explorer (root dir)
<leader>e # Toggle file explorer
<leader>E # Toggle file explorer (root dir)
# Neo-tree navigation
j/k # Move up/down
h/l # Collapse/expand or enter
<CR> # Open file
o # Open file
s # Open in split
v # Open in vsplit
t # Open in tab
a # Add file/directory
d # Delete
r # Rename
c # Copy
x # Cut
p # Paste
q # Close
Fuzzy Finding (Telescope)
# File finding
<leader>ff # Find files
<leader>fr # Recent files
<leader>fg # Find files (git)
<leader>fF # Find files (cwd)
# Text searching
<leader>sg # Grep search
<leader>sw # Search word under cursor
<leader>sG # Grep search (cwd)
<leader>ss # Search symbols
<leader>sS # Search symbols (workspace)
# Buffer management
<leader>fb # Find buffers
<leader>, # Switch buffers
# Git integration
<leader>gc # Git commits
<leader>gs # Git status
# Help and commands
<leader>sh # Help pages
<leader>sk # Key maps
<leader>sc # Commands
<leader>sC # Command history
LSP Features
# Navigation
gd # Go to definition
gr # Go to references
gI # Go to implementation
gy # Go to type definition
gD # Go to declaration
# Information
K # Hover information
gK # Signature help
<c-k> # Signature help (insert mode)
# Code actions
<leader>ca # Code actions
<leader>cA # Source actions
<leader>cr # Rename
<leader>cf # Format
<leader>cF # Format (injected langs)
# Diagnostics
<leader>cd # Line diagnostics
<leader>cD # Workspace diagnostics
]d # Next diagnostic
[d # Previous diagnostic
]e # Next error
[e # Previous error
]w # Next warning
[w # Previous warning
Git Integration (Lazygit)
# Lazygit
<leader>gg # Open Lazygit
<leader>gG # Open Lazygit (root dir)
# Git signs (gitsigns)
]h # Next hunk
[h # Previous hunk
<leader>ghs # Stage hunk
<leader>ghr # Reset hunk
<leader>ghS # Stage buffer
<leader>ghu # Undo stage hunk
<leader>ghR # Reset buffer
<leader>ghp # Preview hunk
<leader>ghb # Blame line
<leader>ghl # Blame line (full)
<leader>ghd # Diff this
<leader>ghD # Diff this ~
Terminal Integration
# Terminal
<leader>ft # Terminal (root dir)
<leader>fT # Terminal (cwd)
<c-/> # Terminal (root dir)
<c-_> # Terminal (root dir) (which-key)
# Terminal navigation (in terminal mode)
<esc><esc> # Enter normal mode
<C-h> # Go to left window
<C-j> # Go to lower window
<C-k> # Go to upper window
<C-l> # Go to right window
Real-World Development Setups
Python Development
-- ~/.config/nvim/lua/plugins/python.lua
return {
-- Python-specific plugins
{
"linux-cultist/venv-selector.nvim",
dependencies = { "neovim/nvim-lspconfig", "nvim-telescope/telescope.nvim", "mfussenegger/nvim-dap-python" },
opts = {
-- Your options go here
name = "venv",
auto_refresh = false,
},
event = "VeryLazy", -- Optional: needed only if you want to type `:VenvSelect` without a keymapping
keys = {
-- Keymap to open VenvSelector to pick a venv.
{ "<leader>vs", "<cmd>VenvSelect<cr>" },
-- Keymap to retrieve the venv from a cache (the one previously used for the same project directory).
{ "<leader>vc", "<cmd>VenvSelectCached<cr>" },
},
},
-- Python debugging
{
"mfussenegger/nvim-dap-python",
ft = "python",
dependencies = {
"mfussenegger/nvim-dap",
"rcarriga/nvim-dap-ui",
},
config = function(_, opts)
local path = "~/.local/share/nvim/mason/packages/debugpy/venv/bin/python"
require("dap-python").setup(path)
end,
},
-- Python testing
{
"nvim-neotest/neotest",
optional = true,
dependencies = {
"nvim-neotest/neotest-python",
},
opts = {
adapters = {
["neotest-python"] = {
-- Here you can specify the settings for the adapter, i.e.
runner = "pytest",
python = ".venv/bin/python",
},
},
},
},
-- Enhanced Python syntax
{
"nvim-treesitter/nvim-treesitter",
opts = function(_, opts)
if type(opts.ensure_installed) == "table" then
vim.list_extend(opts.ensure_installed, { "ninja", "python", "rst", "toml" })
end
end,
},
-- Python LSP configuration
{
"neovim/nvim-lspconfig",
opts = {
servers = {
pyright = {
settings = {
python = {
analysis = {
typeCheckingMode = "basic",
autoSearchPaths = true,
useLibraryCodeForTypes = true,
},
},
},
},
ruff_lsp = {
init_options = {
settings = {
args = {},
},
},
},
},
},
},
}
Web Development
-- ~/.config/nvim/lua/plugins/web.lua
return {
-- TypeScript/JavaScript
{
"neovim/nvim-lspconfig",
opts = {
servers = {
tsserver = {
settings = {
typescript = {
inlayHints = {
includeInlayParameterNameHints = "literal",
includeInlayParameterNameHintsWhenArgumentMatchesName = false,
includeInlayFunctionParameterTypeHints = true,
includeInlayVariableTypeHints = false,
includeInlayPropertyDeclarationTypeHints = true,
includeInlayFunctionLikeReturnTypeHints = true,
includeInlayEnumMemberValueHints = true,
},
},
javascript = {
inlayHints = {
includeInlayParameterNameHints = "all",
includeInlayParameterNameHintsWhenArgumentMatchesName = false,
includeInlayFunctionParameterTypeHints = true,
includeInlayVariableTypeHints = true,
includeInlayPropertyDeclarationTypeHints = true,
includeInlayFunctionLikeReturnTypeHints = true,
includeInlayEnumMemberValueHints = true,
},
},
},
},
eslint = {},
html = {},
cssls = {},
tailwindcss = {},
},
},
},
-- Emmet for HTML/CSS
{
"mattn/emmet-vim",
ft = { "html", "css", "javascript", "typescript", "javascriptreact", "typescriptreact" },
},
-- Auto close tags
{
"windwp/nvim-ts-autotag",
ft = { "html", "javascript", "typescript", "javascriptreact", "typescriptreact", "svelte", "vue" },
config = function()
require("nvim-ts-autotag").setup()
end,
},
-- Package.json management
{
"vuki656/package-info.nvim",
dependencies = "MunifTanjim/nui.nvim",
ft = "json",
config = function()
require("package-info").setup()
end,
},
-- REST client
{
"rest-nvim/rest.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
ft = "http",
config = function()
require("rest-nvim").setup({
result_split_horizontal = false,
result_split_in_place = false,
skip_ssl_verification = false,
encode_url = true,
highlight = {
enabled = true,
timeout = 150,
},
result = {
show_url = true,
show_curl_command = false,
show_http_info = true,
show_headers = true,
formatters = {
json = "jq",
html = function(body)
return vim.fn.system({ "tidy", "-i", "-q", "-" }, body)
end,
},
},
})
end,
},
}
Go Development
-- ~/.config/nvim/lua/plugins/go.lua
return {
-- Go plugin
{
"ray-x/go.nvim",
dependencies = { -- optional packages
"ray-x/guihua.lua",
"neovim/nvim-lspconfig",
"nvim-treesitter/nvim-treesitter",
},
config = function()
require("go").setup()
end,
event = { "CmdlineEnter" },
ft = { "go", "gomod" },
build = ':lua require("go.install").update_all_sync()', -- if you need to install/update all binaries
},
-- Go testing
{
"nvim-neotest/neotest",
optional = true,
dependencies = {
"nvim-neotest/neotest-go",
},
opts = {
adapters = {
["neotest-go"] = {
-- Here you can specify the settings for the adapter, i.e.
args = { "-count=1", "-timeout=60s" },
},
},
},
},
-- Go LSP configuration
{
"neovim/nvim-lspconfig",
opts = {
servers = {
gopls = {
settings = {
gopls = {
gofumpt = true,
codelenses = {
gc_details = false,
generate = true,
regenerate_cgo = true,
run_govulncheck = true,
test = true,
tidy = true,
upgrade_dependency = true,
vendor = true,
},
hints = {
assignVariableTypes = true,
compositeLiteralFields = true,
compositeLiteralTypes = true,
constantValues = true,
functionTypeParameters = true,
parameterNames = true,
rangeVariableTypes = true,
},
analyses = {
fieldalignment = true,
nilness = true,
unusedparams = true,
unusedwrite = true,
useany = true,
},
usePlaceholders = true,
completeUnimported = true,
staticcheck = true,
directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules" },
semanticTokens = true,
},
},
},
},
},
},
-- Go debugging
{
"leoluz/nvim-dap-go",
ft = "go",
dependencies = "mfussenegger/nvim-dap",
config = function(_, opts)
require("dap-go").setup(opts)
end,
},
}
Customization Examples
Custom Colorscheme
-- ~/.config/nvim/lua/plugins/colorscheme.lua
return {
-- Catppuccin theme
{
"catppuccin/nvim",
name = "catppuccin",
priority = 1000,
opts = {
flavour = "mocha", -- latte, frappe, macchiato, mocha
background = { -- :h background
light = "latte",
dark = "mocha",
},
transparent_background = false,
show_end_of_buffer = false,
term_colors = false,
dim_inactive = {
enabled = false,
shade = "dark",
percentage = 0.15,
},
no_italic = false,
no_bold = false,
no_underline = false,
styles = {
comments = { "italic" },
conditionals = { "italic" },
loops = {},
functions = {},
keywords = {},
strings = {},
variables = {},
numbers = {},
booleans = {},
properties = {},
types = {},
operators = {},
},
color_overrides = {},
custom_highlights = {},
integrations = {
cmp = true,
gitsigns = true,
nvimtree = true,
telescope = true,
notify = false,
mini = false,
},
},
},
-- Configure LazyVim to load catppuccin
{
"LazyVim/LazyVim",
opts = {
colorscheme = "catppuccin",
},
},
}
Custom Dashboard
-- ~/.config/nvim/lua/plugins/dashboard.lua
return {
{
"nvimdev/dashboard-nvim",
event = "VimEnter",
opts = function()
local logo = [[
██╗ █████╗ ███████╗██╗ ██╗██╗ ██╗██╗███╗ ███╗ Z
██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝██║ ██║██║████╗ ████║ Z
██║ ███████║ ███╔╝ ╚████╔╝ ██║ ██║██║██╔████╔██║ z
██║ ██╔══██║ ███╔╝ ╚██╔╝ ╚██╗ ██╔╝██║██║╚██╔╝██║ z
███████╗██║ ██║███████╗ ██║ ╚████╔╝ ██║██║ ╚═╝ ██║
╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝
]]
logo = string.rep("\n", 8) .. logo .. "\n\n"
local opts = {
theme = "doom",
hide = {
statusline = false,
},
config = {
header = vim.split(logo, "\n"),
center = {
{ action = "Telescope find_files", desc = " Find file", icon = " ", key = "f" },
{ action = "ene | startinsert", desc = " New file", icon = " ", key = "n" },
{ action = "Telescope oldfiles", desc = " Recent files", icon = " ", key = "r" },
{ action = "Telescope live_grep", desc = " Find text", icon = " ", key = "g" },
{ action = [[lua require("lazyvim.util").telescope.config_files()()]], desc = " Config", icon = " ", key = "c" },
{ action = 'lua require("persistence").load()', desc = " Restore Session", icon = " ", key = "s" },
{ action = "LazyExtras", desc = " Lazy Extras", icon = " ", key = "x" },
{ action = "Lazy", desc = " Lazy", icon = " ", key = "l" },
{ action = "qa", desc = " Quit", icon = " ", key = "q" },
},
footer = function()
local stats = require("lazy").stats()
local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
return { "⚡ Neovim loaded " .. stats.loaded .. "/" .. stats.count .. " plugins in " .. ms .. "ms" }
end,
},
}
for _, button in ipairs(opts.config.center) do
button.desc = button.desc .. string.rep(" ", 43 - #button.desc)
button.key_format = " %s"
end
-- close Lazy and re-open when the dashboard is ready
if vim.o.filetype == "lazy" then
vim.cmd.close()
vim.api.nvim_create_autocmd("User", {
pattern = "DashboardLoaded",
callback = function()
require("lazy").show()
end,
})
end
return opts
end,
},
}
Performance Optimization
Startup Optimization
-- ~/.config/nvim/lua/config/lazy.lua
-- 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",
"--branch=stable",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
spec = {
-- add LazyVim and import its plugins
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
-- import any extras modules here
{ import = "lazyvim.plugins.extras.lang.typescript" },
{ import = "lazyvim.plugins.extras.lang.json" },
{ import = "lazyvim.plugins.extras.ui.mini-animate" },
-- import/override with your plugins
{ import = "plugins" },
},
defaults = {
lazy = false, -- should plugins be lazy-loaded?
version = false, -- always use the latest git commit
},
install = { colorscheme = { "tokyonight", "habamax" } },
checker = { enabled = true }, -- automatically check for plugin updates
performance = {
rtp = {
-- disable some rtp plugins
disabled_plugins = {
"gzip",
"matchit",
"matchparen",
"netrwPlugin",
"tarPlugin",
"tohtml",
"tutor",
"zipPlugin",
},
},
},
})
Memory Optimization
-- ~/.config/nvim/lua/plugins/performance.lua
return {
-- Optimize treesitter
{
"nvim-treesitter/nvim-treesitter",
opts = {
highlight = { enable = true },
indent = { enable = true },
ensure_installed = {
"bash",
"c",
"html",
"javascript",
"json",
"lua",
"luadoc",
"luap",
"markdown",
"markdown_inline",
"python",
"query",
"regex",
"tsx",
"typescript",
"vim",
"vimdoc",
"yaml",
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
},
},
},
},
-- Optimize LSP
{
"neovim/nvim-lspconfig",
opts = {
diagnostics = {
underline = true,
update_in_insert = false,
virtual_text = {
spacing = 4,
source = "if_many",
prefix = "●",
},
severity_sort = true,
},
inlay_hints = {
enabled = true,
},
capabilities = {},
format = {
formatting_options = nil,
timeout_ms = nil,
},
servers = {},
setup = {},
},
},
}
Troubleshooting
Common Issues
# Check LazyVim health
:checkhealth
# Check specific components
:checkhealth lazy
:checkhealth mason
:checkhealth telescope
:checkhealth treesitter
# Plugin management
:Lazy # Open Lazy plugin manager
:Lazy sync # Update all plugins
:Lazy clean # Remove unused plugins
:Lazy profile # Profile startup time
# LSP troubleshooting
:LspInfo # Show LSP information
:LspRestart # Restart LSP servers
:Mason # Open Mason (LSP installer)
# Clear cache
:lua vim.fn.delete(vim.fn.stdpath("cache"), "rf")
Reset Configuration
# Backup current config
mv ~/.config/nvim ~/.config/nvim.backup
mv ~/.local/share/nvim ~/.local/share/nvim.backup
mv ~/.local/state/nvim ~/.local/state/nvim.backup
mv ~/.cache/nvim ~/.cache/nvim.backup
# Fresh install
git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git
Performance Issues
-- Profile startup time
-- Add to ~/.config/nvim/lua/config/options.lua
vim.g.loaded_python3_provider = 0
vim.g.loaded_ruby_provider = 0
vim.g.loaded_perl_provider = 0
vim.g.loaded_node_provider = 0
-- Disable unused features
vim.g.loaded_gzip = 1
vim.g.loaded_zip = 1
vim.g.loaded_zipPlugin = 1
vim.g.loaded_tar = 1
vim.g.loaded_tarPlugin = 1
vim.g.loaded_getscript = 1
vim.g.loaded_getscriptPlugin = 1
vim.g.loaded_vimball = 1
vim.g.loaded_vimballPlugin = 1
vim.g.loaded_2html_plugin = 1
vim.g.loaded_logiPat = 1
vim.g.loaded_rrhelper = 1
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.g.loaded_netrwSettings = 1
vim.g.loaded_netrwFileHandlers = 1
LazyVim provides an excellent foundation for a modern Neovim setup, combining the power of Neovim with sensible defaults and a beautiful interface. It’s perfect for developers who want a powerful IDE-like experience without the complexity of building a configuration from scratch.