[{"data":1,"prerenderedAt":599},["ShallowReactive",2],{"blog-neovim-config":3},{"id":4,"title":5,"body":6,"date":585,"description":586,"extension":587,"featured":588,"meta":589,"navigation":590,"part":572,"path":591,"seo":592,"series":20,"stem":593,"tags":594,"tldr":597,"__hash__":598},"blog\u002Fblog\u002Fneovim-config.md","My Neovim Config (and How It Actually Works)",{"type":7,"value":8,"toc":570},"minimark",[9,22,27,46,51,62,84,87,91,98,112,118,132,158,172,193,234,244,253,263,273,303,313,333,337,344,348,375,379,386,438,442,445,449,452,495,514,518,543,550],[10,11,12],"p",{},[13,14,15,16,21],"em",{},"This is Part 2 of the ",[17,18,20],"a",{"href":19},"\u002Fblog\u002Fneovim-motions","Neovim Guide",". If you haven't read Part 1 on why Vim motions are worth learning, start there.",[23,24,26],"h2",{"id":25},"my-config-where-kickstart-ended-and-opinions-began","My Config: Where Kickstart Ended and Opinions Began",[10,28,29,30,36,37,41,42],{},"My ",[17,31,35],{"href":32,"rel":33},"https:\u002F\u002Fgithub.com\u002Flubasinkal\u002Fnvim",[34],"nofollow","nvim config"," started from kickstart, but it's evolved into something more structured. It's modularised now — not the single-file approach anymore. The config lives in ",[38,39,40],"code",{},"lua\u002Fcustom\u002F"," with separate directories for plugins, LSP, and utilities. The philosophy is still the same though: ",[43,44,45],"strong",{},"if I don't use it, it's gone. If I can't explain what a line does, it doesn't belong.",[47,48,50],"h3",{"id":49},"the-structure","The Structure",[10,52,53,54,57,58,61],{},"The entry point is still one ",[38,55,56],{},"init.lua",", but it's lean. It loads keymaps and options immediately, defers the statusline until the first buffer opens, and lazy-loads utility modules (floating terminal, sessions, tabs) in the background. Then it bootstraps ",[38,59,60],{},"lazy.nvim"," and loads plugins from two directories:",[63,64,65,72,78],"ul",{},[66,67,68,71],"li",{},[38,69,70],{},"lua\u002Fcustom\u002Fplugins\u002F"," — one file per plugin or plugin group",[66,73,74,77],{},[38,75,76],{},"lua\u002Fcustom\u002Flsp\u002F"," — LSP config, autocomplete, and formatting",[66,79,80,83],{},[38,81,82],{},"lua\u002Fcustom\u002Futil\u002F"," — floating terminal, session management, tabs",[10,85,86],{},"Everything is lazy-loaded by default. A plugin only loads when you actually trigger it. Startup is fast because nothing is loaded until you need it.",[47,88,90],{"id":89},"plugins-whats-actually-in-there","Plugins (What's Actually In There)",[10,92,93,94,97],{},"Let me walk through what I'm running and ",[13,95,96],{},"why"," — because every plugin earns its spot.",[10,99,100,103,104,107,108,111],{},[43,101,102],{},"Fzf-lua"," — The fuzzy finder. Files, grep, buffers, git commits, diagnostics, help tags — everything goes through Fzf-lua. It's fast and vim's built-in code action menus use the Fzf-lua UI instead of that ugly default popup. Keybindings are all under ",[38,105,106],{},"\u003Cleader>s"," for search and ",[38,109,110],{},"\u003Cleader>g"," for git.",[10,113,114,117],{},[43,115,116],{},"Treesitter"," — Syntax highlighting that actually understands your code. Instead of regex (which is like reading a book one letter at a time), Treesitter parses your code into a tree structure. Highlighting, indentation, and code context all make sense now. Auto-installs parsers for whatever language you open.",[10,119,120,123,124,127,128,131],{},[43,121,122],{},"Flash"," — Press ",[38,125,126],{},"s"," and type a few characters — every match on screen gets a label. Type the label, you're there. It's like easymotion but actually good. Works in normal, visual, and operator-pending modes. ",[38,129,130],{},"S"," does the same thing but for Treesitter nodes, so you can jump to specific code structures.",[10,133,134,137,138,142,143,142,146,149,150,153,154,157],{},[43,135,136],{},"Blink.cmp"," — Autocomplete engine. I switched from nvim-cmp to blink because it's faster and the config is cleaner. Sources are LSP, path, snippets, and buffer. Completion menu shows the source (",[139,140,141],"span",{},"lsp",", ",[139,144,145],{},"snip",[139,147,148],{},"buf",") so you know where suggestions come from. Auto-brackets are enabled. ",[38,151,152],{},"Tab"," and ",[38,155,156],{},"Shift-Tab"," cycle through completions and jump snippets.",[10,159,160,163,164,167,168,171],{},[43,161,162],{},"Conform"," — Formatter. Runs on save. ",[38,165,166],{},"stylua"," for Lua, ",[38,169,170],{},"biome"," for JavaScript\u002FTypeScript\u002FVue\u002FHTML\u002FCSS\u002FJSON. No config files to maintain — it just works.",[10,173,174,177,178,153,181,184,185,188,189,192],{},[43,175,176],{},"Gitsigns"," — Git diff indicators in the gutter. But the real killer feature is inline blame — every line shows who last touched it and when. ",[38,179,180],{},"]c",[38,182,183],{},"[c"," jump between hunks. ",[38,186,187],{},"\u003Cleader>hs"," stages a hunk. ",[38,190,191],{},"\u003Cleader>hp"," previews it. Full git workflow without leaving the buffer.",[10,194,195,198,199,202,203,206,207,210,211,210,214,217,218,221,222,225,226,229,230,233],{},[43,196,197],{},"Mini.nvim"," — A bundle of small, focused plugins. I use: ",[38,200,201],{},"mini.pairs"," (auto-close brackets), ",[38,204,205],{},"mini.surround"," (add\u002Fdelete\u002Freplace surrounds with ",[38,208,209],{},"gsa","\u002F",[38,212,213],{},"gsd",[38,215,216],{},"gsr","), ",[38,219,220],{},"mini.ai"," (enhanced text objects), ",[38,223,224],{},"mini.comment"," (toggle comments), ",[38,227,228],{},"mini.indentscope"," (visual indent guides), and ",[38,231,232],{},"mini.notify"," (clean notification popups). One import, six plugins, zero bloat.",[10,235,236,239,240,243],{},[43,237,238],{},"Which-key"," — Shows available keybindings as you press them. Uses the ",[38,241,242],{},"helix"," preset for a clean popup. This is how you learn your own config without memorising everything upfront.",[10,245,246,123,249,252],{},[43,247,248],{},"Oil.nvim",[38,250,251],{},"-"," and you get a file browser that works like a buffer. Rename files by editing text. Create files by typing a new line. Delete by removing the line. It's the most intuitive file manager I've used.",[10,254,255,258,259,262],{},[43,256,257],{},"Neo-tree"," — Toggle with ",[38,260,261],{},"\u003Cleader>e",". Opens on the right side. I use Oil more, but Neo-tree is there for when I want a visual overview of the project structure.",[10,264,265,268,269,272],{},[43,266,267],{},"Render-markdown"," — When you open a ",[38,270,271],{},".md"," file, it renders headings, checkboxes, code blocks, and inline formatting with proper styling. Writing markdown in Neovim finally looks good.",[10,274,275,278,279,142,282,142,285,142,288,291,292,153,295,298,299,302],{},[43,276,277],{},"Todo-comments"," — Highlights ",[38,280,281],{},"TODO",[38,283,284],{},"FIXME",[38,286,287],{},"HACK",[38,289,290],{},"NOTE"," in your code. ",[38,293,294],{},"]t",[38,296,297],{},"[t"," jump between them. ",[38,300,301],{},"\u003Cleader>st"," searches all todos across the project via Telescope.",[10,304,305,308,309,312],{},[43,306,307],{},"ts-autotag"," — Auto-closes and renames HTML\u002FJSX tags. Type ",[38,310,311],{},"\u003Cdiv>"," and the closing tag appears. Rename the opening tag, the closing tag updates. Small thing, big quality of life.",[10,314,315,318,319,167,322,325,326,328,329,332],{},[43,316,317],{},"LSP (nvim-lspconfig + Mason)"," — ",[38,320,321],{},"lua_ls",[38,323,324],{},"ts_ls"," for TypeScript\u002FJavaScript (with Vue support via the Vue language server plugin), ",[38,327,166],{}," for formatting. Mason auto-installs what's needed. ",[38,330,331],{},"fidget.nvim"," shows LSP progress in the corner so you know when the server is doing something.",[47,334,336],{"id":335},"hand-built-statusline-no-plugin-needed","Hand-Built Statusline (No Plugin Needed)",[10,338,339,340,343],{},"I don't use lualine or any statusline plugin. It's a hand-written Lua function in ",[38,341,342],{},"statusline.lua"," that renders directly into Neovim's native statusline. Shows the mode (colour-coded — violet for normal, blue for insert, cyan for visual), git branch (from gitsigns), diagnostics count, current file, LSP client name, filetype, line\u002Fcolumn, and scroll percentage. About 150 lines of Lua. No dependencies. Loads after the first buffer to save ~5-10ms on startup.",[47,345,347],{"id":346},"custom-utilities","Custom Utilities",[63,349,350,363,369],{},[66,351,352,318,355,358,359,362],{},[43,353,354],{},"Floating terminal",[38,356,357],{},"\u003Cleader>tt"," toggles a floating terminal at 80% of the editor size. Reuses the same buffer. Auto-closes when the shell exits. ",[38,360,361],{},"Esc Esc"," exits terminal mode.",[66,364,365,368],{},[43,366,367],{},"Sessions"," — Auto-saves and restores your session so you pick up where you left off.",[66,370,371,374],{},[43,372,373],{},"Tabs"," — Better tab\u002Fbuffer management.",[47,376,378],{"id":377},"sensible-defaults-the-boring-stuff-that-matters","Sensible Defaults (The Boring Stuff That Matters)",[10,380,381,382,385],{},"A few things in ",[38,383,384],{},"options.lua"," that make a real difference:",[63,387,388,391,397,400,410,413,416,426,432],{},[66,389,390],{},"Relative line numbers — you know how far away things are",[66,392,393,396],{},[38,394,395],{},"scrolloff = 10"," — keeps the cursor 10 lines from the edge so context is always visible",[66,398,399],{},"Transparent background — the editor background matches your terminal",[66,401,402,405,406,409],{},[38,403,404],{},"cmdheight = 0"," — hides the command line until you press ",[38,407,408],{},":",", gives you an extra line of code",[66,411,412],{},"Cursorline only in the active window — the focused window has a highlighted line, others don't",[66,414,415],{},"Smooth scrolling — because why not",[66,417,418,421,422,425],{},[38,419,420],{},"; as :"," — press ",[38,423,424],{},";"," to enter command mode. One less keypress every time.",[66,427,428,431],{},[38,429,430],{},"Alt+j\u002Fk"," to move lines up\u002Fdown — because sometimes you just need to reorder things fast",[66,433,434,437],{},[38,435,436],{},"Ctrl+d\u002Fu"," centres after half-page jump — no more losing your cursor",[47,439,441],{"id":440},"disabled-built-in-plugins","Disabled Built-In Plugins",[10,443,444],{},"Neovim ships with plugins most people never use. I disable: gzip, tar, zip, netrw, tohtml, matchit, matchparen, rplugin, editorconfig, man, and spellfile. Each one is a tiny startup cost that adds up. If I need them, I can re-enable them. So far, I haven't.",[47,446,448],{"id":447},"how-it-can-help-you-if-youre-new","How It Can Help You If You're New",[10,450,451],{},"If you're just starting to code, here's what this config gives you out of the box:",[63,453,454,460,466,472,478,484,490],{},[66,455,456,459],{},[43,457,458],{},"Autocomplete"," that actually works without being annoying",[66,461,462,465],{},[43,463,464],{},"Errors highlighted"," in real-time so you catch mistakes before running the code",[66,467,468,471],{},[43,469,470],{},"Fast file navigation"," — no more scrolling through a file tree, just fuzzy search",[66,473,474,477],{},[43,475,476],{},"Git integration"," built right into the editor — blame, stage, diff, without leaving your code",[66,479,480,483],{},[43,481,482],{},"A statusline that tells you everything"," — mode, branch, errors, file, position",[66,485,486,489],{},[43,487,488],{},"A floating terminal"," — run commands without leaving Neovim",[66,491,492,494],{},[43,493,238],{}," — shows you what keybindings are available as you press keys",[10,496,497,498,501,502,505,506,509,510,513],{},"You don't need to understand everything on day one. Clone the config, open Neovim, start writing code. Which-key will guide you. Learn the motions as you go. ",[38,499,500],{},"i"," to insert, ",[38,503,504],{},"Esc"," to go back to normal mode, ",[38,507,508],{},":w"," to save, ",[38,511,512],{},":q"," to quit. That's enough to get started. The rest comes naturally.",[23,515,517],{"id":516},"the-how-do-i-exit-vim-section","The \"How Do I Exit Vim\" Section",[10,519,520,521,523,524,527,528,531,532,535,536,539,540,542],{},"Just kidding. It's ",[38,522,512],{},". Or ",[38,525,526],{},":wq"," to save and quit. Or ",[38,529,530],{},"ZZ"," if you're feeling fancy. Or ",[38,533,534],{},":qa!"," if you're having a mental breakdown. Or ",[38,537,538],{},"\u003Cleader>x"," in my config because I got tired of typing ",[38,541,526],{}," like a caveman.",[10,544,545,546,549],{},"In all seriousness — the learning curve is real, but it's front-loaded. You struggle for a week, then you're productive, then you're faster than you were before, and you never look back. It's like learning to ride a bike. Except the bike is your text editor, and falling down is accidentally deleting 47 lines with ",[38,547,548],{},"dG",".",[10,551,552,553,557,558,563,564,569],{},"If you want a starting point, ",[17,554,556],{"href":32,"rel":555},[34],"my config"," is on GitHub. ",[17,559,562],{"href":560,"rel":561},"https:\u002F\u002Fgithub.com\u002Fnvim-lua\u002Fkickstart.nvim",[34],"Kickstart.nvim"," is where it all began — and ",[17,565,568],{"href":566,"rel":567},"https:\u002F\u002Fyoutu.be\u002Fm8C0Cq9Uv9o",[34],"this video"," is the best walkthrough I've found for getting started from scratch.",{"title":571,"searchDepth":572,"depth":572,"links":573},"",2,[574,584],{"id":25,"depth":572,"text":26,"children":575},[576,578,579,580,581,582,583],{"id":49,"depth":577,"text":50},3,{"id":89,"depth":577,"text":90},{"id":335,"depth":577,"text":336},{"id":346,"depth":577,"text":347},{"id":377,"depth":577,"text":378},{"id":440,"depth":577,"text":441},{"id":447,"depth":577,"text":448},{"id":516,"depth":572,"text":517},"2026-03-21","A deep dive into a modular Neovim configuration, exploring the power of Vim motions, lazy-loading plugins, and building a high-efficiency development environment.","md",false,{},true,"\u002Fblog\u002Fneovim-config",{"title":5,"description":586},"blog\u002Fneovim-config",[595,596],"editor","productivity","Inside my modular Neovim config: lazy-loading plugins, LSP setup, a hand-written statusline, floating terminal, session management, and the sensible defaults that make it all work. No bloat, no black magic.","9goe4zwZWW-DXKxeprZOSaedTgya6Hps8HOTqI-bArM",1784119588567]