surplus.ai ยท codebase architecture

Visual Map

How everything fits together, what's missing, and what Jonas would build

Built & working
Not yet built
Jonas would build
โšก

Tech Stack

SOLID
Next.js 16 React 19 TypeScript (strict) tRPC Tailwind Vercel AI SDK OpenRouter Zod
๐Ÿ”’ Strict TypeScript: no any, no as T, Zod validation at all boundaries. This is unusually disciplined for a prototype.
โ–ผ UI Layer
๐Ÿ–ฅ๏ธ

UI โ€” Drawer-Based Interface

BUILT
๐Ÿ“ฆ Products
๐Ÿ‘ฅ Segments
๐Ÿ’ฐ Pricing Policy
๐Ÿ“ Price Models
โ›“๏ธ Value Chain
๐Ÿ’Ž Value Drivers
โš”๏ธ Competitors
๐Ÿ”„ Alternatives
๐Ÿงฎ Costing
๐Ÿค Deal Pricing
๐Ÿ“ก Customer Signals
๐Ÿ“‚ Each section is a workspace tab. Users interact via drawers that trigger agent runs. Landing pages exist but the product is workspace-focused.
โ–ผ tRPC (type-safe)
๐Ÿง 

Agent System โ€” 25 Agents

CORE
Agent Registry ยท lib/ai/
๐Ÿ” Product Discovery
Find and identify products
โœจ Product Enrichment
Add features, specs, details
โš”๏ธ Competitor Discovery
Find who competes
๐Ÿ•ต๏ธ Competitor Deep-Dive
Detailed intel on competitors
๐Ÿ”„ Alternative Discovery
Find substitute products
๐Ÿ’ฐ Pricing Analysis
Analyze competitor pricing
๐Ÿ‘ค Buyer Import
Import buyer profiles
๐Ÿข Company Profiling
Full company analysis
๐Ÿ’Ž Value Drivers
What drives customer value
โœ… Feature Cross-Val
Validate features across sources
๐ŸŽฏ Lead Discovery
Find potential customers
๐Ÿ“Š +14 more agents
Enrichment, analysis, signals
Agent Architecture
defineAgent({ name: "competitor-discovery", model: "haiku-4.5", // per-agent model selection tools: [webSearch, webFetch], // tools available systemPrompt: "...", outputSchema: z.object({...}), // Zod validated output }) // Registry: central Map<name, Agent> for all 25 agents // CLI runner: test any agent from terminal // JSONL logs: every run traced to .jsonl files // Streaming: NDJSON to UI for real-time progress
Models (via OpenRouter)
Claude Haiku 4.5 (default) Gemini Flash (some agents) Per-agent model selection
โ–ผ Tools & External
๐Ÿ”ง

Tools & Integrations

BUILT
๐Ÿ” Exa AI (web search)
๐ŸŒ Web Fetch
๐Ÿ“‚ Workspace Queries
๐Ÿ’พ Result Caching
๐Ÿ“ JSONL Trace Writer
๐Ÿ–ฅ๏ธ CLI Test Runner
โ–ผ Data Layer
๐Ÿ’พ

Data Storage

YAML FILES ONLY
โš ๏ธ No database. All workspace data lives in YAML files. This works for a prototype but can't scale to multi-user.
โ–ผ What's missing
๐Ÿšง

Missing Infrastructure

NOT BUILT
๐Ÿ—„๏ธ Database (no DB at all)
๐Ÿ” Auth / user system
๐Ÿ‘ฅ Multi-tenancy
๐Ÿ’ณ Payment / billing
โ–ผ What Jonas would build
๐Ÿ”ฅ

Jonas's Production Layer

TO BUILD
๐Ÿ—„๏ธ DatabaseReplace YAML with real persistence
๐Ÿ” Auth SystemUser accounts, sessions, roles
๐Ÿ‘ฅ Multi-TenancyIsolated workspaces per org
๐Ÿ’ณ BillingStripe, usage metering, plans
โšก Parallel AgentsSub-agent orchestration (Task 1)
๐Ÿ“Š Ops & MonitoringOTel, dashboards, alerts
๐ŸŽฏ Task 1 for tomorrow: Parallel sub-agent orchestration. Run multiple agents concurrently using map-reduce + p-limit + Promise.allSettled. This is the highest-impact improvement to agent throughput.
๐Ÿ”€

Request Flow โ€” End to End

User clicks "Enrich Product" in workspace โ”‚ โ–ผ UI (React 19) โ”€โ”€โ†’ tRPC call โ”€โ”€โ†’ Server โ”‚ โ–ผ Agent Registry.get("product-enrichment") โ”‚ โ–ผ โ”Œโ”€ ToolLoopAgent โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๐Ÿค” Think: "I need product specs" โ”‚ โ”‚ ๐Ÿ”ง Tool: exa.search("Product X") โ”‚ โ”‚ ๐Ÿ‘€ Observe: got 5 results โ”‚ โ”‚ ๐Ÿค” Think: "Need pricing too" โ”‚ โ”‚ ๐Ÿ”ง Tool: webFetch(competitor.com) โ”‚ โ”‚ ๐Ÿ‘€ Observe: got pricing page โ”‚ โ”‚ โœ… Done: complete enrichment โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”œโ”€โ”€โ†’ JSONL trace log (every step recorded) โ”œโ”€โ”€โ†’ NDJSON stream to UI (real-time updates) โ”‚ โ–ผ Results โ”€โ”€โ†’ Save to YAML (future: database) โ”‚ โ–ผ UI updates workspace view โ”โ”โ” Tomorrow's Addition โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” User clicks "Full Analysis" (runs ALL agents) โ”‚ โ–ผ Orchestrator splits into parallel tracks: โ”Œโ”€ pLimit(5) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Promise.allSettled([ โ”‚ โ”‚ productAgent.run(), โ† slot 1 โ”‚ โ”‚ competitorAgent.run(), โ† slot 2 โ”‚ โ”‚ pricingAgent.run(), โ† slot 3 โ”‚ โ”‚ buyerAgent.run(), โ† slot 4 โ”‚ โ”‚ valueAgent.run(), โ† slot 5 โ”‚ โ”‚ ...20 more waiting... โ† queued โ”‚ โ”‚ ]) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ Reduce: combine all results into workspace