I’ve been using Neovim full-time for a couple of years now. Here’s my current setup - built on LazyVim with a focus on Python development using the Astral toolchain.
Why LazyVim Link to heading
I started with a custom config but maintaining it became tedious. LazyVim gives me sensible defaults while still allowing customisation. The key benefits:
- Batteries included - LSP, treesitter, telescope all preconfigured
- Lazy loading - plugins load on demand, keeping startup fast
- Easy updates -
LazyVimhandles plugin compatibility
~/.config/nvim/
├── init.lua # Bootstraps lazy.nvim
├── lazy-lock.json # Lockfile for reproducible installs
└── lua/
├── config/ # Options, keymaps, autocmds
└── plugins/ # Custom plugin configs
Python setup: ty + ruff Link to heading
The interesting part of my config is the Python tooling. I’ve switched from pyright to ty - Astral’s new type checker (the same folks behind ruff and uv).
-- lua/plugins/lsp.lua
-- Register ty server (not yet in nvim-lspconfig)
local configs = require("lspconfig.configs")
if not configs.ty then
configs.ty = {
default_config = {
cmd = { "ty", "server" },
filetypes = { "python" },
root_dir = require("lspconfig.util").root_pattern("pyproject.toml", "ty.toml", ".git"),
single_file_support = true,
},
}
end
return {
{
"neovim/nvim-lspconfig",
opts = {
servers = {
-- Disable the alternatives
basedpyright = { enabled = false },
pyright = { enabled = false },
pylsp = { enabled = false },
eslint = { enabled = false },
-- Enable ty for type checking
ty = {
enabled = true,
autostart = true,
},
-- Enable ruff for linting/formatting
ruff = {
enabled = true,
autostart = true,
init_options = {
settings = {
fixAll = true,
},
},
},
},
},
},
}
This setup means:
- ty handles type checking (faster than pyright, from the Astral team)
- ruff handles linting and formatting (replaces flake8, black, isort)
The Astral stack (uv + ruff + ty) is becoming my default for everything Python.
Plugins I actually use Link to heading
From my lazy-lock.json, the plugins I interact with daily:
| Plugin | Purpose |
|---|---|
| telescope.nvim | Fuzzy finding everything |
| gitsigns.nvim | Git status in the gutter |
| flash.nvim | Quick navigation |
| which-key.nvim | Keybinding hints |
| trouble.nvim | Better diagnostics list |
| grug-far.nvim | Search and replace |
| venv-selector.nvim | Python virtualenv switching |
LazyVim bundles many more, but these are the ones I consciously use.
Debugging startup time Link to heading
If Neovim feels slow, profile it:
nvim --startuptime startup.log
cat startup.log | sort -k2 -n | tail -20
My startup is ~150ms. If yours is slow, check for:
- Plugins not lazy-loaded (should use
event = "VeryLazy"or similar) - Heavy LSP servers starting immediately
- Treesitter parsers compiling on startup
Test with a clean config to isolate issues:
nvim --clean
Neovim vs VS Code Link to heading
I’ve used both extensively. My take:
Neovim works for me because:
- I live in the terminal anyway
- ~50MB RAM vs VS Code’s 2GB+
- The modal editing model clicked for me
- I enjoy tinkering with configs
I’d still recommend VS Code if:
- You want things to just work
- You pair programme (Live Share is excellent)
- You prefer GUI interactions
- You’re learning a new language and want rich tooling immediately
Config Link to heading
My full config is in my dotfiles. The interesting bits are in lua/plugins/lsp.lua for the ty + ruff setup.