# Router WASM [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![npm version](https://img.shields.io/npm/v/router-wasm.svg)](https://www.npmjs.com/package/router-wasm) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/router-wasm)](https://bundlephobia.com/package/router-wasm) [![WebAssembly](https://img.shields.io/badge/WebAssembly-βœ“-654FF0.svg)](https://webassembly.org/) **WebAssembly bindings for intelligent neural routing and vector search in the browser.** > Bring powerful vector database capabilities to the client-side. Run sub-millisecond vector search entirely in the browser with **zero server dependencies**. Perfect for edge computing, offline AI, and privacy-first applications. ## 🌟 Why Router WASM? Traditional vector databases require backend infrastructure and constant network connectivity. **Router WASM changes that.** ### The Browser-First Advantage - ⚑ **Zero Latency**: No network roundtripsβ€”search happens entirely in the browser - πŸ”’ **Privacy First**: User data never leaves the device - 🌐 **Offline Capable**: Full functionality without internet connection - πŸ’° **Cost Effective**: Eliminate backend infrastructure and API costs - πŸš€ **Edge Computing**: Deploy intelligent routing to CDN edge nodes - πŸ“¦ **Small Bundle**: Optimized WASM binary for fast page loads ## πŸš€ Features ### Core Capabilities - **Client-Side Vector Search**: Sub-millisecond similarity search in the browser - **Neural Routing**: Intelligent request routing and pattern matching - **Multiple Distance Metrics**: Euclidean, Cosine, Dot Product, Manhattan - **HNSW Indexing**: Fast approximate nearest neighbor search - **Memory Efficient**: Optimized for browser memory constraints - **TypeScript Support**: Full type definitions included - **Framework Agnostic**: Works with React, Vue, Svelte, vanilla JS - **Web Worker Ready**: Run computations off the main thread ### Browser-Specific Optimizations - **SIMD Acceleration**: Hardware-accelerated vector operations where available - **Progressive Loading**: Load and initialize asynchronously - **Lazy Initialization**: Initialize only when needed - **Small Footprint**: <100KB gzipped WASM binary - **Memory Pooling**: Efficient memory management for long-running sessions - **IndexedDB Integration**: Persist vector data locally ## πŸ“¦ Installation ### NPM/Yarn ```bash # Using npm npm install router-wasm # Using yarn yarn add router-wasm # Using pnpm pnpm add router-wasm ``` ### CDN (Unpkg) ```html ``` ## ⚑ Quick Start ### Basic Usage (ES Modules) ```javascript import init, { VectorDB, DistanceMetric } from 'router-wasm'; // Initialize WASM module (only once) await init(); // Create a vector database with 128 dimensions const db = new VectorDB(128); // Insert vectors db.insert('doc1', new Float32Array([0.1, 0.2, 0.3, /* ... 125 more */])); db.insert('doc2', new Float32Array([0.4, 0.5, 0.6, /* ... 125 more */])); db.insert('doc3', new Float32Array([0.7, 0.8, 0.9, /* ... 125 more */])); // Search for similar vectors const query = new Float32Array([0.15, 0.25, 0.35, /* ... 125 more */]); const results = db.search(query, 5); // Top 5 results // Process results for (const result of results) { console.log(`ID: ${result.id}, Score: ${result.score}`); } // Get collection size console.log(`Total vectors: ${db.count()}`); // Delete a vector db.delete('doc2'); ``` ### TypeScript Support ```typescript import init, { VectorDB, DistanceMetric } from 'router-wasm'; interface SearchResult { id: string; score: number; } async function initializeVectorSearch(): Promise { // Initialize WASM await init(); // Create database with 384 dimensions (e.g., for sentence embeddings) const db = new VectorDB(384); return db; } async function semanticSearch( db: VectorDB, queryEmbedding: Float32Array, topK: number = 10 ): Promise { const results = db.search(queryEmbedding, topK); return results; } ``` ### React Integration ```jsx import React, { useState, useEffect } from 'react'; import init, { VectorDB } from 'router-wasm'; function VectorSearchApp() { const [db, setDb] = useState(null); const [loading, setLoading] = useState(true); const [results, setResults] = useState([]); useEffect(() => { async function initialize() { await init(); const vectorDb = new VectorDB(128); // Populate with sample data vectorDb.insert('item1', new Float32Array(128).fill(0.1)); vectorDb.insert('item2', new Float32Array(128).fill(0.5)); setDb(vectorDb); setLoading(false); } initialize(); }, []); const handleSearch = async (queryVector) => { if (!db) return; const searchResults = db.search(queryVector, 10); setResults(searchResults); }; if (loading) return
Loading vector database...
; return (

Client-Side Vector Search

    {results.map(r => (
  • {r.id}: {r.score.toFixed(4)}
  • ))}
); } export default VectorSearchApp; ``` ### Vue 3 Integration ```vue ``` ## 🎯 Use Cases ### Client-Side AI Applications **Semantic Search in the Browser** ```javascript // RAG (Retrieval Augmented Generation) in the browser import init, { VectorDB } from 'router-wasm'; import { generateEmbedding } from './embeddings'; // Your embedding model await init(); const knowledgeBase = new VectorDB(384); // Index documents const docs = [ { id: 'doc1', text: 'Rust is a systems programming language' }, { id: 'doc2', text: 'WebAssembly enables near-native performance' }, { id: 'doc3', text: 'Vector databases power semantic search' } ]; for (const doc of docs) { const embedding = await generateEmbedding(doc.text); knowledgeBase.insert(doc.id, embedding); } // Query with natural language const queryEmbedding = await generateEmbedding('What is WASM?'); const relevantDocs = knowledgeBase.search(queryEmbedding, 3); ``` **Offline Recommender System** ```javascript // Product recommendations without backend const productDb = new VectorDB(256); // Index product features products.forEach(product => { const featureVector = extractFeatures(product); productDb.insert(product.id, featureVector); }); // Get recommendations based on user preferences const userPreferences = getUserPreferenceVector(); const recommendations = productDb.search(userPreferences, 10); ``` **Privacy-First Search** ```javascript // Search user data without sending to server const privateDb = new VectorDB(512); // User data stays in browser userDocuments.forEach(doc => { const embedding = embedDocument(doc); privateDb.insert(doc.id, embedding); }); // All searches happen locally const results = privateDb.search(queryEmbedding, 20); ``` ### Edge Computing & CDN **Cloudflare Workers** ```javascript // Deploy to Cloudflare Workers import init, { VectorDB } from 'router-wasm'; export default { async fetch(request, env, ctx) { await init(); const db = new VectorDB(128); // Load pre-computed vectors from KV store const vectors = await env.VECTORS.get('index', 'json'); for (const [id, vector] of Object.entries(vectors)) { db.insert(id, new Float32Array(vector)); } // Handle search at edge const { query } = await request.json(); const results = db.search(new Float32Array(query), 10); return new Response(JSON.stringify(results), { headers: { 'content-type': 'application/json' } }); } }; ``` **Deno Deploy** ```typescript // Edge function with vector search import init, { VectorDB } from 'https://esm.sh/router-wasm'; Deno.serve(async (req) => { await init(); const db = new VectorDB(256); // Your edge routing logic return new Response('OK'); }); ``` ### Web Workers ```javascript // worker.js - Run vector search off main thread import init, { VectorDB } from 'router-wasm'; let db = null; self.addEventListener('message', async (e) => { const { type, payload } = e.data; if (type === 'init') { await init(); db = new VectorDB(payload.dimensions); self.postMessage({ type: 'ready' }); } if (type === 'insert') { db.insert(payload.id, new Float32Array(payload.vector)); self.postMessage({ type: 'inserted', id: payload.id }); } if (type === 'search') { const results = db.search(new Float32Array(payload.query), payload.k); self.postMessage({ type: 'results', data: results }); } }); ``` ```javascript // main.js - Use the worker const worker = new Worker('worker.js', { type: 'module' }); worker.postMessage({ type: 'init', payload: { dimensions: 128 } }); worker.addEventListener('message', (e) => { if (e.data.type === 'ready') { console.log('Vector DB ready in worker'); // Insert data worker.postMessage({ type: 'insert', payload: { id: 'doc1', vector: new Array(128).fill(0.1) } }); // Search worker.postMessage({ type: 'search', payload: { query: new Array(128).fill(0.2), k: 5 } }); } if (e.data.type === 'results') { console.log('Search results:', e.data.data); } }); ``` ## πŸ”§ Advanced Features ### Persistent Storage (IndexedDB) ```javascript import init, { VectorDB } from 'router-wasm'; // Initialize with persistent storage path await init(); const db = new VectorDB(128, 'my-vector-store'); // Data persists across sessions db.insert('doc1', new Float32Array(128)); // Reload in future session const db2 = new VectorDB(128, 'my-vector-store'); console.log(db2.count()); // Previously inserted data is available ``` ### Distance Metrics ```javascript import { VectorDB, DistanceMetric } from 'router-wasm'; const db = new VectorDB(128); // Different similarity measures available: // - DistanceMetric.Euclidean (L2 distance) // - DistanceMetric.Cosine (cosine similarity) // - DistanceMetric.DotProduct (dot product) // - DistanceMetric.Manhattan (L1 distance) // Note: Distance metric is set at index build time in router-core ``` ### Batch Operations ```javascript // Efficient bulk insertion const vectors = [ { id: 'doc1', vector: new Float32Array(128).fill(0.1) }, { id: 'doc2', vector: new Float32Array(128).fill(0.2) }, { id: 'doc3', vector: new Float32Array(128).fill(0.3) }, ]; vectors.forEach(({ id, vector }) => db.insert(id, vector)); // Batch search (multiple queries) const queries = [ new Float32Array(128).fill(0.15), new Float32Array(128).fill(0.25), ]; const allResults = queries.map(query => db.search(query, 5)); ``` ### Memory Management ```javascript // Check collection size const count = db.count(); console.log(`Vectors in database: ${count}`); // Clean up when done (especially important in SPAs) // Note: Drop the reference and let garbage collector handle it db = null; // For explicit cleanup in long-running apps function cleanupVectorDb(db) { const ids = getAllIds(); // Your tracking logic ids.forEach(id => db.delete(id)); } ``` ## πŸ“Š Performance Optimization ### Bundle Size Optimization **Tree Shaking** ```javascript // Import only what you need import init, { VectorDB } from 'router-wasm'; // Don't import unused distance metrics or types ``` **Code Splitting** ```javascript // Lazy load WASM module const loadVectorDB = async () => { const { default: init, VectorDB } = await import('router-wasm'); await init(); return VectorDB; }; // Use when needed button.addEventListener('click', async () => { const VectorDB = await loadVectorDB(); const db = new VectorDB(128); }); ``` **Webpack Configuration** ```javascript // webpack.config.js module.exports = { experiments: { asyncWebAssembly: true, }, optimization: { splitChunks: { chunks: 'all', }, }, }; ``` ### Runtime Performance **Pre-compute Embeddings** ```javascript // Generate embeddings server-side or during build // Ship pre-computed vectors to reduce client computation const precomputedVectors = await fetch('/vectors.json').then(r => r.json()); await init(); const db = new VectorDB(128); for (const [id, vector] of Object.entries(precomputedVectors)) { db.insert(id, new Float32Array(vector)); } ``` **Dimension Reduction** ```javascript // Use lower dimensions for faster search // 128 or 256 dimensions often sufficient for many use cases const db = new VectorDB(128); // Instead of 384 or 768 // Consider PCA or other dimensionality reduction techniques ``` **Limit Result Sets** ```javascript // Request only what you need const results = db.search(query, 10); // Top 10, not 100 // Implement pagination if needed function paginatedSearch(query, page = 0, pageSize = 10) { const allResults = db.search(query, (page + 1) * pageSize); return allResults.slice(page * pageSize, (page + 1) * pageSize); } ``` ## πŸ”¨ Building from Source ### Prerequisites - **Rust**: 1.77 or higher - **wasm-pack**: `cargo install wasm-pack` - **Node.js**: 18.0 or higher (for testing) ### Build Commands ```bash # Clone repository git clone https://github.com/ruvnet/ruvector.git cd ruvector/crates/router-wasm # Build for web (ES modules) wasm-pack build --target web --release # Build for Node.js wasm-pack build --target nodejs --release # Build for bundlers (webpack, etc.) wasm-pack build --target bundler --release # Build with optimizations wasm-pack build --target web --release -- --features simd # Run tests wasm-pack test --headless --chrome ``` ### Build Output After building, the `pkg/` directory contains: ``` pkg/ β”œβ”€β”€ router_wasm.js # JavaScript bindings β”œβ”€β”€ router_wasm.d.ts # TypeScript definitions β”œβ”€β”€ router_wasm_bg.wasm # WebAssembly binary β”œβ”€β”€ router_wasm_bg.wasm.d.ts └── package.json # NPM package metadata ``` ### Custom Build Profiles ```toml # Cargo.toml - Already optimized for size [profile.release] opt-level = "z" # Optimize for size lto = true # Link-time optimization codegen-units = 1 # Better optimization panic = "abort" # Smaller binary ``` ## 🌐 Browser Compatibility | Browser | Version | WASM | SIMD | Notes | |---------|---------|------|------|-------| | **Chrome** | 87+ | βœ… | βœ… | Full support | | **Firefox** | 89+ | βœ… | βœ… | Full support | | **Safari** | 15+ | βœ… | ⚠️ | WASM SIMD in 16.4+ | | **Edge** | 87+ | βœ… | βœ… | Full support | | **Opera** | 73+ | βœ… | βœ… | Full support | | **Mobile Safari** | 15+ | βœ… | ⚠️ | Limited SIMD | | **Mobile Chrome** | 87+ | βœ… | βœ… | Full support | **Notes**: - βœ… Full support - ⚠️ Partial support (SIMD acceleration may not be available) - All modern browsers support WebAssembly - SIMD provides 2-4x performance boost where available ## πŸ”— Integration with Ruvector Ecosystem ### With ruvector-wasm ```javascript import initRouter, { VectorDB as RouterDB } from 'router-wasm'; import initRuvector, { VectorDB } from 'ruvector-wasm'; // Initialize both modules await Promise.all([initRouter(), initRuvector()]); // Router WASM: Intelligent routing and pattern matching const router = new RouterDB(128); // Ruvector WASM: Full-featured vector database const vectorDb = new VectorDB(128); // Use together for advanced use cases ``` ### With Node.js Backend ```javascript // Frontend (router-wasm) import init, { VectorDB } from 'router-wasm'; await init(); const clientDb = new VectorDB(128); // Backend (ruvector Node.js bindings) const { VectorDB } = require('ruvector'); const serverDb = new VectorDB(); // Hybrid architecture: Local search + server sync ``` ## πŸ“š API Reference ### VectorDB ```typescript class VectorDB { /** * Create a new vector database * @param dimensions - Vector dimensionality (e.g., 128, 256, 384, 768) * @param storage_path - Optional persistent storage path */ constructor(dimensions: number, storage_path?: string); /** * Insert a vector into the database * @param id - Unique identifier * @param vector - Float32Array of specified dimensions * @returns The inserted ID */ insert(id: string, vector: Float32Array): string; /** * Search for similar vectors * @param vector - Query vector * @param k - Number of results to return * @returns Array of search results with id and score */ search(vector: Float32Array, k: number): SearchResult[]; /** * Delete a vector by ID * @param id - ID to delete * @returns true if deleted, false if not found */ delete(id: string): boolean; /** * Get total number of vectors * @returns Vector count */ count(): number; } ``` ### Types ```typescript interface SearchResult { id: string; score: number; } enum DistanceMetric { Euclidean, Cosine, DotProduct, Manhattan } ``` ## πŸŽ“ Examples ### Complete RAG Application See [examples/browser-rag](../../examples/browser-rag/) for a full-featured Retrieval Augmented Generation application running entirely in the browser. ### Product Search See [examples/product-search](../../examples/product-search/) for an offline product recommendation system. ### Edge Routing See [examples/edge-routing](../../examples/edge-routing/) for Cloudflare Workers integration. ## πŸ› Troubleshooting ### WASM Module Not Loading ```javascript // Ensure init() is called before creating VectorDB import init, { VectorDB } from 'router-wasm'; // ❌ Wrong const db = new VectorDB(128); // Error: WASM not initialized // βœ… Correct await init(); const db = new VectorDB(128); ``` ### Large Bundle Size ```javascript // Use dynamic imports for code splitting const { default: init, VectorDB } = await import('router-wasm'); await init(); ``` ### Memory Errors in Browser ```javascript // Reduce dimensions or limit database size const db = new VectorDB(128); // Instead of 768 // Clear vectors periodically in long-running apps if (db.count() > 10000) { // Implement your pruning logic oldIds.forEach(id => db.delete(id)); } ``` ### TypeScript Errors ```typescript // Ensure TypeScript can find declarations // tsconfig.json { "compilerOptions": { "moduleResolution": "node", "types": ["router-wasm"] } } ``` ## πŸ“– Documentation - **[Quick Start Guide](../../docs/guide/GETTING_STARTED.md)** - Get started in 5 minutes - **[WASM API Reference](../../docs/getting-started/wasm-api.md)** - Complete API documentation - **[Performance Tuning](../../docs/optimization/PERFORMANCE_TUNING_GUIDE.md)** - Optimization strategies - **[Main README](../../README.md)** - Ruvector ecosystem overview ## 🀝 Contributing Contributions are welcome! See [Contributing Guidelines](../../docs/development/CONTRIBUTING.md). ### Development Setup ```bash # Clone and setup git clone https://github.com/ruvnet/ruvector.git cd ruvector/crates/router-wasm # Build wasm-pack build --target web # Test wasm-pack test --headless --chrome --firefox # Format cargo fmt # Lint cargo clippy -- -D warnings ``` ## πŸ“œ License **MIT License** - see [LICENSE](../../LICENSE) for details. ## πŸ™ Acknowledgments Built with: - **wasm-bindgen**: Rust/JavaScript interop - **router-core**: High-performance vector routing engine - **HNSW**: Fast approximate nearest neighbor search - **SIMD**: Hardware-accelerated vector operations ## 🌐 Links - **GitHub**: [github.com/ruvnet/ruvector](https://github.com/ruvnet/ruvector) - **NPM**: [npmjs.com/package/router-wasm](https://www.npmjs.com/package/router-wasm) - **Documentation**: [ruvector docs](../../docs/README.md) - **Discord**: [Join community](https://discord.gg/ruvnet) - **Website**: [ruv.io](https://ruv.io) ---
**Built by [rUv](https://ruv.io) β€’ Part of [Ruvector](../../README.md) β€’ MIT Licensed** [![Star on GitHub](https://img.shields.io/github/stars/ruvnet/ruvector?style=social)](https://github.com/ruvnet/ruvector) [![Follow @ruvnet](https://img.shields.io/twitter/follow/ruvnet?style=social)](https://twitter.com/ruvnet) **Browser-First Vector Search** | **Zero Backend Required** | **Privacy First** [Get Started](../../docs/guide/GETTING_STARTED.md) β€’ [Documentation](../../docs/README.md) β€’ [Examples](../../examples/)