See React/RSC 'use client' boundaries at the call site.
Inspired by the VS Code extension RSC Boundary Marker, brought to Neovim.
If this helps, please ⭐ star the repo!
- Detects components that declare
'use client'. - Shows a right-aligned
'use client'marker as virtual text next to each JSX usage. - Auto-watches buffers to keep markers in sync (or use a manual refresh).
- Handles default / named / aliased imports and directory imports resolving to
index.
With lazy.nvim:
{
"Kenzo-Wada/boundary.nvim",
branch = "release",
opts = {
auto = true, -- automatic refresh enabled by default
-- marker_text = "'use client'",
},
}Manual refresh:
:BoundaryRefreshWorks with any plugin manager. Once on your runtimepath, just:
require("boundary").setup()All options are optional; sensible defaults are provided.
require("boundary").setup({ ... }) accepts:
| Option | Type | Default | Description |
|---|---|---|---|
marker_text |
string |
'use client' |
Virtual text displayed next to each matching JSX usage. |
marker_hl_group |
string |
BoundaryMarker |
Highlight group for the marker (links to Comment by default). |
hover_only |
boolean |
false |
Only display markers when the cursor is on the matching line. |
directives |
string[] |
{ "'use client'", '"use client"' } |
Directive strings recognized in imported files. |
search_extensions |
string[] |
{ ".tsx", ".ts", ".jsx", ".js" } |
File extensions tried when resolving bare relative imports. |
filetypes |
string[] |
{ "javascript", "javascriptreact", "typescript", "typescriptreact" } |
Filetypes that trigger scanning. |
max_read_bytes |
number |
4096 |
Max bytes read from each import when scanning for directives. |
auto |
boolean |
true |
Enable automatic refresh via autocommands. |
events |
string[] |
{ "BufEnter", "BufWritePost", "TextChanged", "InsertLeave" } |
Events used to refresh when auto is true. |
- Import a local component in a supported React file (
.tsx,.jsx, …). - Ensure the component’s file begins with a
'use client'(or"use client"). - Edit or save (with
auto = true) or run:BoundaryRefreshto populate markers.
// components/Button.tsx
"use client";
export default function Button() {
return <button>Click me</button>;
}
// app/page.tsx
import Button from "../components/Button";
export default function Page() {
return (
<div>
<Button /> 'use client' // boundary.nvim shows virtual text here
</div>
);
}Default events:
BufEnter— when entering a bufferBufWritePost— after savingTextChanged/InsertLeave— during edits / leaving insert mode
Tune this list to balance responsiveness and cost.
:BoundaryRefresh— Re-scan the current buffer.
Issues and PRs are welcome!
We label good first issue to help newcomers get started.
MIT