Neovim Plugin
Vue Native provides an official Neovim plugin with LuaSnip snippets, nvim-cmp completions, and custom diagnostics for .vue and .ts files.
Installation
The plugin lives at tools/nvim-plugin/ inside the monorepo, not at the repo root, so a plugin manager cannot resolve it from the repo slug alone. Clone the repo once, then point your manager at that subdirectory.
git clone https://github.com/abdul-hamid-achik/vue-native \
~/.local/share/vue-native-src
lazy.nvim (recommended)
{
dir = vim.fn.expand('~/.local/share/vue-native-src/tools/nvim-plugin'),
name = 'vue-native',
config = function()
require('vue-native').setup()
end,
ft = { 'vue', 'typescript' },
dependencies = {
'L3MON4D3/LuaSnip',
'hrsh7th/nvim-cmp',
},
}
packer.nvim
use {
'~/.local/share/vue-native-src/tools/nvim-plugin',
config = function()
require('vue-native').setup()
end,
ft = { 'vue', 'typescript' },
requires = {
'L3MON4D3/LuaSnip',
'hrsh7th/nvim-cmp',
},
}
Manual (no plugin manager)
Symlink it into Neovim's native package path:
mkdir -p ~/.config/nvim/pack/plugins/start
ln -s ~/.local/share/vue-native-src/tools/nvim-plugin \
~/.config/nvim/pack/plugins/start/vue-native
That is the whole install. plugin/vue-native.vim calls require('vue-native').setup() on VimEnter, so no init.lua line is needed. Add one only if you want to pass options:
require('vue-native').setup()
Configuration
require('vue-native').setup({
snippets = true, -- LuaSnip snippets (default: true)
completions = true, -- nvim-cmp source (default: true)
diagnostics = true, -- vim.diagnostic warnings (default: true)
})
Features
Snippets
Over 70 LuaSnip snippets for components, composables, navigation, and scaffolds. All prefixed with vn-.
Type a prefix and press your LuaSnip expand key (usually <Tab>) to expand. Use <Tab> and <S-Tab> to jump between tabstops. Choice nodes (marked with c()) can be cycled with your configured LuaSnip choice key.
Scaffold snippets:
| Prefix | Output |
|---|---|
vn-app | Full app scaffold with SafeArea, styles, and script setup |
vn-screen | Screen component with useRoute and createStyleSheet |
vn-main | main.ts entry point with createApp, createRouter, and start() |
vn-config | vue-native.config.ts with iOS and Android configuration |
Component snippets:
| Prefix | Component |
|---|---|
vn-view | VView |
vn-text | VText |
vn-button | VButton with onPress |
vn-input | VInput with v-model |
vn-image | VImage with source and resizeMode |
vn-scrollview | VScrollView |
vn-list | VList with :data and :keyExtractor |
vn-safearea | VSafeArea |
vn-switch | VSwitch |
vn-slider | VSlider |
vn-modal | VModal |
vn-alert | VAlertDialog |
vn-actionsheet | VActionSheet |
vn-webview | VWebView |
vn-checkbox | VCheckbox |
vn-radio | VRadio |
vn-dropdown | VDropdown |
vn-video | VVideo |
VList has no renderItem prop
VList renders each row through its #item scoped slot. renderItem is the React Native idiom — in this framework it belongs to VFlatList, not VList. If your vn-list / vn-list-template expansion contains :renderItem="...", delete it: VList ignores that prop and every row renders blank. Use the slot form instead:
<VList :data="items" :keyExtractor="(item) => item.id">
<template #item="{ item }">
<VView :style="styles.item">
<VText>{{ item.title }}</VText>
</VView>
</template>
</VList>
Composable snippets:
| Prefix | Composable |
|---|---|
vn-haptics | useHaptics |
vn-storage | useAsyncStorage |
vn-clipboard | useClipboard |
vn-animation | useAnimation |
vn-http | useHttp |
vn-camera | useCamera |
vn-websocket | useWebSocket |
vn-database | useDatabase |
See the full list in the plugin README.
Completions
The plugin registers a custom vue_native source for nvim-cmp. Add it to your cmp sources:
require('cmp').setup({
sources = {
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
{ name = 'vue_native' },
},
})
The completion source provides:
- Component names when typing
<Vin a template section - Component props when typing after a component tag (e.g.,
<VButton) - Composable names when typing
usein a script section
Each completion item includes documentation with type information and usage examples.
Diagnostics
The plugin uses vim.diagnostic to show real-time warnings for common Vue Native mistakes:
| Pattern | Severity | Message |
|---|---|---|
app.mount() | Error | Use app.start() instead |
v-for in VList | Warning | Use :data and #item slot |
import from 'vue' | Hint | Import from @thelacanians/vue-native-runtime |
Both @press="handler" and :onPress="handler" are valid. The plugin does not warn on @press.
Diagnostics appear inline and in the diagnostics list (:lua vim.diagnostic.setloclist()).
Language server (LSP)
This plugin provides snippets, completions, and diagnostics, but full language support (template type checking, hover, go-to-definition) comes from the Vue language server. Vue Native ships GlobalComponents types for every built-in component, so Volar resolves <VView>, <VButton>, etc. with no extra configuration:
-- with nvim-lspconfig
vim.lsp.enable('vueols') -- .vue files
vim.lsp.enable('ts_ls') -- .ts files
Open Neovim at the project root so the servers can find node_modules (the scaffold installs vue and typescript for you). See the TypeScript guide for details.
Requirements
- Neovim 0.8+
- LuaSnip — for snippet expansion
- nvim-cmp — for completion menu
- Vue language server — for full LSP support in
.vuefiles
Related
- VS Code Extension — snippets and diagnostics for VS Code