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
isPublicflag to lobby model - Built
/lobbiespage 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
}
}
}
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
What I Learned
- Launch fast, iterate faster - V1 wasn't perfect, but feedback made V2 way better
- Users will tell you what they need - Both features came from user requests
- Technical choices matter - WebSocket is perfect for this use case
- New use cases emerge - Never expected typing exam prep to be a use case!
Try it
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.
Top comments (0)