Two projects, one stack: architecture of Decent TD and Sidebar Agent
Two shipped projects. Same Nuxt 4 + Vue 3 + TypeScript foundation. One is a real-time multiplayer game; the other is an agentic dev-tools surface embedded in the app itself. Both were built predominantly by coding agents — Claude sessions steering architecture, implementation, and iteration — with human oversight on scope and review.
This post breaks down the stack choices, key architectural decisions, and what agent-driven development actually looks like once you push past toy demos.
The shared foundation
Both projects run on Nuxt 4 with Nitro as the server layer. The choice was deliberate: file-based routing, auto-imports, and server routes in the same repo eliminates glue code between frontend and backend. TypeScript end-to-end means types flow from database schema to rendered component without manual DTO mapping.
Common infrastructure decisions:
- HTTPS everywhere, even in dev — SSL certs from a shared
~/certs/directory, bound to0.0.0.0for LAN testing on mobile - Bootstrap 5 + SCSS over Tailwind — agents produce more consistent markup with utility classes they can name explicitly, and the component library (
BsButton,BsCard,BsModal) stays stable across refactors - MongoDB for content and user state; PostgreSQL + Drizzle ORM where relational integrity matters (game state, tower definitions, upgrade trees)
- Port isolation via a registry (
PORT-REGISTRY.md) — each project owns a 20-port range, no collisions
Decent TD: real-time game on a web stack
A multiplayer cooperative tower defense where agents wrote the overwhelming majority of gameplay code.
Server-authoritative game loop
The server owns all game state. Clients are pure renderers. This prevents cheating and simplifies the mental model: the WebSocket handler in server/routes/_ws.ts receives player actions, validates them against current state, mutates the GameRoom, and broadcasts diffs.
// server/game/GameRoom — simplified tick
tick(dt: number) {
this.spawnEnemies(dt)
this.moveEnemies(dt)
this.fireTowers(dt)
this.checkWaveComplete()
this.broadcastState()
}
Fog of war at scale
A 100×100 grid (10,000 cells) with three visibility states: unexplored, explored, and in-vision. Server calculates vision from tower ranges every second; clients receive delta updates (only changed cells). On the GPU side, fog renders as instanced meshes — single draw call, <1ms per frame.
3D with Three.js
Towers render as CAD-generated meshes (via replicad). The admin panel has an interactive 3D tower catalog where you rotate, zoom, and inspect each tower definition before it goes live. Procedural audio via Tone.js means no asset pipeline for sound effects — agents synthesize new sounds by tweaking oscillator parameters.
Stack summary
| Layer | Choice | Why |
|---|---|---|
| Rendering | Three.js | Agents handle imperative 3D APIs well; scene graph is explicit |
| Audio | Tone.js | Procedural — no asset files to manage |
| State | Pinia | Vue-native reactivity for UI overlays on the canvas |
| DB | PostgreSQL + Drizzle | Relational data (towers, upgrades, player stats) |
| Real-time | Nitro WebSocket | Same-process, no separate WS server to deploy |
| Auth | OAuth (Google/GitHub/Discord) | Standard; agents scaffold OAuth flows reliably |
Sidebar Agent: agentic surface inside the app
The second project puts Claude directly into the running application as two components.
The chat panel
A docked sidebar holding a persistent agent session. Route-aware — it knows what page you're viewing, can read surrounding application state, and operates against the project from inside the running app. Tool calls, file reads, and AskUserQuestion cards stream inline.
The key architectural decision: the agent session is bound to the current route. Navigation doesn't destroy context; it enriches it. The agent accumulates understanding of what the user is doing across pages.
The issue reporter
A modal that captures complaints — typed text, voice transcription, or screenshot-with-annotation — and routes them to a structured triage pipeline:
- User submits a report
- Agent classifies: hotfix-shaped bug vs. feature request
- HMAC-authenticated callback triggers a detached agent process
- SSE streams status back to the UI (triaging → working → resolved)
- Queue watchdog recovers from crashes; retries with exponential backoff
The result: the loop from "this is broken" to "tracked and being worked on" collapses to a single in-app interaction.
DevTools proxy: closing the feedback loop
Both projects are developed with the help of a custom MCP proxy server that gives coding agents eyes and hands in the browser. The proxy bridges multiple Chrome controllers:
local-chrome-client— headless Puppeteer for automated testingdevtools-ws-client— Chrome extension on a real browser for GPU-rendered screenshotsbrowser-tab-bridge— read-only access to all open tabs
Agents can navigate, take snapshots, evaluate scripts, click elements, and read console output. This turned frontend development from "agents write code blindly and hope" into a genuine feedback loop where the agent sees its own output and self-corrects.
What agent-driven development actually looks like
The agents aren't generating boilerplate and walking away. The pattern that emerged:
- Architecture spec — human defines the shape (a
.architecture/folder with YAML records and a constitution) - TDD gates — agents write tests first; implementation must pass before moving on
- Session continuity — CLAUDE.md files and architecture records let cold sessions pick up where the last one left off
- Visual verification — devtools-proxy screenshots let agents confirm their UI changes render correctly
Interventions are mostly scope corrections ("don't build that subsystem yet") and taste decisions ("use instanced meshes, not individual objects"). The agents handle implementation depth, edge cases, and cross-cutting concerns autonomously.
Next steps
- Decent TD: deploy matchmaking as a separate Nitro service; add spectator mode via read-only WebSocket connections
- Sidebar Agent: voice input for the issue reporter; persistent agent memory across browser sessions
Looking forward
These two projects serve as proof points for a specific thesis: coding agents can drive real, production-quality software when you give them the right scaffolding — architecture records for memory, TDD for correctness, and visual feedback for UI work. The stream documents this process as it evolves, building in public with the tools rather than just talking about them.