Skip to main content
Pokemon Showdown is a comprehensive battle simulator with a multi-component architecture designed for scalability and flexibility.

System Overview

At the highest level, Pokemon Showdown is split into three major components that communicate directly with each other:

Game Server

Handles chat, matchmaking, and battle simulation

Client

Web interface for users to battle

Login Server

Manages authentication and databases

Component Architecture

Game Server

The game server is written in TypeScript and runs on Node.js. It’s the core of the Pokemon Showdown system.
1

Entry Point

The server starts at server/index.ts, which launches several major components:
2

Socket Management

server/sockets.ts sets up a SockJS (abstracted WebSocket) server to accept connections from clients.
3

User Management

server/users.ts wraps SockJS connections in a user management system.
4

Room Management

server/rooms.ts handles individual chat rooms and battle rooms.
5

Chat System

server/chat.ts processes chat commands and messages from users. All client-to-server commands are routed through the chat system.

Battle Simulation

The Rooms system includes support for battle rooms, which connect to the game simulator. All game simulation code lives in the sim/ directory.
// Battle simulation is integrated into rooms
import { BattleStream } from './sim/battle-stream';
import { Teams } from './sim/teams';

// The simulator uses streams for battle communication
const stream = new BattleStream();
The simulator can be used as a standalone library via npm: npm install pokemon-showdown

Client

The client is built with a mix of TypeScript and JavaScript, using a mostly hand-rolled framework built on Backbone. Key Details:
  • Entry point: index.template.html
  • Main logic: js/client.js
  • Architecture: Legacy design with multiple JS files (pre-dates modern bundlers)
  • Migration status: Rewrite to Preact is in progress but stalled
The client uses an older architecture pattern. A Preact rewrite is planned but not yet complete.

Login Server

The login server handles authentication and database operations. It’s written in TypeScript. Architecture:
  • Entry point: server.ts
  • MySQL InnoDB database: Users, ladder, and most data
  • Postgres (Cockroach) database: Replays
  • Migration: Replacing legacy PHP code from the client (halfway complete)

Communication Flow

Here’s how the components interact when a user plays:
1

Initial Connection

User visits https://play.pokemonshowdown.com/, served by Apache (static files + legacy PHP).
2

Authentication

Browser communicates with Login Server at https://play.pokemonshowdown.com/api/ for authentication and database operations.
3

Game Connection

Browser connects to Game Server via SockJS for chat rooms, matchmaking, and battles.
4

Replay Storage

Game Server communicates with Login Server to handle replay uploads and ladder updates.

Technology Stack

Game Server

  • Runtime: Node.js v16+
  • Language: TypeScript
  • WebSockets: SockJS
  • Simulation: Custom battle engine

Client

  • Framework: Backbone (migrating to Preact)
  • Languages: TypeScript + JavaScript
  • Server: Apache
  • Legacy: PHP (being replaced)

Login Server

  • Language: TypeScript
  • Databases: MySQL InnoDB, Postgres
  • Purpose: Auth + data persistence

Simulator

  • Language: TypeScript
  • Generations: 1-9 support
  • Formats: Singles, doubles, triples
  • API: Stream-based

Core Modules

The game server is organized into several key modules:
ModuleLocationPurpose
Socketsserver/sockets.tsWebSocket connection management
Usersserver/users.tsUser session and authentication
Roomsserver/rooms.tsChat and battle room logic
Chatserver/chat.tsCommand processing and messaging
Simulatorsim/Battle engine and game mechanics
Dexsim/dex.tsPokemon data and Pokedex
Teamssim/teams.tsTeam validation and generation

Battle Simulator Architecture

The simulator implements an ObjectReadWriteStream pattern:
  • Write: Player choices (strings)
  • Read: Protocol messages (strings)
import { BattleStream } from 'pokemon-showdown';

const stream = new BattleStream();

// Write commands to the simulator
stream.write(`>start {"formatid":"gen7randombattle"}`);
stream.write(`>player p1 {"name":"Alice"}`);
stream.write(`>player p2 {"name":"Bob"}`);

// Read battle messages
for await (const output of stream) {
    console.log(output);
}

Simulator Components

Battle Stream

Core communication layer using streams

Battle Engine

Game logic, moves, abilities, items

Dex

Pokemon species, moves, abilities data

Team Validator

Format rules and team validation

Running Your Own Server

The game server can be run independently for hosting custom communities:
# Install and run
./pokemon-showdown

# Or with Node.js directly
node pokemon-showdown

# Specify a port
node pokemon-showdown 8000
Default port is 8000. Visit your server at http://localhost:8000 for local testing.

Server

Game server repository

Client

Client repository

Login Server

Login server repository

Design Philosophy

Modularity

Clear separation between server, client, and auth

Extensibility

Custom game modes and formats supported

Streams

Stream-based architecture for battle simulation

TypeScript

Fully typed API with comprehensive definitions

Next Steps

Battle Simulator

Learn the simulator API in detail

Protocol

Understand the communication protocol

Running a Server

Host your own Pokemon Showdown server

Contributing

Contribute to the project

Build docs developers (and LLMs) love