Back to projects

Case study · Rivals Pulse

A real-time game overlay with a voice assistant, and the web app that feeds it

Anthony Turner · September 2026

  • Angular 21 / 20
  • TypeScript
  • Signals + RxJS
  • Overwolf ODK
  • ElevenLabs Conversational AI
  • Supabase
  • IndexedDB
  • Turso (libSQL)
  • Vercel
  • Jasmine + Karma

In one paragraph

Rivals Pulse is a companion for the game Marvel Rivals, in two parts. The desktop app runs inside the game through Overwolf: it reads live match events and draws a heads-up display of rosters, stats and match state, and a voice assistant answers questions out loud mid-match without the player leaving the game. The web app at rivalspulse.com is a coaching site with hero guides, counters, a team builder and meta reports, and it doubles as the data service the desktop app reads from. I built both on my own, directing AI coding agents through tracked issues, pull requests and reviews: 261 merged pull requests and about 1,910 automated tests on the desktop app, and 85 production releases of the web app.

merged pull requests on the desktop app
261
automated tests on the desktop app
~1,910
Overwolf windows: a dashboard and 15 overlays
16
production releases of the web app
85
Unedited match capture of the voice assistant in use. Turn sound on: the assistant is heard rather than shown, so the spoken questions and its replies are the demo.

The product

Players of a fast team shooter have seconds to make decisions and no time to alt-tab to a wiki. Rivals Pulse puts the information where the player already is:

  • In the game: a match bar, a live stats bar, ally and enemy rosters with a top-performer badge, last-match rosters carried into hero select, a session win/loss record and an end-of-match summary.
  • Out loud: a hotkey-activated voice assistant with on-screen subtitles and a spoken end-of-match wrap-up.
  • On the desktop: match history, hero stats and insight charts, hero lookup, counter search, a ban list, a glossary of game slang, and per-widget settings.
  • On the web: about 24 pages of coaching: a hero encyclopedia, hero and strategist guides, positioning guides, counters with a planner for dive compositions, a team builder, a tier list, season win-rate reports and live player-count stats.

Architecture: two apps, one data flow

PartHow it works
Desktop appAngular 21 on Overwolf, with standalone components, signals and OnPush change detection. 96 components and 76 services across 16 windows and 19 hotkeys, fed by Overwolf's game events for live match, roster and scene data.
Local-first dataAn IndexedDB cache is reconciled with Supabase Postgres (row-level security), so match history stays visible when a stats provider is down.
Backend functionsSupabase Edge Functions sync match and hero history from third-party stats providers and issue short-lived voice sessions.
Web appAngular 20 (zoneless) on Vercel with 13 serverless functions over a Turso database. It also serves heroes, the glossary and the tier list to the desktop app.
Fresh data without redeploysScheduled jobs refresh game stats hourly, the tier list every six hours and the news daily. A nightly workflow adds new heroes to the database and opens a pull request for their portraits.

A voice assistant grounded in live match data

The assistant runs on ElevenLabs Conversational AI over WebRTC. The design choices are what make it useful in a match rather than a demo:

  • Answers come from the app, not the model's memory. The agent calls eight tools that wrap the app's own services (counters, glossary, team composition, player stats, player comparison, hero guides, session record and match info), so it answers from the live match.
  • Latency against cost. A toggle hotkey opens the session, and it closes after 15 seconds of silence, with a hard cap on session length, balancing connection time against per-minute billing. It is off by default.
  • Secured sessions. Short-lived session tokens are minted by a backend function and rate-limited, so no API key ships in the app.
  • Platform rules first. The overlay treats other players' data conservatively, following the publisher's rules for overlays as the project understands them. That approach is written down once as a decision record and enforced in what the assistant will answer.

Hard problems in a real-time overlay

  • Out-of-memory crashes mid-match. Every game-event update started a new timer, and full event dumps were logged in every window. One timer per player and debug-only logging fixed it.
  • Wasted re-renders in teamfights. The stats bar rebuilt its DOM on every event tick. Signal equality checks, stable tracking keys and OnPush change detection stopped it.
  • Noisy game state. The game's scene flag flips between match and lobby for minutes after a match, which made the display flicker. It is now debounced once, at the source, instead of in every consumer.
  • Events that arrive in either order. Match start and a new match ID race each other, and carrying the last match's roster into hero select failed about three times in four. It now opens on whichever signal arrives first.
  • A silently stale season on the web app. A news parser matched the wrong headline and fell back to a hard-coded season for about a month. The fix scans every headline for the highest season and adds a regression test.

How I directed the AI

  • Issue-first, from July 2026. Since July, changes on the desktop app go from issue to branch, pull request, review and merge: 335 issues and 261 merged pull requests.
  • Written rules for the agents. A written agent guide, role definitions for product, refinement, UX, engineering and QA agents, and nine Architecture Decision Records.
  • Visible AI authorship. 192 of the desktop app's 386 commits on main (about half) carry an AI co-author trailer, so the history shows which work was agent-written.
  • Guard rails in the tooling. Strict TypeScript with strict template checks, ESLint, conventional commits enforced by a commit hook, and lint on every commit.
  • Tests that match the code. The desktop app has about 33,000 lines of tests alongside about 35,400 lines of app code.

Mistakes along the way

  • A bad merge broke the build. A bad merge once left a stray brace and dropped a fix on main, breaking the build. A follow-up restored both.
  • Widgets built, then cut. Four HUD widgets and their services were built, then removed to reduce clutter.
  • Uneven test coverage. The web app has 30 tests against the desktop app's 1,910. Its stale-season bug lasted about a month before it was caught, and the fix added a regression test.

What this shows

  • Real-time front-end engineering: performance and correctness under a constant stream of game events, across 16 windows.
  • Practical AI integration: a voice agent that uses the app's own data through tools, with cost, security and platform rules designed in.
  • Full-stack delivery: Angular on the desktop and the web, Supabase and Turso data, serverless functions and scheduled data pipelines.
  • Directing AI with discipline: hundreds of tracked changes through pull requests, with decisions written down.

Timeline

The desktop app's first commit was 25 Nov 2025. The web app started 4 Jun 2026 and first reached production on 15 Jun. The issue-first workflow began 16 Jul, the web app took the Rivals Pulse name on 30 Jul, and the voice assistant merged 22 Sep. The desktop app is at version 1.0 and not yet released on the Overwolf store.