<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marius van Zundert</title>
    <description>The latest articles on DEV Community by Marius van Zundert (@mvzundert).</description>
    <link>https://dev.to/mvzundert</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F38402%2F428b5ab3-8144-4396-bcfb-edb7b807d753.png</url>
      <title>DEV Community: Marius van Zundert</title>
      <link>https://dev.to/mvzundert</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mvzundert"/>
    <language>en</language>
    <item>
      <title>Why I Built nvim-starter — a Neovim Config Beginners Can Actually Understand</title>
      <dc:creator>Marius van Zundert</dc:creator>
      <pubDate>Thu, 25 Jun 2026 10:32:21 +0000</pubDate>
      <link>https://dev.to/mvzundert/why-i-built-nvim-starter-a-neovim-config-beginners-can-actually-understand-19a5</link>
      <guid>https://dev.to/mvzundert/why-i-built-nvim-starter-a-neovim-config-beginners-can-actually-understand-19a5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Kickstart.nvim gives you a working IDE. It also gives you lazy.nvim, nvim-cmp, telescope, nvim-treesitter, and a dozen concepts to learn before you've written a single line of config. I wanted something simpler.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with kickstart.nvim
&lt;/h2&gt;

&lt;p&gt;Let me be clear: kickstart.nvim is a good project. It's the standard recommendation for Neovim beginners, it's maintained by a core Neovim developer, and it ships a genuinely capable setup. I recommend it to people all the time.&lt;/p&gt;

&lt;p&gt;But every time I did, I'd watch them hit the same wall. They'd clone the repo, launch Neovim, see plugins install, and then freeze. Not because the config didn't work — because they couldn't &lt;em&gt;read&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;Here's what a beginner sees when they open kickstart.nvim's &lt;code&gt;init.lua&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;First, a large &lt;code&gt;require('lazy').setup({...})&lt;/code&gt; block with a DSL they've never seen before — &lt;code&gt;event&lt;/code&gt;, &lt;code&gt;cmd&lt;/code&gt;, &lt;code&gt;keys&lt;/code&gt;, &lt;code&gt;dependencies&lt;/code&gt;, &lt;code&gt;opts&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;. Before they've learned what &lt;code&gt;vim.opt&lt;/code&gt; does, they're staring at lazy-loading triggers and event-driven plugin activation. Then nvim-cmp, which requires four separate source plugins (&lt;code&gt;cmp-nvim-lsp&lt;/code&gt;, &lt;code&gt;cmp-buffer&lt;/code&gt;, &lt;code&gt;cmp-path&lt;/code&gt;, &lt;code&gt;cmp_luasnip&lt;/code&gt;) and a configuration block that maps twenty keybindings, defines a formatting function, and wires up capabilities. Then telescope with its own setup and extension loading. Then nvim-treesitter with &lt;code&gt;ensure_installed&lt;/code&gt;. Then mason-lspconfig with a manual &lt;code&gt;ensure_installed&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;None of this is wrong — it's just &lt;em&gt;a lot&lt;/em&gt;. It's a production config dressed as a starter. The very things that make kickstart powerful (lazy-loading, modular plugin specs, extensible completion sources) are the things that make it illegible to someone who doesn't yet know what a plugin &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So I built nvim-starter. The goal: a configuration you can read top to bottom in ten minutes and walk away understanding.&lt;/p&gt;




&lt;h2&gt;
  
  
  What nvim-starter does differently
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. No plugin manager
&lt;/h3&gt;

&lt;p&gt;This is the biggest decision I made, and the one that shapes everything else.&lt;/p&gt;

&lt;p&gt;Kickstart.nvim uses lazy.nvim. lazy.nvim is excellent software — Folke is a brilliant developer, and lazy.nvim rightfully became the standard. But it's an &lt;em&gt;abstraction layer&lt;/em&gt; between you and your plugins. To understand the config, you first have to understand lazy.nvim's spec format: what &lt;code&gt;event = "VeryLazy"&lt;/code&gt; means, how &lt;code&gt;cmd&lt;/code&gt; triggers work, why some plugins use &lt;code&gt;dependencies&lt;/code&gt; and others don't, what the &lt;code&gt;opts&lt;/code&gt; shorthand expands to.&lt;/p&gt;

&lt;p&gt;For a beginner, this is backwards. They should be learning &lt;em&gt;Neovim's&lt;/em&gt; concepts — buffers, windows, keymaps, options, LSP — not a plugin manager's DSL.&lt;/p&gt;

&lt;p&gt;nvim-starter uses &lt;code&gt;vim.pack.add()&lt;/code&gt;, which shipped with Neovim 0.12. You give it a list of GitHub URLs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/folke/tokyonight.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tokyonight.nvim"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/folke/which-key.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"which-key.nvim"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/folke/snacks.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"snacks.nvim"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;-- ...&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;confirm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. There is nothing to learn. Neovim clones these repos into its standard plugin directory, adds them to the runtimepath, and loads them the same way it's loaded plugins for decades. The "plugin manager" is the editor itself. When a beginner reads this block, they see exactly what's happening: here are the plugins, here are their URLs, they get installed automatically.&lt;/p&gt;

&lt;p&gt;No lazy-loading. No event triggers. No &lt;code&gt;after/&lt;/code&gt; directories. Ten plugins load at startup, and with &lt;code&gt;vim.loader.enable()&lt;/code&gt; (bytecode caching introduced in Neovim 0.12), startup time is imperceptible. For a starter config with ten plugins, the complexity of lazy-loading isn't worth the cognitive cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. blink.cmp instead of nvim-cmp
&lt;/h3&gt;

&lt;p&gt;When kickstart.nvim was created, nvim-cmp was the only viable completion engine. It works, but it's a sprawling setup. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nvim-cmp&lt;/code&gt; itself&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmp-nvim-lsp&lt;/code&gt; for LSP completions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmp-buffer&lt;/code&gt; for buffer words&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmp-path&lt;/code&gt; for filesystem paths&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmp_luasnip&lt;/code&gt; for snippets&lt;/li&gt;
&lt;li&gt;A capabilities bridge to wire it into the LSP client&lt;/li&gt;
&lt;li&gt;A formatting function if you want pretty icons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's five plugins and a configuration block that typically runs 40–60 lines.&lt;/p&gt;

&lt;p&gt;blink.cmp — Saghen's Rust-based completion engine — bundles LSP, path, buffer, and snippet sources internally. The entire completion configuration in nvim-starter is 25 lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"blink.cmp"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="n"&gt;keymap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;preset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="n"&gt;sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"lsp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"snippets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"buffer"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="n"&gt;snippets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;preset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"luasnip"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No separate source plugins. No capability bridging (one wildcard LSP config covers it). No formatting function. It's faster at runtime and dramatically simpler to read.&lt;/p&gt;

&lt;p&gt;blink.cmp is younger than nvim-cmp and has a smaller ecosystem, but for the four sources a starter config needs — LSP, path, snippets, buffer — it's the simpler tool. I'll take simpler over battle-tested for something meant to be read and understood before it's used.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. snacks.nvim over telescope (and toggleterm, and neo-tree)
&lt;/h3&gt;

&lt;p&gt;telescope.nvim is a fantastic fuzzy finder. But it's &lt;em&gt;only&lt;/em&gt; a fuzzy finder. If you also want a built-in terminal, you install toggleterm.nvim. A file explorer? neo-tree.nvim or nvim-tree.lua. Each of these has its own configuration syntax, its own keybindings, its own documentation to read.&lt;/p&gt;

&lt;p&gt;Folke's snacks.nvim bundles all three — picker, terminal, explorer — into one plugin with one setup call. In nvim-starter, the entire UI layer is 10 lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"snacks"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="n"&gt;explorer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="n"&gt;terminal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="n"&gt;picker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fuzzy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;smartcase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename_bonus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One plugin to understand instead of three. One set of keybindings to learn. One repo to trust. For a beginner who hasn't yet internalized the difference between a picker, a terminal buffer, and a file tree, this collapsing of concepts is a genuine learning aid.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. No nvim-treesitter — just what Neovim ships
&lt;/h3&gt;

&lt;p&gt;nvim-treesitter is another plugin that's excellent software and adds unnecessary complexity for beginners. It manages parser installations through &lt;code&gt;:TSInstall&lt;/code&gt;, which means you're learning a plugin-specific command before you've learned &lt;code&gt;:help&lt;/code&gt;. It has its own configuration syntax (&lt;code&gt;ensure_installed&lt;/code&gt;, &lt;code&gt;highlight = { enable = true }&lt;/code&gt;). It periodically prompts you about parser updates.&lt;/p&gt;

&lt;p&gt;Neovim 0.12 ships with built-in Treesitter support and includes parsers for C, Lua, Markdown, Vimscript, vimdoc, and Query. That covers the languages most new Neovim users encounter first: Lua for their config, Markdown for notes, and maybe C if they're systems-curious.&lt;/p&gt;

&lt;p&gt;For additional languages, you install parsers through your OS package manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;tree-sitter-python
&lt;span class="nv"&gt;$ &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;tree-sitter-rust
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or via the tree-sitter CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree-sitter &lt;span class="nb"&gt;install &lt;/span&gt;python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Neovim plugin involved. No &lt;code&gt;:TSInstall&lt;/code&gt;. The FileType autocmd in nvim-starter silently skips languages without parsers using &lt;code&gt;pcall&lt;/code&gt; — no errors, no prompts, no confusion. When a beginner eventually installs a parser, highlighting just works.&lt;/p&gt;

&lt;p&gt;This is a deliberate philosophical choice: parser management belongs to the OS, not to your editor's plugin system.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Zero per-server LSP configuration
&lt;/h3&gt;

&lt;p&gt;In most Neovim configs — including kickstart — every language server needs its own setup block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;lspconfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pyright&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;lspconfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rust_analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;lspconfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lua_ls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiply this by however many languages you use, add capability merging and on_attach callbacks, and the LSP section alone can hit a hundred lines.&lt;/p&gt;

&lt;p&gt;nvim-starter takes a different approach. mason-lspconfig's &lt;code&gt;automatic_enable = true&lt;/code&gt; means: if a server binary exists on disk (because the user installed it through Mason's UI), start it automatically. No per-server blocks. No boilerplate.&lt;/p&gt;

&lt;p&gt;Capabilities for blink.cmp are merged once, globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lsp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;capabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"blink.cmp"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;get_lsp_capabilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One line. Every server, present and future, gets completion, signature help, and snippet capabilities. When I install &lt;code&gt;pyright&lt;/code&gt; in Mason, it works. When I install &lt;code&gt;rust_analyzer&lt;/code&gt;, it works. There is nothing to write, nothing to maintain, nothing to explain.&lt;/p&gt;

&lt;p&gt;For beginners, this transforms the LSP experience from "read the lspconfig docs for your language" to "open Mason, press &lt;code&gt;i&lt;/code&gt; on the server you want, restart neovim." That's the level of friction I wanted.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Single-file, by design
&lt;/h3&gt;

&lt;p&gt;Kickstart.nvim starts as a single file but encourages modularization — its README suggests splitting into &lt;code&gt;lua/plugins/&lt;/code&gt;, &lt;code&gt;lua/opts/&lt;/code&gt;, &lt;code&gt;lua/keymaps/&lt;/code&gt;. This is good practice for a growing config, but it's also the moment a beginner's understanding fragments. Suddenly the colorscheme is in one file, keymaps in another, and LSP config in a third, connected through &lt;code&gt;require()&lt;/code&gt; calls that assume you understand Lua's module system.&lt;/p&gt;

&lt;p&gt;nvim-starter's CONTRIBUTING.md states it plainly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Stay single-file.&lt;/strong&gt; The whole point is a single &lt;code&gt;init.lua&lt;/code&gt; with comments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The entire config is 363 lines, organized into 16 numbered sections. It starts with a comment block telling you the three most common tweaks (colorscheme, indent size, plugin list) and their line numbers. Section 0 enables the loader. Section 1 sets the leader key. Section 2 declares plugins. And so on, linearly, until section 16 enables Treesitter.&lt;/p&gt;

&lt;p&gt;You read it top to bottom. You understand it. Then you fork it, rename it, and build your own. nvim-starter isn't a framework you extend — it's a reference implementation you learn from and outgrow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I chose these specific plugins
&lt;/h2&gt;

&lt;p&gt;Every plugin in nvim-starter passed a simple test: &lt;em&gt;is this essential for a beginner, and is it the simplest implementation of what it does?&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;th&gt;Why this one&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;tokyonight.nvim&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dark theme, well-maintained, widely used. Gruvbox is commented-out as an alternative on the very next line.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;which-key.nvim&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shows available keybindings when you pause on &lt;code&gt;&amp;lt;Space&amp;gt;&lt;/code&gt;. Beginners don't memorize keymaps — they discover them.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;snacks.nvim&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One plugin replaces three (fuzzy finder, terminal, explorer). Less to install, less to configure, less to read.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;mason.nvim&lt;/strong&gt; + &lt;strong&gt;mason-lspconfig.nvim&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;GUI server installer + auto-wiring. Beginners shouldn't need to know where binaries live or how &lt;code&gt;cmd&lt;/code&gt; tables work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;nvim-lspconfig&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The standard LSP configuration library. Still needed for server-specific defaults, even with &lt;code&gt;automatic_enable&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;blink.cmp&lt;/strong&gt; + &lt;strong&gt;blink.lib&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Rust-based completion that bundles its sources. Faster and simpler than nvim-cmp's source-plugin ecosystem.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;gitsigns.nvim&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Git gutter markers. Beginners use Git. Seeing what changed is immediately useful.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;guess-indent.nvim&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-detects indentation per file. Beginners open files from projects they didn't create — this saves them from mixing tabs and spaces.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LuaSnip&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snippet expansion. Powers the snippet source in blink.cmp. The only plugin with a build hook (compiles its regex engine on install).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's 10 plugins, 11 if you count blink.lib (a dependency of blink.cmp). No file tree, no statusline plugin, no debug adapter, no auto-formatter beyond LSP formatting. Each omission is documented in &lt;code&gt;docs/plugins.md&lt;/code&gt; with recommendations if you want to add them later.&lt;/p&gt;




&lt;h2&gt;
  
  
  What nvim-starter doesn't try to be
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It's not your forever-config.&lt;/strong&gt; It's deliberately undersized. Once you're comfortable with Neovim, you'll want things it doesn't include — a statusline, a debug adapter, auto-formatting on save, session management. That's by design. nvim-starter gets you to the point where you &lt;em&gt;know&lt;/em&gt; what you want to add, which is the real goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's not modular.&lt;/strong&gt; There are no &lt;code&gt;lua/&lt;/code&gt; subdirectories, no &lt;code&gt;require()&lt;/code&gt; chains, no plugin specs split across files. This is a constraint, not an oversight. Modularity is the right call for a configuration you'll maintain for years — but it's the wrong call for a configuration meant to be read in one sitting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's not version-agnostic.&lt;/strong&gt; nvim-starter requires Neovim ≥ 0.12. This is a hard requirement and I'm comfortable with it. &lt;code&gt;vim.pack.add()&lt;/code&gt; and native Treesitter are the right primitives for a beginner config, and they didn't exist before 0.12. Ubuntu 24.04 LTS ships Neovim 0.9.5, so you'll need a PPA, AppImage, or manual build. I think the trade-off — a simpler config that leverages editor-native features — is worth the install step. If Neovim 0.12 isn't available to you, use kickstart.nvim instead.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you get in five minutes
&lt;/h2&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/Mvzundert/nvim-starter/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a file. Plugins clone for ~30 seconds. Then:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You get&lt;/th&gt;
&lt;th&gt;Press&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keybinding cheat sheet&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;Space&amp;gt;&lt;/code&gt; and wait&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fuzzy file finder&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;sf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content search (grep)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;sg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LSP server installer (GUI)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;cm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal toggle&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;tt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File explorer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;e&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go-to-definition&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gd&lt;/code&gt; (with LSP attached)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hover docs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;K&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rename symbol&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;rn&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code actions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;ca&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto-completion&lt;/td&gt;
&lt;td&gt;Just type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Format buffer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Space&amp;gt;f&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Install a language server by opening Mason (&lt;code&gt;&amp;lt;Space&amp;gt;cm&lt;/code&gt;), pressing &lt;code&gt;2&lt;/code&gt; for LSP servers, searching for your language, and pressing &lt;code&gt;i&lt;/code&gt;. Reopen your file. Autocompletion, go-to-definition, and diagnostics all work. No config written. No docs read. Just a working IDE.&lt;/p&gt;




&lt;h2&gt;
  
  
  The trade-offs I'm comfortable with
&lt;/h2&gt;

&lt;p&gt;Every design decision is a trade-off. Here are the ones I made and why I stand by them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neovim ≥ 0.12 only.&lt;/strong&gt; Yes, this excludes stable-distribution users. But &lt;code&gt;vim.pack.add()&lt;/code&gt; eliminates the plugin manager abstraction entirely. That single simplification justifies the version requirement. Beginners installing Neovim fresh aren't tied to a distro package anyway — they're following a "how to install Neovim" tutorial that gives them the latest version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No lazy-loading.&lt;/strong&gt; Ten plugins load at startup. On any machine built in the last decade, with &lt;code&gt;vim.loader.enable()&lt;/code&gt; caching bytecode, this is under 50 milliseconds. The cognitive cost of explaining lazy-loading to a beginner vastly outweighs the performance gain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;blink.cmp instead of nvim-cmp.&lt;/strong&gt; blink.cmp is newer and has a smaller plugin ecosystem. But a beginner doesn't need custom completion sources — they need LSP completions, buffer words, and file paths. blink.cmp does all three out of the box with a 25-line config. If they eventually need a source blink.cmp doesn't support, they'll have learned enough to evaluate nvim-cmp themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No &lt;code&gt;:LspInfo&lt;/code&gt;.&lt;/strong&gt; Neovim 0.12 replaced &lt;code&gt;:LspInfo&lt;/code&gt; with &lt;code&gt;:checkhealth vim.lsp&lt;/code&gt;. This is documented in the README and in the inline comments, but I know it will trip up users following older tutorials. It's a Neovim upstream decision I can't control, and I think documenting it clearly is sufficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Built-in Treesitter requires extra steps for more languages.&lt;/strong&gt; If you work in Python, Rust, Go, TypeScript, Bash, and ten other languages, installing parsers through your package manager is an extra step per language. nvim-treesitter's &lt;code&gt;:TSInstall all&lt;/code&gt; is genuinely more convenient for polyglots. But nvim-starter is for beginners — beginners typically work in one or two languages. Installing one or two tree-sitter packages isn't a meaningful burden, and avoiding nvim-treesitter keeps the plugin count down and the mental model simple.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why you might choose nvim-starter over kickstart.nvim
&lt;/h2&gt;

&lt;p&gt;Use nvim-starter if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You're new to Neovim and want to understand your config.&lt;/strong&gt; Kickstart works, but it's hard to read. nvim-starter is 363 lines of commented Lua that tells you exactly what every line does and why it's there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You don't want to learn a plugin manager before learning Neovim.&lt;/strong&gt; lazy.nvim is powerful, but it's an abstraction. nvim-starter uses &lt;code&gt;vim.pack.add()&lt;/code&gt; — there is no plugin manager to learn because the editor &lt;em&gt;is&lt;/em&gt; the plugin manager.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want to get productive in five minutes, not five hours.&lt;/strong&gt; Install, launch, install one LSP server, start coding. That's the workflow. There's no config to write.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You learn by reading working code.&lt;/strong&gt; nvim-starter is a reference implementation. Read it top to bottom. Then delete it and write your own — you'll know enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You prefer smaller dependency trees.&lt;/strong&gt; Fewer plugins, fewer repositories to trust, fewer version interactions to debug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stick with kickstart.nvim if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need Neovim ≥ 0.9 compatibility (Ubuntu LTS, Debian stable, RHEL).&lt;/li&gt;
&lt;li&gt;You want lazy-loading and fine-grained startup control.&lt;/li&gt;
&lt;li&gt;You want nvim-cmp's mature plugin ecosystem.&lt;/li&gt;
&lt;li&gt;You want &lt;code&gt;:TSInstall&lt;/code&gt; convenience for dozens of languages.&lt;/li&gt;
&lt;li&gt;You want a config you can grow modularly without rewriting from scratch.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;I built nvim-starter because I believe the first Neovim configuration a beginner sees should be legible. They should be able to read it in one sitting, understand what every section does, and feel confident tweaking it. The plugins should auto-install without a plugin manager. The LSP should auto-wire without per-server configuration. The code should document itself.&lt;/p&gt;

&lt;p&gt;Kickstart.nvim is a launchpad. nvim-starter is a tutorial that happens to give you a working IDE.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/Mvzundert/nvim-starter" rel="noopener noreferrer"&gt;github.com/Mvzundert/nvim-starter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt; Neovim ≥ 0.12, Git, Nerd Font (optional)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/p&gt;

</description>
      <category>nvim</category>
      <category>lua</category>
      <category>learning</category>
      <category>developerlife</category>
    </item>
  </channel>
</rss>
