DEV Community

Cover image for I built a real-time multiplayer typing game (and shipped 2 features in 5 days based on feedback)
Nico Hirsch
Nico Hirsch

Posted on

I built a real-time multiplayer typing game (and shipped 2 features in 5 days based on feedback)

I built a real-time multiplayer typing game (and shipped 2 features in 5 days based on feedback)

What is TYPECHAMP?

I built TYPECHAMP - a real-time multiplayer typing race game where you compete against friends (or strangers) to see who can type the fastest.

Think TypeRacer meets modern web tech.

The Stack

  • Frontend: Next.js 16 + React 19 (with the new React Compiler!)
  • Backend: Go 1.25 with WebSocket for real-time communication
  • Styling: Tailwind CSS v4

The WebSocket connection maintains <100ms latency for real-time cursor position updates, so you can literally see your opponents typing character-by-character.

The Launch Story

I launched V1 five days ago on Reddit and got... 2 upvotes. 😅

But more importantly, I got feedback:

"This is cool but I lack friends :( Can you add public lobbies so I can race strangers?"

Challenge accepted.

Fast Iteration: V1 → V2 in 5 Days

Within the next few days, I shipped:

1. Public Lobbies (Dec 5)

  • Added isPublic flag to lobby model
  • Built /lobbies page with auto-refresh (every 5s)
  • REST API endpoint: GET /api/lobbies/public
  • Players can now browse and join public races

2. Custom Text Passages (Dec 8)

Another user mentioned using it for typing exam prep in India. They needed to practice specific passages.

So I added:

  • "Custom" as a 4th language option (alongside English/German/French)
  • Textarea for pasting any text (no length limits)
  • Full Unicode support (handles emoji, Chinese characters, German umlauts, etc.)
  • Text persists across multiple rounds for practice

Turned a typing game into a typing exam prep tool with one feature.

Technical Highlights

Real-time synchronization:

// Go backend broadcasts to all clients in a lobby
func (h *Hub) BroadcastToLobby(lobbyCode string, message []byte) {
    h.mu.RLock()
    defer h.mu.RUnlock()

    for client := range h.clients {
        if client.LobbyCode == lobbyCode {
            client.send <- message
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
Unicode handling on frontend:
// Use Array.from() instead of .split() for proper multi-byte char support
const chars = Array.from(text); // ✅ Works with emoji, ä, ö, ß, 中文
const chars = text.split('');   // ❌ Breaks multi-byte characters
Enter fullscreen mode Exit fullscreen mode

What I Learned

  1. Launch fast, iterate faster - V1 wasn't perfect, but feedback made V2 way better
  2. Users will tell you what they need - Both features came from user requests
  3. Technical choices matter - WebSocket is perfect for this use case
  4. New use cases emerge - Never expected typing exam prep to be a use case!

Try it

👉 https://typechamp.com

It's free, no signup required. Create a lobby and share the 6-character code with friends (or join a public lobby).

Would love your feedback - especially from the dev.to community!

What's Next?

  • Product Hunt launch (once I have more traction)
  • Competitive ranked mode with matchmaking (planned for January)
  • Leaderboards and user profiles

Built in public. Shipped fast. Learning as I go.

Follow along: https://twitter.com/typechamp

Top comments (0)