Nova is a production-grade, multilingual AI voice assistant that delivers natural conversation directly in the browser. Powered by Google Gemini 2.0 Flash with real-time SSE streaming, a 3D GLSL shader visualization, and full Web Speech API integration, Nova supports English, Arabic (Lebanese), and French. Talk, type, or say "Hey Nova" -- it handles all three.
Speech Recognition -- Browser-native speech-to-text via Web Speech API with interim results
Text-to-Speech -- Sentence-queue TTS with per-language pitch/rate tuning and intelligent voice selection
Wake Word Detection -- Hands-free activation with "Hey Nova" / "Nova"; extracts trailing query automatically
Chrome 15s TTS Fix -- Prevents Chrome from silently cutting off long utterances via sentence splitting and periodic pause/resume keep-alive
Multilingual Support -- English (US), Arabic (Lebanese), French with voice-triggered language switching
Listening Debounce -- 250ms stop-restart delay prevents overlapping recognition sessions
SSE Streaming -- Real-time progressive text delivery via Netlify Edge Functions (Deno runtime)
Server-side API Proxy -- Gemini API key never reaches the browser; proxied through Netlify serverless functions
Multi-turn Context -- Last 10 conversation messages sent with each request for context-aware responses
Rate Limiting -- 30 requests per 60-second window per IP with in-memory tracking
Retry with Backoff -- Automatic retry on 503 errors (2 attempts, 1s base delay)
Safety Filtering -- 4 harm categories blocked at medium threshold (harassment, hate, sexual, dangerous content)
Tuned Generation -- temperature 0.7, topK 40, topP 0.95, maxOutputTokens 1024
Streaming Fallback -- Automatically falls back to single-shot requests when streaming fails
Text Input -- Type-to-chat alternative with localized placeholders and RTL support for Arabic
Message Search & Filtering -- Real-time case-insensitive search with highlighted matching text and result count
Conversation Persistence -- Messages survive page refresh via localStorage (capped at 200 messages with schema validation)
Time-based Greeting -- Contextual welcome message based on time of day (morning / afternoon / evening)
Fully Responsive -- Adapts layout and blob sizing for mobile and desktop
Accessible Conversation History -- Focus trap, keyboard navigation, focus restoration, outside-click dismiss
Language Selector -- Visual picker with flag indicators; spoken confirmation on switch
Online/Offline Detection -- Reactive connectivity status with localized banner (EN/AR/FR)
Network Quality Monitoring -- Reads effective connection type, downlink, RTT, and Save-Data via Network Information API
Adaptive Streaming -- Automatically disables SSE on 2G / slow-2G / Save-Data connections
Slow Network Banner -- Visual warning when degraded connection is detected
Three.js Animated Blob -- IcosahedronGeometry at detail level 5 (~20K faces) with custom GLSL shaders
Simplex Noise Deformation -- Organic surface morphing via 3D simplex noise in vertex shader
Fresnel Rim Lighting -- Glowing edge effect with pulse color oscillation in fragment shader
State-driven Colors -- Idle (purple), Listening (blue), Speaking (purple), Responding (green)
WebGL Context Recovery -- Handles GPU context loss/restore without reloading
Keyboard & Screen Reader Support -- Enter/Space activation, dynamic aria-labels per state
Content Security Policy -- Strict CSP with whitelisted sources; frame-ancestors and object-src set to none
HSTS -- Forced HTTPS with 2-year max-age, includeSubDomains, and preload
Security Headers -- X-Frame-Options (DENY), X-Content-Type-Options (nosniff), Referrer-Policy (strict-origin-when-cross-origin)
Permissions Policy -- Microphone restricted to self; camera blocked entirely
Input Validation -- Query length (2000 chars), history cap (10 items), language enum enforcement
Dynamic Favicon -- Favicon changes to match assistant state (idle / listening / speaking / responding)
Progressive Web App -- Installable with offline caching via Workbox service worker
Privacy-friendly Analytics -- Plausible integration (production-only) with custom event tracking
Error Tracking -- Global error capture with FIFO buffer (max 20 reports); unhandled rejection handling
Localized Error Messages -- Error text displayed in the user's active language
-
Clone the Repository
git clone https://github.com/naveed-gung/nova.git cd nova -
Install Dependencies
npm install
-
Set Up Environment Variables
For local development, create a
.envfile:VITE_GEMINI_API_KEY=your_gemini_api_key
For Netlify deployment, set
GEMINI_API_KEYin the Netlify dashboard (Settings > Environment variables). The API key is proxied through a serverless function and never exposed to the client. -
Start Development Server
npm run dev
The app will be available at
http://localhost:8080.
Say "Hey Nova" or "Nova" followed by your question to activate hands-free. The assistant will detect the wake word and process the trailing query automatically.
| Language | Commands |
|---|---|
| English | "Switch to Arabic", "Speak Arabic", "Switch to French", "Speak French" |
| Arabic | "ΨͺΩΩΩ Ψ§ΩΨ¬ΩΩΨ²Ω" (Speak English), "ΨͺΩΩΩ ΩΨ±ΩΨ³Ω" (Speak French) |
| French | "Parle anglais", "Passer a l'anglais", "Parle arabe" |
- GLSL simplex noise vertex shader drives organic surface deformation
- Fresnel rim lighting with pulse color oscillation in fragment shader
- State-driven color and animation parameters (speed, amplitude, pulse rate)
- WebGL context recovery for resilience against GPU context loss
- Code-split Three.js chunk (~452KB) loaded independently
- Streaming path: Client β Netlify Edge Function (Deno) β Gemini SSE endpoint β chunked text back to UI
- Non-streaming path: Client β Netlify Handler Function (Node.js) β Gemini REST endpoint β complete response
- Automatic path selection based on network quality; manual fallback on stream failure
- Per-language system prompts instruct concise, direct responses
- API key isolated on server; never bundled or transmitted to the client
- CSP, HSTS, X-Frame-Options, and Permissions-Policy headers enforced via
netlify.toml - Rate limiting at the function layer (30 req/min per IP)
- Input validation on query length, history depth, and language enum
- Hosted on Netlify with automatic builds from the repository
- PWA with Workbox service worker for offline asset caching
- Code-split bundles for optimal loading performance
- SPA fallback routing configured for client-side navigation
