feat: replace npm live-server with pure-Lua HTTP server#29
Merged
barrettruth merged 23 commits intomainfrom Mar 3, 2026
Merged
feat: replace npm live-server with pure-Lua HTTP server#29barrettruth merged 23 commits intomainfrom
barrettruth merged 23 commits intomainfrom
Conversation
Problem: the plugin required users to install Node.js and the live-server npm package globally, adding a heavyweight external dependency for a simple dev-server workflow. Solution: implement an HTTP server entirely in Lua using vim.uv (libuv bindings). The new server handles static file serving, SSE-based live reload, CSS hot-swap, directory listings, and file watching with debounce — all with zero external dependencies. Minimum Neovim version bumped to 0.10. Old args-based config is migrated with a deprecation warning.
Problem: only --port and --no-browser were migrated from the old args config. Users with --wait, --ignore, or --no-css-inject would lose their settings silently. Unsupported flags were also silently dropped. Solution: migrate --wait to debounce, --ignore to ignore (split on comma), and --no-css-inject to css_inject. Warn on unsupported flags (--host, --cors, --spa, etc). Add css_inject config field that controls whether CSS changes hot-swap or trigger a full reload. Format all deprecation and warning messages with backticks.
Problem: the pure-Lua server uses vim.uv and vim.ui.open which don't exist before Neovim 0.10. Loading the plugin on older versions produces a cryptic Lua traceback. Solution: check nvim-0.10 at the top of the plugin file and bail with a clear ErrorMsg directing users to pin v0.1.6 or upgrade. No commands are registered and no modules are required, preventing any crash.
672aba4 to
06a16de
Compare
Problem: hot-reload failures are silent — there's no way to tell which step in the fs_event → debounce → reload → SSE broadcast chain is breaking without manually adding print statements. Solution: add a `debug` boolean to the config (default false). When enabled, a `dbg` helper logs each critical step via vim.notify at DEBUG level: fs_event firing, ignore checks, CSS detection, debounce callback, reload dispatch, SSE broadcast, and client connect/disconnect.
Closed
6616a24 to
9419943
Compare
Problem: selene's deprecated TOML std format doesn't support the lua_versions field, so the parser defaults to Lua 5.1 and rejects \z string escapes used in server.lua HTTP response builders. Solution: convert vim.toml to vim.yaml with lua_versions: [luajit], enabling LuaJIT parser mode. Add bad_string_escape = "allow" to selene.toml to suppress a known false positive where the lint only whitelists \z for roblox mode, not the actual lua version.
Problem: lua-typecheck-action fails with undefined-global jit (guarded behind a LuaJIT preprocessor flag in lua-ls), undefined-doc-name for uv_tcp_t/uv_timer_t/uv_fs_event_t, and cascading undefined-field errors for close/is_closing. The type annotations used unprefixed names but LuaCATS/luv defines them as uv.uv_tcp_t etc. Solution: set runtime.version to LuaJIT in .luarc.json to enable the jit builtin, and update all type annotations in server.lua to use the uv.-prefixed class names matching the LuaCATS/luv definitions.
Problem: lua-language-server is not available in the dev shell, making it impossible to run local type checks. Solution: add lua-language-server to the devShell packages.
Problem: no way to verify plugin requirements or detect deprecated config without hitting runtime errors. Solution: add lua/live-server/health.lua for :checkhealth, reporting on Neovim version, vim.uv availability, deprecated args config, and presence of the now-unnecessary npm live-server package.
Problem: the runtime notification about missing recursive file watching on Linux fires every session, annoying users about something they cannot change. Solution: remove the runtime vim.notify and surface the limitation through :checkhealth instead, where users discover it on their terms.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The plugin requires users to install Node.js and the
live-servernpmpackage globally. This is a heavyweight external dependency for what
amounts to a simple local dev-server workflow, and it creates friction
for users who don't otherwise need Node.js.
Solution
Replace the npm shell-out with a pure-Lua HTTP server built on
vim.uv(libuv bindings), eliminating all external dependencies. The new server
supports static file serving, SSE-based live reload, CSS hot-swap
without full page reload, directory listings, and recursive file
watching with configurable debounce.
Minimum Neovim version is bumped to 0.10 for
vim.uvandvim.ui.open.The old
args-based config is automatically migrated with a deprecationwarning.
Closes #28.