Inside Roundhouse: Building the Discord Command Bridge
Roundhouse is the desk where human support instincts meet the volatility of Discord. We ingest threads the instant they ignite, stitch them into a living interface, and let operators respond with the same urgency that created the fire in the first place. This post pulls the curtain back on the project: what we built, how the pieces collaborate, and the features that make the console feel alive.
Why Roundhouse Exists
Discord has become the default helpdesk for communities, yet its interface was never meant for triaging high-volume support. Roundhouse treats every thread as a ticket, every message as a data point, and every second as an opportunity to reply while the context is still warm.
- Surface Discord conversations in a single, searchable cockpit.
- Preserve tone and history while adding structure: status, priority, assignments.
- Keep agents in flow with AI summaries, live updates, and in-app replies.
The Monorepo Constellation
Workspace | Stack | Purpose |
---|---|---|
apps/web |
React + Vite, Apollo Client, Tailwind | Operator UI with real-time threads, message timeline, and compose tools |
apps/api |
Hono, GraphQL Yoga, Pothos | GraphQL queries, mutations, subscriptions, auth, and Discord handshakes |
apps/worker |
discord.js , Prisma, Redis |
Gateway consumer, persistence pipeline, and event broadcaster |
packages/db |
Prisma | Schema and generated client shared across services |
packages/data |
TypeScript utilities | Shared domain types and helpers to keep contracts honest |
packages/redis |
Typed Redis wrappers | Abstractions for publishing and subscribing to live events |
Each workspace owns a clear slice of the mission but shares a single type system. That keeps the mental model compact even as traffic scales.
Following the Signal
- A Discord thread or message lands. The worker adapts the payload, normalizes authors, threads, and message entities, and commits them through Prisma.
- The worker emits a compact event into Redis. We keep the envelope tiny so event fan-out stays resilient.
-
The API subscribes to that Redis channel, shapes a GraphQL-safe payload with Pothos, and streams it over
graphql-ws
to every connected browser. - The web client patches Apollo caches in place, animating the UI without a single refetch.
The result: Roundhouse responds to every Discord twitch in under a second, even when multiple operators watch the same ticket.
Feature Flyover
- Thread Radar: A real-time list of Discord threads with status, priority, unread counts, and live avatars so operators know who is already on it.
- Conversation Canvas: Full message history with inline metadata, Discord reactions, and composer tools for firing off replies without touching Discord.
- AI Summaries: OpenAI-powered synopsis streams token-by-token, condensing the situation into actionable bullet points while messages are still coming in.
- Searchable Memory: Filters across authors, channels, and keywords wrap Discord’s sprawl into a structured archive.
- Operational Controls: Status lanes, priority toggles, and claim buttons wire directly into the GraphQL API, feeding back into Discord threads when necessary.
-
Public Intake: A shared
/form
surfaces a low-friction entry point for people who are not yet in Discord-Roundhouse auto-creates the appropriate thread and triage context.
Architecture in Slow Motion
- Worker Discipline: The gateway worker is stateless aside from transient caches. Every event is idempotent: we upsert authors, threads, and messages, then publish a sanitized event object. Backfill scripts replay historical data so the state is never one outage away from divergence.
- API as Contract: Hono keeps the HTTP transport lean, while GraphQL Yoga hosts the schema and WebSocket server. Pothos maps Prisma models into a typed schema, meaning every field the UI consumes is traceable to a single resolver.
-
Web in Lockstep: Apollo Client splits HTTP queries from WebSocket subscriptions,
react-tracked
keeps local state minimal, and Tailwind +tailwind-merge
render a cockpit UI that responds instantly to cache writes. -
Shared DNA:
packages/data
exports enums and helper functions shared across worker, API, and web so business rules (like thread lifecycle states) never drift.
Design Principles
- Real-time first: The system assumes every ticket is in motion. Subscriptions are the default; polling is a fallback.
- Context over noise: AI summaries supplement, never replace, the raw feed. Operators can see receipts and metadata without losing the narrative.
- Composable ops: Each mutation is a pure GraphQL call that wraps Discord REST requests. That makes it trivial to layer feature flags or observability around sensitive actions.
- Observability baked in: Structured logs and metrics from worker → API → web let us pinpoint where latency or dropped events originate.
Edges We Watch
- Authentication scope: Discord OAuth issues a JWT cookie. Today any authenticated user gains access; future work includes guild and role checks.
- Horizontal scale: Redis pub/sub currently lives single-instance. A sharded or Kafka-backed fan-out is on the roadmap for multi-region resiliency.
- AI guardrails: Summaries lean on OpenAI; we monitor output drift and token costs, and we keep the human transcript as the source of truth.
Looking Forward
Roundhouse is already a fast lane for Discord support teams, but the next frontier is proactive help: knowledge base retrieval during replies, smarter alerting when threads go cold, and richer dashboards for volume forecasting. Until then, every piece of the stack-from the Prisma schema to the Tailwind components-exists to keep human responders in sync with a very noisy world.
Stay legendary.