ELO Darts logo

ELO Darts

Co-Founder & Lead Engineer·2024 - present·Live

ELO Darts is a real-time platform for serious webcam and club darts, with verified players, automated tournaments and rich performance stats for players, teams and associations.

  • TypeScript
  • Next.js
  • Express.js
  • Socket.IO
  • WebRTC
  • mediasoup
  • Prisma
  • PostgreSQL
  • Redis
  • BullMQ
  • Stripe
  • Docker

Key Features

  • Real-time webcam matches
  • Cross-device scoring app
  • Automated tournaments & brackets
  • Player verification & anti-cheat
  • Advanced stats & ELO ratings
  • Streaming views with chat
  • Club & association tools

A Look Inside

Autoscoring match with automatic multi-camera throw detection, live scoring and stats
Player profile with verified average, checkout rates and 3-dart average over time
Live broadcast of several parallel webcam matches with stats and tournament bracket

ELO Darts — Making Real-Time Feel Instant

ELO Darts started with a feeling I couldn't shake: playing darts online should feel as alive as standing at the board with a friend. No lag between your throw and the score. No awkward "did it register?" moments. Just instant, trustworthy, competitive play.

That obsession with how it feels is what shaped every technical decision I made. This is the project where I went deepest on real-time systems — and the one I'm most proud of.

Why I Built It This Way

Real-time apps are deceptively easy with a handful of users. They get genuinely hard the moment you add:

  • Parallel matches and tournaments running at once
  • Live scoring and live video and chat, all in sync
  • Stats and rankings that update the instant a leg finishes

I could have faked "real-time" with polling and called it a day. But the whole promise of the platform is that every score, every camera frame, every state change feels instant — even with many matches and spectators in parallel. Cutting corners there would have killed the thing that makes it special. So I designed for scale from the first commit, not as an afterthought.

How I Built It

The stack is a modern real-time core wrapped in a fast frontend:

  • Frontend: Next.js, React, Tailwind, shadcn/ui — a responsive scoring UI that works on phone, tablet and desktop
  • Backend: a dedicated Node.js / Express server, split from the Next.js app so the real-time layer scales on its own
  • Real-time messaging: Socket.IO with a Redis adapter, so multiple Node instances handle WebSocket traffic while staying perfectly in sync
  • Live video: WebRTC over a mediasoup SFU — one media server fans webcam streams out to many parallel matches and spectators
  • Data: PostgreSQL with Prisma, indexed around the read patterns of live dashboards and match views
  • Background work: BullMQ queues in a separate worker service for ELO updates, stat aggregation and bracket generation
  • Payments: Stripe for premium features and tournament fees
  • Infrastructure: Dockerized services with load balancing on Hetzner

The biggest challenge was keeping real-time traffic fast and predictable as usage grew. Here's how I solved it:

  • Socket.IO + Redis lets me add more backend instances and have Redis reliably fan events out across all of them.
  • Room-based channels (per match, per tournament, per club) mean a client only ever receives the data it actually needs — no broadcasting noise.
  • WebRTC via a mediasoup SFU keeps video scalable: clients send their stream once, the server distributes it, instead of every peer talking to every other peer.
  • Heavy work runs async — rating recalculations, statistics and integrity checks live in background workers, so the request/response path stays lean.
  • Tracing and metrics (OpenTelemetry and Sentry) let me find hot paths and tighten bottlenecks before players ever feel them.

The result: I can spin up more backend instances and the system keeps latency low under load, with Redis keeping every event in sync.

Why I Love It

This project is my reference for scalable, real-time architecture — but the reason I love it goes beyond the stack. It's the moment two players in different cities throw, and the score and the video land at the same instant, and it just feels right. Getting software to disappear like that — so the experience is all that's left — is the part of engineering I find most rewarding.

It also taught me lessons I now bring into every project: how to design WebSocket APIs and room structures that stay sane as features grow, how to separate "must be real-time" from "can be async," and why monitoring and a good data model matter just as much as clever code when you're dealing with live data.

Interested in this project?

Check out the live website or get in touch to learn more.