Skip to content

zraisan/keystrike

Repository files navigation

KeyStrike

A modern, real-time typing speed test application with multiplayer racing capabilities.
Practice your typing skills solo or compete against friends in live races.

Live Demo

Next.js React TypeScript
Socket.io Three.js License

KeyStrike Screenshot

Features

Solo Typing Test

  • Real-time WPM (Words Per Minute) calculation
  • Accuracy percentage tracking
  • Dynamic text generation using Markov chains

Multiplayer Racing

  • Create or join rooms with unique 6-character codes
  • Real-time progress synchronization across players
  • Live WPM tracking during races
  • Finish position indicators

Interactive 3D Visuals

  • Three.js powered 3D keyboard key animations
  • Interactive orbit controls

Tech Stack

Category Technologies
Frontend Next.js 15, React 19, TypeScript 5
Styling Tailwind CSS 4, Shadcn UI
3D Graphics Three.js
Real-time Socket.io
Backend Express.js 5
Tooling Bun, Turbopack, Biome

Architecture

System Overview

graph TB
    subgraph Client["Client (Browser)"]
        UI[React Components]
        Socket[Socket.io Client]
        Three[Three.js 3D Renderer]
    end

    subgraph Server["Server (Node.js/Bun)"]
        Express[Express.js]
        SocketServer[Socket.io Server]
        NextHandler[Next.js SSR Handler]
        RoomManager[Room Manager]
    end

    UI --> Socket
    UI --> Three
    Socket <-->|WebSocket| SocketServer
    Express --> NextHandler
    SocketServer --> RoomManager

    style Client fill:#234C6A,color:#fff
    style Server fill:#1B3C53,color:#fff
Loading

Multiplayer Flow

sequenceDiagram
    participant P1 as Player 1
    participant S as Server
    participant P2 as Player 2

    P1->>S: join_room (roomId, username)
    S->>P1: room_players (existing players)

    P2->>S: join_room (roomId, username)
    S->>P1: new_player (P2 info)
    S->>P2: room_players (existing players)

    P1->>S: paragraph_set (text)
    S->>P1: room_paragraph (text)
    S->>P2: room_paragraph (text)

    loop Typing Race
        P1->>S: send_keystroke (progress)
        S->>P2: receive_keystroke (P1 progress)
        P2->>S: send_keystroke (progress)
        S->>P1: receive_keystroke (P2 progress)
    end

    P1->>S: Race Complete
    Note over P1: Confetti if 1st place
Loading

Component Architecture

graph LR
    subgraph Pages
        Home["/"]
        Type["/type"]
        Multi["/multiplayer"]
    end

    subgraph Components
        Keyboard[Keyboard.tsx<br/>3D Key]
        Header[Header.tsx]
        UI[UI Components]
    end

    subgraph Hooks
        UseSocket[useSocket.tsx]
    end

    subgraph Utilities
        Markov[markov.ts<br/>Text Generation]
        Utils[utils.ts]
    end

    Home --> Keyboard
    Type --> Markov
    Multi --> UseSocket
    Multi --> Markov
    UseSocket -->|Socket.io| Server[(Server)]

    style Pages fill:#456882,color:#fff
    style Components fill:#234C6A,color:#fff
    style Hooks fill:#1B3C53,color:#fff
Loading

Room State Management

stateDiagram-v2
    [*] --> Lobby: User opens /multiplayer
    Lobby --> WaitingRoom: Creates/Joins room
    WaitingRoom --> Racing: Host starts game
    Racing --> Finished: User completes text
    Finished --> WaitingRoom: Play Again
    Finished --> Lobby: Leave Room
    WaitingRoom --> Lobby: Leave Room
Loading

Getting Started

Prerequisites

  • Bun (recommended) or Node.js 18+

Installation

# Clone the repository
git clone https://github.com/yourusername/keyflow.git
cd keyflow

# Install dependencies
bun install

Development

# Start the development server (includes Socket.io server)
bun run dev

Open http://localhost:4000 in your browser.

Production

# Build the application
bun run build

# Start production server
bun start

Socket Events

Event Direction Payload Description
join_room Client → Server roomId Join a specific room
player_joined Client → Server { room, username } Announce player with username
send_keystroke Client → Server { room, message, sender, username } Broadcast typing progress
receive_keystroke Server → Client { message, sender, username } Receive others' progress
new_player Server → Client { id, username } New player joined notification
room_players Server → Client Player[] List of current players
player_left Server → Client playerId Player disconnection
paragraph_set Client → Server { room, paragraph } Set race text
room_paragraph Server → Client paragraph Receive race text

Environment Variables

Variable Default Description
PORT 4000 Server port
CORS_ORIGIN localhost:3000,localhost:4000 Allowed CORS origins (comma-separated)
NODE_ENV development Environment mode

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Race against friends, track WPM & accuracy, and compete in live rooms powered by Socket.io.

Topics

Resources

License

Stars

5 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors