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 - LazyVim handles 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:

PluginPurpose
telescope.nvimFuzzy finding everything
gitsigns.nvimGit status in the gutter
flash.nvimQuick navigation
which-key.nvimKeybinding hints
trouble.nvimBetter diagnostics list
grug-far.nvimSearch and replace
venv-selector.nvimPython 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.

Further reading Link to heading