Voyagent 📊 Live Pulse 📚 Knowledge base Open app ↗
Technical Specification · Beta

Voyagent — Tech Specs

A group-trip planner that reconciles every traveller's budget, tastes and hard "no"s into one fair, AI-written itinerary — built in a hackathon sprint with a deliberately boring, zero-build stack. Everyone's voice, one trip.

Every number on this page is measured from the actual codebase. App: voyagent.netlify.app · Live metrics: Voyagent Pulse

~2.7k
lines of core code
14
API endpoints
7
database tables
4
AI features
10
app screens
3
npm dependencies
0
build steps

1 · Architecture

Browser / PWA Preact 10 + htm (CDN) one HTML file, no build installable, offline cache voice input (Web Speech) Netlify static app + edge CDN /api/* serverless fn 14 routes · shared core rate limits · sanitization Supabase Postgres 7 tables · RLS deny-all realtime broadcast pings AI provider gpt-4o (Claude-ready) strict JSON schemas Open-Meteo rain forecast → re-tune Voyagent Pulse · Vercel static dashboard + KB (+ Netlify backup) HTTPS service role "change" broadcast ping (no data) GET /api/stats (aggregates only)

One shared API core runs identically as an Express server locally and a Netlify Function in production — no drift between dev and prod. The browser holds zero secrets: the database denies all direct access (row-level security with no policies + revoked grants), and live updates are empty "something changed" broadcast pings that trigger clients to re-fetch through the API.

2 · Stack

LayerTechnologyWhy
FrontendPreact 10.25 + htm 3.1 via esm.sh CDN — single index.html (~1,500 lines)Zero toolchain; edit-and-refresh; ~4KB framework
APIShared api-core.js → Express 5 (local) / Netlify Function (prod), esbuild-bundledSame code both environments
DatabaseSupabase (Postgres) · SQLite (node:sqlite) fallback for key-less local devManaged, realtime, free tier
AIOpenAI gpt-4o default · Anthropic claude-opus-4-8 supported — provider-agnostic wrapperStrict structured outputs on both
WeatherOpen-Meteo forecast API (AI-supplied coordinates)Free, no key, drives rain re-tune
HostingNetlify (app+API) · Vercel (Pulse, primary) + Netlify mirror (backup)Git-push deploys, multi-platform resilience
PWAManifest + network-first service worker + canvas-generated iconsInstallable, offline-readable plans
Dependencies@supabase/supabase-js, @anthropic-ai/sdk, express — that's allTiny attack/maintenance surface

3 · Product surface

10 screens (Home hub, Create, Join, Invite, Quiz, Group, Suggestions, Vote, Generating, Itinerary) + 4 overlay sheets (Trip settings, Re-tune, Trip chat, Surprise roulette), all in one Preact file with light/dark Zen theming.

4-step 60-second quizper-day budgets ₹/$/€/£ (log-scale slider)optional age bandstrip-aware avoid presetshard dealbreakersdestination voting (live tally)AI day-by-day itineraryweather-aware re-tunechat that edits the schedulevoice input ×3 fieldssurprise-destination rouletteconsensus gatesstale-plan rebuild bannerpublic share pages (zero-JS)realtime roster/votes

4 · API surface (14 endpoints)

MethodPathPurpose
GET/api/configRuntime config (AI provider, anon realtime key)
GET/api/stats?month=YYYY-MMPublic aggregate analytics (CORS-open, 60s cache, month filter)
POST/api/tripsCreate trip
POST/api/trips/join/:codeJoin via invite code
GET/api/trips/:idFull trip state (members, prefs, votes, plan)
POST/api/trips/:id/preferencesSubmit/update quiz
POST/api/trips/:id/settingsRename / re-date (creator-only)
POST/api/trips/:id/suggestAI destination suggestions ⚡
POST/api/trips/:id/voteCast vote (validated against ballot)
POST/api/trips/:id/generateAI itinerary for vote winner ⚡
POST/api/trips/:id/retuneAI single-day rewrite (preview) ⚡
POST/api/trips/:id/retune/applyPersist re-tune as new version (validated)
POST/api/trips/:id/askTrip chat — can directly edit the schedule ⚡
GET/api/trips/:id/weatherRain probability per trip day (Open-Meteo)

⚡ = AI route, guarded by rate limits. Every mutating route fires a realtime broadcast ping after writing.

5 · Data model

TableColsHolds
trips10Trip, phase state machine, private invite code + separate public share_code
members5Travellers (first-name only, no accounts)
preferences12Quiz answers: per-day budget + currency, vibes, city, age band, dealbreakers
suggestions4AI destination cards incl. coordinates
votes4One vote per member (composite PK)
itineraries11Versioned plans — every re-tune/chat-edit is a new version; unique partial index enforces one active
ai_calls5Append-only AI usage ledger → rate limits + spend cap

7 indexes including UNIQUE (trip_id) WHERE active on itineraries and a unique share-code index. RLS enabled with zero policies + all grants revoked from anon: the public key can read and write nothing.

6 · AI decision engine

FeatureFunctionOutput budgetFallback when AI is down
Destination suggestionssuggestDestinations3.5k tokens3 seeded cards with real coordinates
Itinerary generationgenerateItinerary3k + 1.2k/day (≤16k)Destination-aware template days
Day re-tuneretuneDay3.5k tokensCanned indoor/covered day
Trip chat + editsaskTrip6k tokensSafe "plan unchanged" reply

7 · Security posture

ControlImplementation
Database lockdownRLS deny-all + revoked anon grants — verified HTTP 401 on every table with the public key
Zero-data realtimeEmpty broadcast pings only; realtime publication contains no tables
HTTP headersCSP (allow-listed origins only), HSTS, nosniff, DENY framing, strict referrer, Permissions-Policy (mic-only)
Share pagesServer-rendered, zero JavaScript, CSP default-src 'none', public code never exposes private invite
Input handlingEvery field length-capped + control-chars stripped server-side; payload shape validation on all writes
Prompt securityInjection/junk/unsafe-input battle-tested and scored by an independent AI judge panel
Spend control20 AI calls/trip/hr · 30/IP/hr · 300/day global hard cap (env-tunable), append-only ledger, friendly 429s
SecretsKeys live only in host env vars; browser receives only the powerless anon key

8 · Analytics — Voyagent Pulse

A separate static dashboard (Vercel primary, Netlify backup) implementing Pirate Metrics (AARRR): 6 KPI cards (North Star = shared plans delivered), acquisition/activation/referral funnel, activity sparkline, trending destinations, vibes, budget bands, currencies and age mix — with a month/year filter and 60-second live refresh.

Privacy by construction: the dashboard holds no credentials and consumes only /api/stats — aggregates computed server-side (counts, categories, label-only budget bands, small-bucket suppression). It cannot display a name, a trip, or any single person's data.

9 · Quality & hardening

10 · Constraints & roadmap

Deliberate beta constraints: no accounts (trips are capability URLs), AI content is advisory (verify prices/visas), data resets possible.

Next: Google sign-in (unlocks retention metrics), affiliate booking links (revenue), expense splitting, push notifications, vote deadlines, multilingual, error tracking.


Voyagent · Beta · Everyone's voice, one trip. — Repos: voyagent (app) · voyagent-pulse (this site) on GitHub. Full narrative in the knowledge base.