A web app that allows you to fully customize your Risk of Rain 2 savefile.
| Challenges | Logbook |
|---|---|
![]() |
![]() |
https://comeixalpha.github.io/ror2-editor/index.html
Hosted as part of comeixalpha.github.io — or build it from source, below.
This project is a fork of tjosepo/ror2-editor, the original editor. All credit for the original application goes there; the fork exists to carry the features listed below.
What the fork adds on top of the original:
- Support for the base game plus all four expansions — Survivors of the Void, Seekers of the Storm, Alloyed Collective and Hallowed Concepts — 205 achievements in total.
- A Logbook tab that mirrors the in-game journal: the game's own artwork, the game's own ordering, and each item's real functional description.
- An English / Chinese interface, using the game's own translations for game content.
- Save validation derived from the game's deserialiser, so a broken profile is explained rather than silently written.
This repository is the source. The hosted copy is published from the comeixalpha.github.io Pages site, whose build checks this repository out and mounts it at /ror2-editor/, so that deployment always reflects main here.
The app makes no network requests of its own: loading, editing and exporting a profile all happen in the browser, and the save never leaves the machine.
This project uses pnpm. With pnpm 10 or newer, most settings live in pnpm-workspace.yaml rather than .npmrc.
pnpm install
pnpm build
Run the development server with:
pnpm dev
Run the test suite with:
pnpm test
pnpm build produces a root-relative bundle, which is what pnpm dev and a root deployment want. To serve it from a sub-path, pass a base:
pnpm build --base=/ror2-editor/
The ComeixAlpha Pages site serves the editor that way: its workflow checks this repository out, builds it with that flag, and drops the result into its own public/ directory. The entry point is the explicit /ror2-editor/index.html rather than the bare directory — see the note in that repository's src/lib/shared.ts for why.
Vite rewrites the paths it generates, but not the ones this app builds by hand — the icon and logbook image URLs. Those go through import.meta.env.BASE_URL (see src/lib/public-url.ts) so they follow the same prefix instead of resolving against the domain root.
pnpm install needs to run dependency install scripts for esbuild. It is allow-listed in pnpm-workspace.yaml; without it vite cannot find its esbuild binary. If you are behind a proxy, Node does not read the Windows system proxy — set HTTPS_PROXY/HTTP_PROXY, or uncomment the proxy entries in .npmrc.
The editor does not use hand-written tables. Everything under src/data/generated/ is extracted from an installed copy of the game.
The extracted data is committed, so building the app needs no copy of the game. It covers the achievements and their icons, the logbook — all 618 entries with their artwork and each pickup's functional description — and the loadout viewables.
Only the nodes the editor manages are touched. Every other element, attribute and token in the profile is carried through byte-for-byte, so a save from a newer game version survives an edit instead of being silently trimmed. tests/xml.test.mjs asserts a byte-identical round-trip on a real 552 KB profile.
Achievements and unlockables are two independent lists: granting an achievement writes the id to <achievementsList> and the reward string to <stats><unlock>, because writing only the achievement does nothing in-game.

