Thank you for taking the time to contribute; every little bit helps! This project is entirely open-source and unmonetized - community contributions are what keep it alive!
Please make sure you understand everything relevant to your changes from the Table of Contents, and absolutely feel free to reach out in the #pokerogue-dev channel on Discord. We are here to help and the better you understand what you're working on, the easier it will be for it to find its way into the game.
As per GitHub's terms of service, any contributions made to this repository will be licensed under this repository's terms. If you use any external code, please make sure to follow its licensing information. Please make use of SPDX snippets for any portion of the file that is licensed differently.
PokéRogue is built with TypeScript, using the Phaser game framework.
If you have the motivation and experience with TypeScript/JavaScript (or are willing to learn), you can contribute by forking the repository and making pull requests with contributions.
Arguably the easiest way to get started is by using the prepared development environment.
We have a .devcontainer/devcontainer.json file, meaning we are compatible with:
This Linux environment comes with all required dependencies needed to start working on the project.
Due to quirks of devcontainer port forwarding, you must use pnpm start:podman to start a local dev server from within a devcontainer.
All other instructions remain the same as local development.
For those who prefer Docker containers, see this instructions page for information on how to setup a development environment with Podman.
npm on Windows native) | alternate method - volta.shpnpm install from the repository root
pnpm start:dev to locally run the project at localhost:8000A great way to develop an understanding of how the project works is to look at test cases (located in the test folder).
Tests show you both how things are supposed to work and the expected "flow" to get from point A to point B in battles.
This is a big project and you will be confused at times - never be afraid to reach out and ask questions in #pokerogue-dev!
Once you have your feet under you, check out the Issues page to see how you can help us!
Most issues are bugs and are labeled with their area, such as Move, Ability, UI/UX, etc. There are also priority labels:
P0: Completely gamebreaking (very rare)P1: Major - Game crashP2: Minor - Incorrect (but non-crashing) move/ability/interactionP3: No gameplay impact - typo, minor graphical error, etc.Also under issues, you can take a look at the List of Partial / Unimplemented Moves and Abilities and the Bug Board. The latter is essentially the same as the issues page, so take your pick.
You are free to comment on any issue so that you may be assigned to it and we can avoid multiple people working on the same thing.
You can find the auto-generated API documentation here. It can be incomplete at times (as many methods lack documentation comments), but it's a great way to get a look at the overall structure of the codebase and find particular methods or classes you may be looking for.
Additionally, the docs folder contains a variety of in-depth documents and guides useful for aspiring contributors.
Notable topics include:
Again, please feel free to ask any questions you may have!
You've just made a change - how can you check if it works?
You have two areas to hit:
This will likely be your first stop. After making a change, you'll want to spin the game up and make sure everything is as you expect. To do this, you will need a way to manipulate the game to produce the situation you're looking to test.
src/overrides.ts contains overrides for most values you'll need to change for testing, controlled through the overrides object.
There are a variety of overrides available, ranging from changing movesets and abilities to modifying battle conditions and forcing specific scenarios.
For example, here is how you could test a scenario where the player Pokemon has the ability Drought and the enemy Pokemon has the move Water Gun:
const overrides = {
ABILITY_OVERRIDE: AbilityId.DROUGHT,
ENEMY_MOVESET_OVERRIDE: MoveId.WATER_GUN,
} satisfies Partial<InstanceType<typeof DefaultOverrides>>;
If the situation you're trying to test can't be created using existing overrides (or with the Dev Save), reach out in #pokerogue-dev. You can get help testing your specific changes, and you might have found a new override that needs to be created!
PokéRogue uses Vitest for automated testing. Checking out existing tests in the test folder is a great way to understand how the existing system works, as well as familiarizing yourself with the project as a whole.
Most non-trivial changes (especially bug fixes) should be accompanied by one or more new automated test cases.
To create a new test file, run pnpm test:create and follow the on-screen prompts.
If the move/ability/etc. you're modifying already has tests, you can add new cases to the test file or edit existing ones.
Ensure that new test cases:
it.todo. Once the edge case has been handled, you can remove the todo marker.
Testing UI-related code within the automated test harness is usually a bad idea.
While it can be done, such tests tend to be boilerplate-heavy, hard to maintain and prone to randomly breaking/timing out.
If your change is primarily UI-related, it's usually best to test it manually and only use automated tests for the underlying logic (if applicable).
While Vitest does support both Jest and Chai syntax for assertions, our project exclusively uses Jest-style assertions (...toBe(), ...toEqual(), etc.) for internal consistency. (The Chai variants have been blacklisted via TypeScript declaration merging, ensuring they aren't accidentally used by mistake.)
To make sure your changes didn't break any existing test cases, run pnpm test:silent <files> in your terminal to run test files associated with your changes.
You can provide additional arguments to the command to alter its behavior;
a full list of supported arguments can be found on Vitest's website.
Passing all test cases does not guarantee that everything is working properly. The project does not have complete regression testing, so manual verification is still advised for most changes.
Some issues may require you to have unlocks on your save file which go beyond normal overrides. For this reason, the repository contains a save file with everything unlocked (including things not legitimately obtainable, like unreleased variant shinies).
Menu -> Manage Data -> Import Datatest/utils/saves/everything.prsv) and hit "Confirm".Most information related to submitting a pull request is contained within comments inside the default pull request template.
This section serves to elaborate on particular parts of the PR creation workflow that cannot fit fully inside the margins.
This repository follows the Conventional Commits standard for PR titles, enforced by an automated GitHub Actions workflow.
Each PR must contain a valid prefix (and optionally a valid scope), followed by a colon and then the PR's subject line. \
fix(move): Future Sight no longer crashes
^ ^ ^
| | |__ Subject
| |_________ Scope (optional)
|_____________ Prefix
If a save migrator, version increase or other breaking change is part of the PR, a ! must be added before the :.
Try to keep the title under 72 characters, as GitHub cuts off commit titles longer than this length.
refactor(data)!: improve serialization of Pokemon save data
balance: update TM compatibility lists
fix(move): Retaliate now saves power boost between waves
test: preserve text output of original shards
./github/** directory
All scopes are valid when using the "docs", "feat", "fix", "refactor" and "test" prefixes.
All scopes except "audio", "battle", "graphics", and "ui" are valid when using the "balance" prefix.
No other prefixes have valid scopes.
There is a special "beta" scope for the "fix" prefix,
for fixing bugs that only existed on the beta branch that never made it onto main.