Overview
Digcrate is a Next.js application with a Convex real-time backend. The browser communicates with serverless API routes on Vercel, which in turn talk to Convex (database), Anthropic (AI), and MCP tool servers (music data).Tech stack
| Layer | Technology | Purpose |
|---|---|---|
| Framework | Next.js 16 (App Router) | SSR, API routes, Turbopack dev |
| Deployment | Vercel | Serverless functions |
| Auth | Clerk | User sign-in, OAuth |
| Connected services | Auth0 Token Vault | OAuth connections for Spotify, Slack, Google |
| Database | Convex | Real-time sessions, messages, playlists, collections, influence graph, subscriptions, skills, shares |
| Dynamic UI | OpenUI (@openuidev/react-lang) | Agent-generated interactive components |
| Agent | Anthropic SDK + agentic loop | Tool-use loop with crate-cli MCP servers |
| Billing | Stripe | Checkout, billing portal, webhooks |
| Styling | Tailwind CSS v4 | Dark theme, responsive mobile |
| Audio | YouTube IFrame API | Persistent player bar |
| Analytics | PostHog | Product analytics, LLM observability |
Project structure
The agentic loop
Every user message goes through a multi-turn tool-use loop implemented insrc/lib/agentic-loop.ts.
- The browser sends a
POSTto/api/chatwith the message, session history, model choice, and API key. - The route handler builds the tool list from
crate-cliMCP servers and callsagenticLoop(). - The loop calls the Anthropic (or OpenRouter) API with the message and available tools.
- If the model returns
tool_useblocks, the loop executes each tool call against the appropriate MCP server. - Tool results are fed back to the model as
tool_resultblocks. Steps 3–5 repeat up to 25 turns. - Each turn emits Server-Sent Events to the browser:
thinking,tool_start,tool_end,answer_token, and finallydone. - The browser’s chat panel renders tokens as they arrive and parses OpenUI components from the final answer.
useOpenRouter flag on AgenticLoopOptions selects the path.
Key data flows
Authentication
/api/webhooks/clerk. The Convex users table stores the Clerk user ID, email, encrypted API keys, and Stripe customer ID.
Agent query
Real-time state (Convex)
The browser subscribes to Convex queries that push updates in real time:| Subscription | What updates |
|---|---|
sessions.listByUser | Sidebar session list |
messages.listBySession | Chat message history |
artifacts.listBySession | Deep Cuts panel |
playlists.listByUser | Playlist library |
usage.getForCurrentPeriod | Usage meter in settings |
Connected services (Auth0 Token Vault)
Database schema
The Convex database has 24 tables. Key tables:| Table | Purpose |
|---|---|
users | User accounts with Clerk ID, encrypted keys, Stripe customer ID |
crates | Named session folders for organizing research |
sessions | Chat sessions (title, crate membership, starred, archived) |
messages | Chat messages (user and assistant roles) |
artifacts | Saved research components (Deep Cuts) |
toolCalls | Tool execution log per session |
playerQueue | Audio player queue tracks per session |
playlists / playlistTracks | User playlists with track metadata |
collection | Vinyl collection records |
subscriptions | Stripe subscription state |
usageEvents | Per-user, per-period query count |
userSkills | Custom slash commands |
shares | Published Deep Cut share records |
influenceArtists / influenceEdges | Cached influence graph nodes and edges |
telegraphAuth / telegraphEntries | Telegraph publishing credentials and posts |
tumblrAuth / tumblrPosts | Tumblr publishing credentials and posts |
orgKeys | Team-level shared API keys by domain |