The Pokémon Showdown client is entirely driven by a globalDocumentation 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.
Config object that is injected into the page as a <script> tag before any client JavaScript runs. When you visit play.pokemonshowdown.com, this object is served dynamically by the production PS server at /config/config.js. When you run your own instance or use the test client, you control it yourself — making it the single most important file to understand before customizing the client.
The PSConfig Interface
The Config global is typed as PSConfig in TypeScript (declared in play.pokemonshowdown.com/src/client-main.ts):
Field Reference
server
The active server the client connects to. The test client overrides this from the
?~~host:port query string. Contains the WebSocket host, port, prefix path, and flags like afd and registered.defaultserver
The server to use when the page is loaded from the canonical
Config.routes.client domain. The production config points this to sim3.psim.us:443. Your own builds should point it at your server host.routes
Six URL prefixes (no trailing slash) that the client uses to construct links to the Pokédex, replays, user pages, and the teams builder. The production values come from
config/routes.json.customcolors
A plain object mapping lowercase usernames to hex color strings. These override the algorithmic color generation for specific users. Example:
{ "zarel": "aeo" }.whitelist
Optional. When present, restricts which server IDs the client will allow connections to. The production whitelist is a large list of approved domains maintained server-side.
testclient
A boolean flag set to
true inside testclient-old.html immediately after loading config.js. It unlocks test-only UI elements and relaxes certain production-only guards.How Config Is Loaded
The client never fetchesConfig — it relies on the server to inject it as a plain <script> tag before any client bundle runs. In the test client HTML (testclient-old.html), you can see this pattern directly:
The test client deliberately loads the production
config.js and then mutates Config inline. This means your local test instance inherits the production route URLs, whitelist, and custom colors — and only overrides server and testclient.Sample Config Structure
For your own Pokémon Showdown server deployment, yourconfig/config.js should follow this pattern (based on config/config-example.js):
Production vs. Custom Instances
Production: config served dynamically by the server
Production: config served dynamically by the server
On
play.pokemonshowdown.com, the server generates config.js dynamically and includes the full whitelist, registered server information, and custom color assignments for all known users. You do not interact with this file directly — it is controlled by the Pokémon Showdown team.Custom instance: you control config.js entirely
Custom instance: you control config.js entirely
When running your own instance of the client, you must provide your own
config.js. The minimum required fields are defaultserver (your server’s host and port) and routes (the URL domains for cross-links). All other fields are optional.Copy config/config-example.js as your starting point and adjust the defaultserver and routes fields to match your deployment.Test client: inherits production config, mutates server
Test client: inherits production config, mutates server
The test client (
testclient-old.html) is a special case: it loads the production config.js from play.pokemonshowdown.com and then immediately overrides Config.server from the query string and sets Config.testclient = true. This means you get production routes and custom colors for free, while pointing the socket connection at a local or custom server.TypeScript Declaration
BecauseConfig is injected via a <script> tag and not an ES module import, TypeScript only knows about it through an ambient declaration in client-main.ts:
Config will be present at runtime but does not bundle or validate the actual JS file. If your config.js is missing or malformed, the client will fail silently or throw runtime errors — there is no compile-time check.
