Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/smogon/pokemon-showdown-client/llms.txt

Use this file to discover all available pages before exploring further.

The Pokémon Showdown client is a browser-based application that powers play.pokemonshowdown.com. Contributing to it requires a build step — TypeScript and JSX source files are compiled down to browser-compatible JavaScript before you can test changes. Once your environment is set up, the iteration loop is fast: edit a source file, run node build, and reload the test client in your browser.

Prerequisites

Before cloning the repository, make sure the following tools are available on your system:

Node.js v20+

The build system and test runner both require Node.js version 20 or later. Download from nodejs.org.

Git

Used to clone the repository and manage branches for pull requests. Any recent version of Git will work.

Setting Up the Repository

1

Clone the repository

Clone the client repository from GitHub:
git clone https://github.com/smogon/pokemon-showdown-client
cd pokemon-showdown-client
2

Run the initial build

The repository is not pre-built, so you must compile the source files before opening the test client. On Windows:
node build
On macOS and Linux you can also use the shorthand:
./build
This compiles all TypeScript and TSX source files from play.pokemonshowdown.com/src/ into the play.pokemonshowdown.com/js/ output directory.
3

Open the test client

Open testclient-old.html (stable client) or testclient-new.html (beta Preact rewrite) in your browser. No local server is required for basic testing.
The new Preact client is available at testclient-new.html and mirrors the live beta at https://play.pokemonshowdown.com/beta. Prefer this file if you are contributing to the rewritten client.
4

Configure a test key (recommended)

By default, logging in on the test client requires copy-pasting session data. For frequent reloads, create config/testclient-key.js with the following content:
const POKEMON_SHOWDOWN_TESTCLIENT_KEY = 'sid';
Replace 'sid' with the actual value of your sid cookie, which you can retrieve from:
https://play.pokemonshowdown.com/testclient-key.php
Place the file in config/, not play.pokemonshowdown.com/config/. The test key is the only supported login method for testclient-new.html.
5

Make changes and rebuild

After editing any source file under play.pokemonshowdown.com/src/, rerun the build and reload the test client:
node build
Use node build full for a clean, non-incremental rebuild:
node build full

Build Commands

All scripts are defined in package.json. The primary entry point is node build, which performs an incremental compile using the custom build-tools/compiler.js wrapper around Babel.
# Incremental build — only recompiles files that have changed
node build
Run npm run fix before committing to auto-resolve formatting violations reported by ESLint. This avoids failing the lint step in the full test suite.

The Build System

The build system lives in build-tools/compiler.js — a lightweight wrapper around @babel/core that adds incremental compilation on top of what babel-cli provides. It reads .babelrc for its plugin configuration and writes compiled output alongside source maps. Key behaviours:
  • Incremental by default — files are skipped if the source ctime is older than the destination ctime, making typical rebuilds fast.
  • Source maps.map files are written alongside compiled .js files so browser DevTools can map errors back to TypeScript source.
  • Concatenation — multiple source files can be combined into a single output bundle with a merged source map.
Output lands in play.pokemonshowdown.com/js/ and related subdirectories (replay.pokemonshowdown.com/, teams.pokemonshowdown.com/).

Running Tests

The test suite is run by Mocha and lives in the test/ directory:
FileWhat it tests
test/battle.test.jsBattle simulation logic
test/ev-guesser.test.jsEV guesser heuristics
test/ev-optimizer.test.jsEV optimizer output
To run only the Mocha tests without the full build and lint pipeline:
mocha test/*.js
The npm run test command combines all checks in the correct order:
node build && tsc && eslint --cache --cache-location caches/eslintcache.json --max-warnings 0 && mocha test/*.js
tsc is run with noEmit: true (see tsconfig.json) — it performs type-checking only and does not produce output files. Babel handles the actual compilation.

Connecting to Other Servers

You can point the test client at any Pokémon Showdown server by appending ?~~host:port to the URL:
testclient-old.html?~~localhost:8000
Some browsers convert ? to %3F when loading files from the local filesystem. If this happens, serve the files with a local HTTP server:
npx http-server .
Then navigate to http://localhost:8080/testclient-old.html?~~localhost:8000.

Code Ownership

The CODEOWNERS file designates specific reviewers for certain parts of the codebase. Pull requests touching these paths will automatically request a review from the listed maintainers:
PathOwner
play.pokemonshowdown.com/src/battle-animations-moves.ts@KrisXV
play.pokemonshowdown.com/src/battle-animations.ts@KrisXV
teams.pokemonshowdown.com/**/*@mia-pi-git
If your changes touch battle animations or the teams subsite, expect review from the listed owners before your PR is merged.

Architecture Overview

The client loads in four phases to balance startup speed with feature availability:
  • client.css — basic styling
  • client-core.ts — background model and view
  • client-main.ts — Prefs, Teams, User, Room, and PS models
  • client-connection.ts — server connection via SockJS
  • panel-mainmenu.tsx, panel-rooms.tsx, panels.tsx — URL router, global listeners, and main view
  • panel-chat.tsx — chat panel
  • panel-ladder.tsx — ladder panel
Loaded only when the user opens a battle or the teambuilder:
  • panel-battle.tsx, panel-teambuilder.tsx
  • battle-dex.ts, battle.ts
  • jQuery (loaded here, not earlier)
Avoid using jQuery in Phase 1–3 files. Interact with the DOM directly, being careful not to use APIs that crash IE9.

Build docs developers (and LLMs) love