- Frontend
- Next.js 16 + React 19 with the App Router. The fund's analyst-facing surfaces (toggle settings, memo history, manual re-run) live here. shadcn/ui as the primitive layer; minimal Framer Motion for the kinds of micro-interactions that signal a tool, not a website.
- Backend
- Hono backend in a Turborepo monorepo, deployed to Vercel separately from the frontend. OpenAPI-TS for end-to-end type-safe API contracts; the frontend has zero hand-written client code. Webhook handlers, queue workers, notetaker adapters, ClickUp client all organized by domain under `server/src/services/`.
- Notetaker integration layer
- Each notetaker is wrapped in an adapter that exposes the same internal shape — get_calls(since), get_transcript(call_id), get_speakers(call_id). The pluggable shape was the part of the architecture that made the Granola MCP-to-API-key migration manageable.
- AI orchestration
- Anthropic Claude Sonnet 4.6 with a 400-token system prompt that has gotten shorter over time, not longer. The current production prompt is roughly a third the length of what we shipped in week one and produces strictly better memos. The 42-question structure is enforced by a Zod schema; structured-output JSON ensures the memo can be parsed into ClickUp doc sections without LLM-formatting drift.
- ClickUp integration
- Deal-stage-change webhook subscription on the relevant ClickUp Space. The webhook handler validates, enqueues a delayed job, and returns 200 within ClickUp's 30-second window. The job worker pulls the transcript window, calls Claude, and posts the memo back as a structured doc update plus a four-question summary as a comment on the card.
- Auth + multi-tenancy
- Supabase SSR with cookie-based JWT auth. The deployment is currently single-tenant (one fund) but architected for multi-tenant — every entity is scoped by `org_id`, every endpoint enforces that scope server-side. Adding a second fund is a configuration exercise, not a refactor.