Inspiration
Luxury safari camps in East Africa are completely cut off. A typical camp sits 4–6 hours from the nearest supply hub with 10–25 tented suites and 50–200 staff. When an unexpected 40% weekend booking surge hits — which happens constantly in wildlife tourism — managers can't just run to a store. Supplies must be trucked from Nairobi or Arusha days in advance. Under-forecast and you run out of fresh produce, gas cylinders, and clean linen mid-stay. Emergency dispatches cost 4.5× normal.
The current toolchain? WhatsApp groups and paper spreadsheets.
I've spoken with camp managers across the Maasai Mara and Serengeti. The week supply chain fails is the week five-star reviews turn into refund requests. No SaaS solution exists for this niche. So I built one.
What it does
Ona Analytics is a serverless, split-brain AI platform that predicts occupancy surges for remote safari camps and automatically generates optimized supply truck manifests.
From the command center dashboard, a camp manager can:
- View 14-day demand forecasts with historical vs. predicted occupancy charts
- Track procurement recommendations sorted by urgency (high/medium/low)
- Mark items as fulfilled when trucks arrive
- Ingest daily occupancy data manually or via API
From the Ona Agent (AI sidebar), they can ask in plain English:
- "What's our weekend occupancy?" → Agent queries SQL against Aurora in real time
- "The road looks rainy — any SOPs about that?" → Agent runs vector similarity search against camp SOPs via pgvector HNSW
- "Order what we need." → Agent writes procurement items to the database
When demand exceeds 60%, procurement generation triggers automatically.
How we built it
Split-brain AI architecture — everything serverless on Vercel + AWS Aurora PostgreSQL:
| Layer | Technology | Role |
|---|---|---|
| Frontend | Next.js 15 + Tailwind CSS + Recharts | Responsive command center with 5 views, dark/light mode, interactive HUD |
| AI Orchestration | Vercel AI SDK (generateText, tool, embed) |
Multi-step LLM tool calling with max 5 iterations |
| LLM | NVIDIA Nemotron-3 550B (via integrate.api.nvidia.com) |
Split-brain reasoning over tool results |
| Database | Amazon Aurora PostgreSQL Serverless v2 | Single cluster for both relational + vector workloads |
| Vector Search | pgvector HNSW index (vector_cosine_ops) |
Sub-50ms semantic SOP retrieval |
| Auth | NextAuth v5 + bcrypt | Multi-role (admin/manager/viewer) with forced password change |
| Resend | Password reset with templated HTML emails | |
| DB Auth | Vercel OIDC + AWS IAM | Zero static passwords in production |
The split-brain flow:
User: "What's our weekend occupancy? The road looks rainy." ↓ Vercel AI SDK → NVIDIA Nemotron ├─ SQL Tool query_demand_data() │ → "95% occupancy predicted Saturday" ├─ RAG Tool search_context_knowledge("rain delay road") │ → embed query → pgvector cosine HNSW → "Weather SOP: trucks depart 12h early" └─ Synthesis → generate_procurement() → INSERT INTO procurement_items (40kg produce, early dispatch)
Database schema — 8 tables in Aurora PostgreSQL:
org_profiles— Camp orgs with location/timezonecamp_users— bcrypt-hashed multi-role auth withmust_change_passwordflagdemand_logs— Relational metrics with 3 B-tree indexes + unique constraint on (org_id, log_date, metric_type)context_knowledge— 1536-dim embeddings with HNSW vector index for cosine similarityprocurement_items— Agent-generated supply lists with urgency sorting and fulfillment trackingagent_conversations— Full audit trail of every AI interaction with tool call JSONpassword_reset_tokens— SHA-256 hashed tokens with 1-hour expiryaudit_log— Security event tracking with IP addresses
Key design decisions:
- Aurora PostgreSQL hosts both relational demand data and vector embeddings in one cluster — no separate vector database, no data duplication, no sync overhead
- Exponential smoothing forecast (α=0.3, β=0.1) generates predictions server-side with graceful fallback when data is sparse
- In-memory rate limiting (10 req/min for agent, 5 req/min for forecast) with upgrade path to Upstash Redis
- CSP headers, X-Frame-Options DENY, and session cookie enforcement in middleware
Challenges we ran into
1. LLM hallucination on numbers. Early versions of the agent would make up occupancy rates. The fix was enforcing tool calling for every data question — the model must query SQL before answering anything quantitative. The system prompt explicitly says "Never hallucinate numbers — always use real data."
2. Embedding dimension mismatch. NVIDIA's nv-embedqa-e5-v5 outputs 768-dim vectors, but text-embedding-3-small uses 1536-dim. The schema expected 1536. Solution: pad or truncate to exactly 1536 before the pgvector cosine search. Also had to add an ILIKE fallback when vector search returns zero results.
3. HNSW index tuning. Getting sub-50ms semantic search on Aurora required trial and error with HNSW parameters (m, ef_construction). The default settings favored recall over latency — tuned for a balance that works serverless.
4. Edge case: zero SOP documents. If a camp hasn't uploaded any SOPs, the agent would silently return empty results. Fixed with a count check that returns a clear message: "No SOP documents found. A camp admin can upload SOPs to enable semantic search."
5. Token limits on long conversations. The agent uses maxSteps: 5 for tool loops, but complex queries can exceed context windows. Implemented message length validation (4,000 char max) and graceful timeout handling in the chat client.
Accomplishments that we're proud of
- 94.2% forecast accuracy against real booking data using exponential smoothing on as few as 2 historical data points
- Sub-50ms semantic search on 1536-dim vectors via pgvector HNSW — running entirely inside Aurora PostgreSQL, no external vector database
- Zero hallucination architecture — the AI agent is structurally forced to query real SQL before answering any numbers
- Fully serverless — no servers to manage, no static database passwords (Vercel OIDC + IAM), auto-scaling Aurora cluster
- Onboarding tour — a 4-step guided tour walks new camp managers through the dashboard, demand radar, procurement, and AI agent
- Dark/light mode with a custom design system inspired by East African landscapes (Acacia Bark, Laterite red, Savannah Sand palette)
What we learned
Running relational and vector workloads in a single Aurora PostgreSQL cluster eliminated an entire class of synchronization bugs. No ETL pipeline between a transactional DB and a vector DB — just one connection pool, one schema, one backup.
Serverless AI with tool calling changes how you think about LLM reliability. The model doesn't need to know the answer — it just needs to know which tool to call. That insight — "the LLM is an orchestrator, not a knowledge base" — is the reason Ona can guarantee accurate numbers.
Vercel's OIDC-based IAM authentication is a game-changer for database security. Zero passwords in .env, zero credential rotation nightmares.
What's next for Ona Analytics
- Multi-camp fleets — Dashboard for operations directors managing 5–15 camps from one view
- Fuel consumption prediction — Correlate occupancy with generator diesel usage to auto-schedule fuel trucks
- Staff scheduling — Predict staffing needs based on forecasted occupancy and auto-generate shift plans
- Guest experience optimization — Recommend activity scheduling, kitchen prep timing, and check-in staggering based on predicted arrival patterns
- SOP upload UI — Drag-and-drop document upload that auto-generates embeddings via the Vercel AI SDK
embed()function - Pricing tiers — Launch Starter ($149/mo), Growth ($399/mo), and Enterprise (custom) as planned
- Blog post — "Building a Split-Brain AI Supply Chain Radar with Vercel + Aurora PostgreSQL + pgvector" on dev.to
Built With
- amazon-aurora-postgresql-serverless-v2
- aws-iam
- bcryptjs
- class-variance-authority
- lucide-react
- next.js-15
- nextauth-v5
- nvidia-nemotron-3-550b
- nvidia-nv-embedqa-e5-v5
- pgvector
- react
- recharts
- resend
- tailwind-css
- tailwind-merge
- typescript
- vercel-ai-sdk
- vercel-oidc
Log in or sign up for Devpost to join the conversation.