PKSX is an offline-first Pokemon save management app. The app uses a controller-friendly SvelteKit UI and a C# WebAssembly PKHeX Engine that wraps PKHeX.Core for save parsing, validation, legality, serialization, and mutation work.
The first milestone is a browser/PWA tracer bullet: prove that the Svelte app can load local save bytes, call PKHeX-compatible logic through WebAssembly, and keep user-controlled import/export workflows explicit.
| Environment | URL | Deployment |
|---|---|---|
| Production | pksx.app | Signed vX.Y.Z release tags from main |
| Staging | staging.pksx.app | Every push to main |
- Frontend: SvelteKit 2, Svelte 5, Tailwind CSS, static adapter
- Engine: .NET
browser-wasmproject inengine/Pksx.Pkhex.Engine - PKHeX source: pinned
PKHeX.CoreNuGet package by default, optional local PKHeX source checkout for upstream testing - Storage direction: app-managed Saves for imported save artifacts, backups, and future bank data
- Primary UX direction: box-first, controller-friendly save management
PKSX should stay aligned with upstream PKHeX behavior. Prefer wrapping PKHeX.Core over reimplementing Pokemon save logic in TypeScript.
- Node.js 23.6 or newer
- The engine sync script is TypeScript and runs through Node's native type stripping.
- pnpm
- .NET 10 SDK
- .NET WebAssembly workload:
dotnet workload install wasm-toolsInstall dependencies:
pnpm installStart the development server through Portless:
pnpm devThis serves the app at https://pksx.localhost. On first run, Portless may ask to trust its local development CA so it can serve HTTPS locally.
Open the app automatically:
pnpm dev -- --open| Command | Purpose |
|---|---|
pnpm dev |
Start the Vite/SvelteKit dev server through Portless at https://pksx.localhost. |
pnpm build |
Build the static production app. |
pnpm preview |
Preview the production build locally. |
pnpm engine:sync |
Publish the PKHeX Engine and sync generated browser WASM assets into static/pkhex-engine. |
pnpm legal:sync |
Copy the license, source location, and third-party notices into static/legal. |
pnpm item-sprites:download |
Refresh the pinned offline item sprite catalog. |
pnpm item-sprites:validate |
Validate the committed item sprite manifest and files without network access. |
pnpm typecheck |
Run svelte-check and TypeScript checks for scripts/**/*.ts. |
pnpm check |
Alias for pnpm typecheck. |
pnpm check:watch |
Run Svelte type checking in watch mode. |
pnpm native:sync:ios |
Build the web app and sync it into the Capacitor iOS project. |
pnpm ios:open |
Open the native iOS project in Xcode. |
pnpm ios:build |
Build and sync the web app, then compile an unsigned iOS Simulator app. |
pnpm test:ios |
Run native controller acceptance tests in an iPhone simulator. |
pnpm native:sync:android |
Build the web app and sync it into the Capacitor Android project. |
pnpm android:open |
Open the native Android project in Android Studio. |
pnpm android:build |
Build and sync the web app, then assemble an Android debug APK. |
pnpm android:run |
Build PKSX, start the visible Android emulator, install it, and launch the app. |
pnpm test:android |
Run native controller acceptance tests on the API 36 test emulator. |
pnpm lint |
Check Prettier formatting and ESLint. |
pnpm format |
Format the repo with Prettier. |
pnpm test:unit -- --run |
Run unit tests once. |
pnpm test:e2e |
Run Playwright tests. Currently passes when no E2E tests exist. |
pnpm test |
Run unit tests and Playwright tests. |
See Android testing and iOS testing for the one-time simulator setup and headless local acceptance-test workflows.
The Svelte app loads the engine from /pkhex-engine, which maps to generated static files under static/pkhex-engine.
Generate those assets with:
pnpm engine:syncThe command:
- Publishes
engine/Pksx.Pkhex.Enginewithdotnet publish. - Defaults to
Release. - Verifies the
.NETSDK andwasm-toolsworkload are present. - Removes any existing
static/pkhex-engine. - Copies the published
AppBundleintostatic/pkhex-engine.
static/pkhex-engine is generated output and is ignored by git.
engine/Pksx.Pkhex.Engine/main.js is the required browser WebAssembly boot entry selected by WasmMainJSPath. Its _framework/dotnet.js dependency is generated into the published AppBundle, so focused Fallow suppressions cover that build-time boundary.
pnpm engine:sync -- --configuration DebugBy default, PKSX uses the pinned PKHeX.Core NuGet package from Directory.Packages.props.
To test against a local PKHeX checkout instead:
pnpm engine:sync -- --property UseLocalPKHeX=true --property PKHeXSourcePath=/path/to/PKHeX/PKHeX.Core/PKHeX.Core.csprojThis uses the Directory.Build.targets source override and swaps the NuGet package reference for a local ProjectReference.
PKSX selects its Saves adapter at runtime. Web and installed PWA builds use IndexedDB. Native Capacitor builds detected by Capacitor.isNativePlatform() use the official Filesystem plugin with Directory.Data.
The native adapter stores imported saves, active Workspace bytes, and Backups as binary files under pksx-saves. A versioned JSON catalog stores metadata, while Pokemon Storage uses a separate JSON file. Raw Save File and Backup bytes never enter TinyBase, and unchanged Export reads the original imported file.
After adding or updating a native platform project, run pnpm exec cap sync. The iOS project includes the Filesystem plugin's required privacy manifest entry for App Store submission.
PKHeX.Coreversion is pinned inDirectory.Packages.props.- The PKSX facade version is reported by the engine through
GetVersionJson(). - Updating upstream PKHeX behavior should happen by changing the pinned package version, publishing the engine, and validating the Svelte-side contract.
engine/Pksx.Pkhex.Engine/ C# browser-wasm PKHeX Engine
scripts/ Node-executed TypeScript maintenance scripts
src/lib/engine/ Svelte-side engine API, mock engine, and WASM loader
src/lib/pksx/saves/ Saves storage primitives
src/routes/ SvelteKit app routes
static/ Static assets served by SvelteKit
docs/architecture/ Architecture notes and reference-project findings
docs/adr/ Architecture decision records
CONTEXT.md Project glossary and domain language
The following are generated and should not be committed:
static/pkhex-enginestatic/legal.svelte-kitbuildengine/**/binengine/**/objsrc/lib/paraglideif Paraglide is reintroduced later
- Domain glossary
- Reference projects
- PKHeX Engine spike
- ADR: C# WebAssembly PKHeX Engine
- ADR: App-managed Saves
- ADR: Box-first controller UI
- ADR: Keep save artifacts out of TinyBase
Copyright (C) 2026 Rajan Singh and PKSX contributors.
Except where a file or directory says otherwise, PKSX source code is free software licensed under the GNU General Public License, version 3 or later. You may redistribute and modify it under GPL version 3 or, at your option, any later version.
PKSX links and distributes PKHeX.Core, which uses the same GPL-3.0-or-later license. See third-party notices for its attribution and for content that the PKSX license does not cover, including PokemonDB sprite images and third-party save fixtures.
Production builds copy the license, third-party notices, and exact source revision into /legal. The repository includes the source and build scripts needed to produce the web, WebAssembly, iOS, and Android builds.