A Vue compiler, Language Server Protocol (LSP) implementation, and build tool — built as a hybrid Rust + TypeScript monorepo.
Note
Verter is in beta (v0.0.1-beta.1). It is actively used in development and tested against real-world Vue projects (Element Plus, Naive UI, PrimeVue, Vuetify, and more). The core APIs are stabilizing but may still change between releases. Bug reports and feedback are very welcome — please open an issue if you run into anything.
Important
The generated TSX is syntactically valid TypeScript/TSX used for type analysis only — it's not meant to be executed or compiled as actual JSX/TSX code.
Verter is a full Vue compiler and toolchain built in Rust: it compiles templates to optimized render functions for production, generates typed TSX for IDE analysis, runs ~186 lint rules without ESLint, and powers a Language Server with type-provider integration (TSGO/tsserver). A bundler plugin, MCP server for AI agents, and component metadata extraction round out the toolchain.
-
Full TypeScript Support: Converts
.vuefiles to typed TSX representations, enabling complete TypeScript type inference - Vue 3 Support: Optimized for Vue 3 with Composition API and Script Setup
- Options API Support: While Script Setup receives more attention, Options API is supported
- Strict Type Safety: Built with a "strict first" approach to type safety
- JSX/TSX Interoperability: SFCs can be seamlessly used in JSX/TSX projects
- Generic Component Handling: Full support for generic Vue components with proper constructor typing
- Automatic Event Handler Type Inference: Infers parameter types for functions used as template event handlers
- Fully Typed Vue Directives: Complete type safety for directives with strict modifier, argument, and value validation
- Rust-Powered Template Compilation: High-performance template-to-render-function compilation via native bindings or WASM
- Built-in Linting: ~186 lint rules across 12 categories (Vue, a11y, CSS, performance, security, SSR, and more) — runs natively in Rust, no ESLint needed
- MCP Server: Built-in Model Context Protocol server with 49 Vue analysis tools for AI agents
- TypeScript Type Provider: Delegates type checking to TSGO (fast Go binary) or tsserver (workspace TS version)
-
Experimental Native Svelte Compilation: Compiles a pinned, tested client-runtime surface against
svelte@5.56.3; unsupported runtime features fail closed with typed diagnostics instead of producing successful placeholder modules - Component-Meta Audit Footprint: Opt-in per-request observability (loaded files, derivation graph, cache counters) with deterministic JSON serialization. See docs/audit-footprint/.
Verter provides improved handling for generic Vue components, respecting Vue constructors with proper type inference:
<!-- Comp.vue -->
<script setup lang="ts" generic="T extends string">
defineProps<{
name: T;
}>();
defineSlots<
Record<T & string, (args: { test: T }) => any> & {
header: (a: { foo: string }) => any;
}
>();
</script>import Comp from "./Comp.vue";
const foo = {} as InstanceType<typeof Comp<"myName">>;
foo.$props.name; // Type: 'myName'Verter automatically infers types for function parameters used as event handlers in templates:
<script setup lang="ts">
// No type annotation needed - Verter infers the type automatically
function handleClick(e) {
// e is inferred as MouseEvent from HTMLElementEventMap["click"]
console.log(e.clientX, e.clientY);
}
</script>
<template>
<button @click="handleClick">Click me</button>
</template>This works for native HTML elements (via HTMLElementEventMap), Vue components (via emits/props definitions), and multi-parameter event handlers.
<script setup lang="ts">
import type { Directive } from "vue";
import { ref } from "vue";
const count = ref(0);
const vColor: Directive<HTMLElement, string, "red" | "blue"> = (el, binding) => {
el.style.color = binding.value;
};
</script>
<template>
<span v-color.blue="'red'" />
<!-- valid -->
<span v-color.green="'red'" />
<!-- type error: invalid modifier -->
<input v-model.number.trim="count" />
</template>Verter maintains benchmark harnesses for compiler micro-fixtures, repository first-pass and warm-pass workloads, editor latency, component metadata, and an equal-work comparison between the experimental Svelte compiler and the pinned official compiler.
Performance numbers are deliberately not embedded here: they vary by platform, compiler revision, corpus, build profile, and cache state, and a static table quickly becomes misleading. Treat a result as evidence only for its recorded fixture set and immutable revisions. Comparative runs must perform equivalent work, validate behavior, attest cache mode, and report process RSS when making a memory comparison. See the benchmark package for commands, fixtures, and machine-readable result contracts.
Verter is a ground-up reimagining of Vue tooling — a single Rust-powered toolchain that replaces several separate tools:
- Compiler: Native runtime and IDE compilation for Vue, plus a bounded experimental Svelte client surface
- Language Server: Full LSP with hover, completions, diagnostics, go-to-definition, rename, and more — with type checking delegated to TSGO or tsserver
- Linter: ~186 built-in lint rules across 12 categories (Vue, a11y, CSS, performance, security, SSR) — no ESLint or extra plugins needed
- Bundler Plugin: Universal plugin for Vite, Webpack, Rollup, esbuild, Rspack, Rolldown, and Farm
- MCP Server: 49 analysis tools for AI agents via Model Context Protocol
- Component Metadata: Prop/event/slot extraction with adapters for Storybook, Histoire, Zod, and JSON Schema
| Aspect | Verter | Volar |
|---|---|---|
| Maturity | Beta | Production-ready |
| Language | Rust compiler + TypeScript IDE glue | TypeScript only |
| IDE approach | SFC → valid typed TSX for direct TS analysis | Virtual file mapping |
| Template compilation | Built-in (VDOM + Vapor output) | Delegates to @vue/compiler-sfc
|
| Linting | ~186 built-in rules (no ESLint needed) | Relies on eslint-plugin-vue |
| Type provider | TSGO (fast) or tsserver (compatible) | TypeScript language service |
| AI integration | Built-in MCP server | — |
Note
If you haven't encountered specific issues with Volar, there's no reason to switch. Verter is for developers who want a faster, more integrated Vue toolchain and are comfortable with beta software.
The LSP delegates TypeScript semantics to one TypeScript authority per editor
epoch. Configure verter.typeProvider in VS Code:
| Mode | Behavior |
|---|---|
auto (default) |
Prefer the exact editor-owned Native Preview Program, then the attested editor tsserver route; start managed TSGO only after a connected demand observes a bounded failure |
shared-tsgo |
Prefer the exact editor-owned Native Preview Program, with lazy managed fallback after an observed attach failure |
tsgo |
Use a separately managed TSGO process as an explicit operator override |
tsserver |
Use the workspace TypeScript version through tsserver |
extension |
Host the TypeScript language service in the extension process (experimental) |
off |
Disable TypeScript-backed checking and editor features |
Fallback is demand-driven and bounded. Initialization probes alone do not silently replace an editor-owned engine, and Verter does not run multiple TypeScript authorities for the same served response.
Verter is a hybrid Rust + TypeScript monorepo. The core compiler, LSP server, linter, MCP server, and static analysis are all Rust. TypeScript packages handle IDE integration (VS Code extension, TS plugin) and bundler plugin orchestration.
graph TB
subgraph "IDE Layer"
VSCode["verter-vscode<br/>(VS Code Extension)"]
TSPlugin["@verter/typescript-plugin<br/>(TS Plugin)"]
end
subgraph "Rust Core"
LSP["verter_lsp<br/>(LSP Server)"]
MCP["verter_mcp<br/>(MCP Server)"]
Host["verter_session<br/>(File Host + Caching)"]
Compiler["verter_compiler<br/>(Template Compiler)"]
Analysis["verter_semantic<br/>(Semantic Analysis)"]
Diagnostics["verter_diagnostics<br/>(~186 Lint Rules)"]
Actions["verter_actions<br/>(Quick Fixes)"]
end
subgraph "Bindings"
Native["@verter/native<br/>(NAPI-RS)"]
WASM["@verter/wasm<br/>(wasm-bindgen)"]
end
subgraph "Consumers"
Unplugin["@verter/unplugin<br/>(7 Bundlers)"]
ComponentMeta["@verter/component-meta<br/>(Metadata Extraction)"]
Playground["@verter/playground<br/>(Online)"]
end
VSCode --> LSP
VSCode --> TSPlugin
LSP --> Host
MCP --> Host
Host --> Compiler
Host --> Analysis
LSP --> Diagnostics
LSP --> Actions
MCP --> Diagnostics
Native --> Host
WASM --> Compiler
Unplugin --> Native
ComponentMeta --> Native
ComponentMeta -.-> WASM
Playground --> WASM
flowchart LR
SFC[".vue file"] --> Compiler["verter_compiler<br/>(Rust)"]
Compiler --> IDE["Typed TSX<br/>(IDE analysis)"]
Compiler --> Runtime["Render Functions<br/>(VDOM / Vapor)"]
IDE --> LSP["verter_lsp<br/>+ Type Provider"]
Runtime --> Bundler["Bundler Plugin<br/>+ Production"]
verter/
├── crates/ # Rust crates (core of the project)
│ ├── verter_compiler/ # Template compiler: VDOM/Vapor codegen, IDE TSX codegen
│ ├── verter_parser/ # SFC/carrier tokenizer, parser, and AST
│ ├── verter_semantic/ # Semantic analysis: component surface, bindings, type resolution
│ ├── verter_session/ # In-memory file host: caching, dependency tracking
│ ├── verter_diagnostics/ # Diagnostic engine: ~186 lint rules, visitor, DiagnosticSet
│ ├── verter_actions/ # Code actions: quick fixes, refactoring
│ ├── verter_lsp/ # LSP server binary (stdio)
│ ├── verter_mcp/ # MCP server binary (stdio + HTTP)
│ ├── verter_ffi/ # FFI types: shared serializable structs for NAPI/WASM
│ ├── verter_span/ # Typed span types (Span, RelativeSpan, GeneratedSpan)
│ ├── verter_bench/ # Benchmarks and comparison examples
│ ├── verter_napi/ # Native Node.js bindings (NAPI-RS)
│ └── verter_wasm/ # WASM bindings (wasm-bindgen)
├── packages/ # TypeScript packages
│ ├── unplugin/ # @verter/unplugin — Universal bundler plugin (7 bundlers)
│ ├── native/ # @verter/native — NAPI binding loader + platform packages
│ ├── wasm/ # @verter/wasm — WASM binding wrapper
│ ├── vue-vscode/ # verter-vscode — VS Code extension
│ ├── typescript-plugin/ # @verter/typescript-plugin — TS language service plugin
│ ├── language-shared/ # @verter/language-shared — Shared LSP protocol types
│ ├── component-meta/ # @verter/component-meta — Metadata extraction + Type IR
│ ├── playground/ # @verter/playground — Online playground (Netlify)
│ ├── types/ # @verter/types — Type utilities (internal)
│ └── example/ # Example project
├── docs/ # Documentation (VitePress site)
└── scripts/ # Build and utility scripts
verter-vscode (VS Code extension)
├── verter_lsp (Rust LSP binary, stdio)
│ ├── verter_session (file host + compilation)
│ ├── verter_diagnostics (lint rules + DiagnosticSet)
│ ├── verter_actions (quick fixes + refactoring)
│ └── TypeProvider (optional: TSGO or tsserver)
├── @verter/language-shared (custom protocol types)
└── @verter/typescript-plugin (.vue import resolution, NAPI-backed)
verter_mcp (MCP server binary, stdio + HTTP)
├── verter_session (file host + compilation)
├── verter_semantic (semantic analysis + type resolution)
├── verter_diagnostics (lint rules + DiagnosticSet)
└── verter_actions (quick fixes + refactoring)
@verter/unplugin (universal bundler plugin)
└── @verter/native (NAPI-RS bindings)
@verter/component-meta (metadata extraction)
├── @verter/native (NAPI host, Node.js)
└── @verter/wasm (WASM host, browser, optional)
@verter/playground (Netlify-hosted)
└── @verter/wasm (wasm-bindgen)
Install the Verter VS Code extension from the marketplace (coming soon).
# 1. Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
# 2. Add WASM target and install wasm-bindgen CLI
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.122 --locked
# 3. Install pnpm (if not already installed, requires Node.js 26 — see .nvmrc)
corepack enable
corepack prepare pnpm@latest --activate
# 4. Clone and build
git clone https://github.com/pikax/verter.git
cd verter
pnpm install
pnpm build # Builds: native bindings → LSP binary → WASM bindings → TypeScript packages
# 5. (Optional) Package VS Code extension
pnpm package- Node.js 18+
- pnpm 10+
- Rust toolchain (for building native/WASM bindings) — install via rustup
-
wasm32 target —
rustup target add wasm32-unknown-unknown -
wasm-bindgen CLI (for WASM builds) —
cargo install wasm-bindgen-cli --version 0.2.122 --locked
# Build everything (sequential: native → lsp → wasm → TypeScript)
pnpm build
# Build individual layers
pnpm run build:native # Rust → .node bindings
pnpm run build:lsp # Rust → LSP binary (debug)
pnpm run build:lsp:release # Rust → LSP binary (release, optimized)
pnpm run build:wasm # Rust → .wasm bindings
pnpm run build:ts # TypeScript packages
# Watch mode for extension development
pnpm watch
# Build LSP binary, then watch language-shared + vscode extension + typescript-plugin
pnpm dev-extension
# Clean build artifacts
pnpm clean# Run all Rust tests
cargo test --workspace --verbose
# Run specific crate tests
cargo test --package verter_compiler
# Format and lint
cargo fmt --all
cargo clippy --workspace# TypeScript tests (Vitest)
pnpm test
pnpm vitest --run # All tests (non-watch)
pnpm vitest --run path/to/test.spec.ts # Specific file
# Rust tests
cargo test --workspace --verbose
cargo test --package verter_compiler test_name # Specific testTest files are co-located with source files as *.spec.ts.
See the Performance section above for latest results. To run benchmarks locally:
# Run benchmarks (8 fixtures + 20k file stress test)
pnpm --filter @verter/benchmark bench
# Run with JSON output (for CI)
pnpm --filter @verter/benchmark bench:jsonBenchmarks are also triggered in CI via /benchmark PR comment.
Use hotpath profiling on real Vue projects (or fixture fallback) via profile_ast:
# Timing profile
pnpm run profile:hotpath
# Timing + allocation profile
pnpm run profile:hotpath:alloc
# Full-corpus timing / allocation profile
pnpm run profile:hotpath:full
pnpm run profile:hotpath:full:allocFor the analysis MCP server (verter-mcp) used by AI agents, see mcp/README.md.
Tests Verter against real-world Vue projects (Vuetify, PrimeVue, etc.) to ensure compilation correctness:
# Manual trigger via GitHub Actions
# - Actions tab → Integration Test → Run workflow
# - Or comment "/integration" on any PRSee .github/INTEGRATION_TEST.md for details.
- Documentation — Full documentation site
- Architecture Overview — Deep dive into Verter's design
- Rust Setup Guide — Rust development environment
- Contributing Guide — How to contribute
- CI/CD Documentation — Workflows and release process
| Package | README | Description |
|---|---|---|
verter-vscode |
README | VS Code extension |
@verter/unplugin |
Docs | Universal bundler plugin (7 bundlers) |
@verter/native |
README | NAPI-RS binding loader + platform packages |
@verter/wasm |
README | WASM bindings for browser |
@verter/typescript-plugin |
README | TypeScript language service plugin |
@verter/language-shared |
README | Shared LSP protocol types |
@verter/component-meta |
README | Component metadata + Type IR + adapters |
@verter/playground |
README | Online playground |
Internal packages (not intended for direct use)
| Package | Description |
|---|---|
@verter/types |
TypeScript utility types used by the compilation pipeline |
| Crate | Description |
|---|---|
verter_compiler |
Core template compiler (VDOM/Vapor + IDE TSX) |
verter_parser |
SFC/carrier tokenizer, parser, and AST |
verter_semantic |
Semantic analysis: component surface, bindings, type resolution |
verter_session |
In-memory file host: caching, dependency tracking |
verter_diagnostics |
Diagnostic engine: ~186 lint rules |
verter_actions |
Code actions: quick fixes, refactoring |
verter_lsp |
Rust LSP server binary (stdio) |
verter_mcp |
MCP server binary (stdio + HTTP) |
verter_ffi |
FFI types for NAPI/WASM boundaries |
verter_span |
Typed span types (Span, RelativeSpan, etc.) |
verter_bench |
Benchmarks and comparison examples |
verter_napi |
NAPI-RS Node.js bindings |
verter_wasm |
WASM bindings (wasm-bindgen) |
- Svelte language-tools for proving inspiration
- Vetur for providing the base for language support
- Volar for inspiration and testing
MIT