en
Vue.js SPA on Tor Hidden Service: Complete 2026 Guide
Modern single-page applications built with Vue.js can be deployed as Tor hidden services for privacy-first user experiences. This guide covers building, configuring, and deploying a Vue.js SPA as a .onion service.
Need this done for your project?
We implement, you ship. Async, documented, done in days.
Vite Build Configuration for .onion Deployment
Vue.js apps built with Vite need specific configuration for .onion deployment. vite.config.js: set base: '/' (ensures asset paths are root-relative, not absolute URLs that would reference clearnet domains), and build.outDir: 'dist' (standard output directory). Critical: do not use public CDN URLs for any dependencies. All JavaScript, CSS, and fonts must be bundled locally or served from the .onion server. Check your vendor chunks for any external URL imports (some packages load fonts or icons from CDNs by default - override these). Build optimization: enable code splitting (dynamic imports for route components), use tree shaking (Vite handles this by default), and configure chunk size warnings (aim for chunks under 500KB for faster loading over Tor's bandwidth-limited circuits).
Nginx Configuration for Vue.js SPA
Vue.js SPAs use HTML5 History mode routing (or hash mode). For history mode .onion service: Nginx must return index.html for all routes (the SPA handles routing client-side). Configuration: location / { try_files $uri $uri/ /index.html; } - this returns index.html for any path that does not match a static file. Static asset caching: set Cache-Control headers for static assets (Vite generates hashed filenames for cache busting). location ~* \.(js|css|png|jpg|svg|woff2)$ { expires 1y; add_header Cache-Control 'public, immutable'; } Static files with hash in filename can be cached indefinitely. Security headers for SPA on .onion: Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' (unsafe-inline needed for Vite's dev mode, remove for production if possible); style-src 'self' 'unsafe-inline'; img-src 'self' data:;
API Integration: Vue.js Frontend to Backend .onion
A Vue.js SPA typically needs a backend API. For .onion deployment, both the SPA and API can be served from the same .onion address: Nginx proxies /api/ to the backend application, and / serves the Vue.js dist files. Alternatively, the API can be on a separate .onion address (different key, different introduction points). API URL configuration in Vue: use environment variables (import.meta.env.VITE_API_URL) to set the API base URL. For production, set VITE_API_URL to the API .onion address (or /api/ if same-origin). Environment files: .env.onion for .onion deployment configuration versus .env.clearnet for clearnet deployment. CORS for .onion API: if the API is on a different .onion from the SPA, configure CORS in the API server (Access-Control-Allow-Origin: http://spaaddress.onion).
Authentication in Vue.js .onion Applications
Authentication in a Vue.js SPA over .onion: use JWT tokens stored in-memory (not localStorage - localStorage persists across Tor Browser sessions in Standard mode and can be accessed by JavaScript). In-memory token storage: store JWT in a reactive store (Pinia or Vuex) and re-authenticate on page refresh. HTTPOnly cookies: an alternative to in-memory storage, HTTPOnly cookies cannot be accessed by JavaScript (XSS safe) and are sent with every request. For .onion HTTP services: set cookies without the Secure flag (only needed for HTTPS). Session management: for anonymous .onion services, consider session-less authentication (stateless JWT with short expiry) to minimize server-side session state. Vue Router guards: implement route-level authentication checks (beforeEach guard) to redirect unauthenticated users to the login page.
Performance Optimization for Vue.js on .onion
Tor's limited bandwidth makes asset optimization critical for Vue.js applications. Bundle size reduction: use Vue's tree shaking (import only what you use from component libraries), code splitting (dynamic import() for route components - routes load only when visited), and avoid large dependencies (check bundle-analyzer, replace heavy libraries with lighter alternatives). Image optimization: use modern formats (WebP, AVIF with fallbacks), lazy load images below the fold (Vue's v-lazy or Intersection Observer), and compress images aggressively (aim for <100KB for most images). Loading performance: preload critical resources ( for main bundle), use service workers for caching (though Tor Browser's strict mode may restrict service workers), and show meaningful loading states during initial load (Tor circuit establishment adds 3-5 seconds to first load). Progressive loading: show text content immediately while images and secondary content load.
Related Services
Why Anubiz Host
100% async — no calls, no meetings
Delivered in days, not weeks
Full documentation included
Production-grade from day one
Security-first approach
Post-delivery support included
Ready to get started?
Skip the research. Tell us what you need, and we'll scope it, implement it, and hand it back — fully documented and production-ready.