Skip to content

ptrlrd/spire-codex

Repository files navigation

Spire Codex

A comprehensive database and API for Slay the Spire 2 game data, built by reverse-engineering the game files. Supports all 14 languages shipped with the game.

Live site: spire-codex.com

Steam App ID: 2868840

How It Was Built

Slay the Spire 2 is built with Godot 4 but all game logic lives in a C#/.NET 8 DLL (sts2.dll), not GDScript. The data pipeline:

  1. PCK ExtractionGDRE Tools extracts the Godot .pck file to recover images, Spine animations, and localization data (~9,947 files).

  2. DLL DecompilationILSpy decompiles sts2.dll into ~3,300 readable C# source files containing all game models.

  3. Data Parsing — 20 Python regex-based parsers extract structured data from the decompiled C# source, outputting per-language JSON to data/{lang}/:

    • Cards: base(cost, CardType, CardRarity, TargetType) constructors + DamageVar, BlockVar, PowerVar<T> for stats
    • Characters: StartingHp, StartingGold, MaxEnergy, StartingDeck, StartingRelics
    • Relics/Potions: Rarity, pool, descriptions resolved from SmartFormat templates
    • Monsters: HP ranges, ascension scaling via AscensionHelper, move state machines with per-move intents (Attack/Defend/Buff/Debuff/Status/Summon/Heal), damage values, powers applied per move (target + amount from PowerCmd.Apply<T>), block, healing, encounter context (act, room type)
    • Enchantments: Card type restrictions, stackability, Amount-based scaling
    • Encounters: Monster compositions, room type (Boss/Elite/Monster), act placement, tags
    • Events: Multi-page decision trees (56 of 66 events), choices with outcomes, act placement, StringVar model references resolved to display names
    • Ancients: 8 Ancient NPCs with epithets, character-specific dialogue, relic offerings, portrait icons
    • Powers: PowerType (Buff/Debuff), PowerStackType (Counter/Single), DynamicVars, descriptions
    • Epochs/Stories: Timeline progression data with unlock requirements
    • Orbs: Passive/Evoke values, descriptions
    • Afflictions: Stackability, extra card text, descriptions
    • Modifiers: Run modifier descriptions
    • Keywords: Card keyword definitions (Exhaust, Ethereal, Innate, etc.)
    • Intents: Monster intent descriptions with icons
    • Achievements: Unlock conditions, descriptions
    • Acts: Boss discovery order, encounters, events, ancients, room counts
    • Ascension Levels: 11 levels (0–10) with descriptions from localization
    • Potion Pools: Character-specific pools parsed from pool classes and epoch references
    • Translations: Per-language filter maps (card types, rarities, keywords → localized names) and UI strings (section titles, descriptions, character names) for frontend consumption
  4. Description Resolution — A shared description_resolver.py module resolves SmartFormat localization templates ({Damage:diff()}, {Energy:energyIcons()}, {Cards:plural:card|cards}) into human-readable text with rich text markers for frontend rendering. Runtime-dynamic variables (e.g., {Card}, {Relic}) are preserved as readable placeholders. StringVar references in events (e.g., {Enchantment1}ModelDb.Enchantment<Sharp>().Title) are resolved to display names via localization lookup.

  5. Spine Rendering — Characters and monsters are Spine skeletal animations, not static images. A headless Node.js renderer assembles idle poses into 512×512 portrait PNGs. All 111 monsters have images: 100 rendered from Spine skeletons, 6 aliased from shared skeletons (Flyconid→flying_mushrooms, Ovicopter→egg_layer, Crusher/Rocket→kaiser_crab), and 5 from static game assets (Doormaker). Also renders all 5 characters (combat, rest site, character select poses), NPCs, and backgrounds. Skin-based variants (Cultists, Bowlbugs, Cubex) are rendered individually. See Spine Renderer below.

  6. Images — Card portraits, relic/potion icons, character art, monster sprites, Ancient portrait icons, and boss encounter icons extracted from game assets and served as static files.

  7. Changelog Diffing — A diff tool compares JSON data between game versions (via git refs or directories), tracking added/removed/changed entities per category with field-level diffs. Changelogs are keyed by Steam game version + optional Codex revision number.

Project Structure

spire-codex/
├── backend/                    # FastAPI backend
│   ├── app/
│   │   ├── main.py             # App entry, CORS, GZip, rate limiting, static files
│   │   ├── dependencies.py     # Shared deps (lang validation, language names)
│   │   ├── routers/            # API endpoints (22 routers)
│   │   ├── models/schemas.py   # Pydantic models
│   │   ├── services/           # JSON data loading (LRU cached, 14-lang support)
│   │   └── parsers/            # C# source → JSON parsers
│   │       ├── card_parser.py
│   │       ├── character_parser.py
│   │       ├── monster_parser.py
│   │       ├── relic_parser.py
│   │       ├── potion_parser.py
│   │       ├── enchantment_parser.py
│   │       ├── encounter_parser.py
│   │       ├── event_parser.py
│   │       ├── power_parser.py
│   │       ├── keyword_parser.py        # Keywords, intents, orbs, afflictions, modifiers, achievements
│   │       ├── epoch_parser.py
│   │       ├── act_parser.py
│   │       ├── ascension_parser.py
│   │       ├── pool_parser.py            # Adds character pool to potions
│   │       ├── translation_parser.py    # Generates translations.json per language
│   │       ├── description_resolver.py   # Shared SmartFormat resolver
│   │       └── parse_all.py              # Orchestrates all parsers (14 languages)
│   ├── static/images/          # Game images (not committed)
│   ├── scripts/copy_images.py  # Copies images from extraction → static
│   ├── Dockerfile
│   └── requirements.txt
├── frontend/                   # Next.js 16 + TypeScript + Tailwind CSS
│   ├── app/
│   │   ├── contexts/           # LanguageContext (i18n state + localStorage)
│   │   ├── components/         # CardGrid, RichDescription, SearchFilter,
│   │   │                       #   GlobalSearch, Navbar, Footer, LanguageSelector
│   │   └── ...                 # Pages: cards, characters, relics, monsters, potions,
│   │                           #   enchantments, encounters, events, powers, timeline,
│   │                           #   reference, images, changelog, about, merchant, compare
│   │                           #   Detail pages: cards/[id], characters/[id], relics/[id],
│   │                           #   monsters/[id], potions/[id], enchantments/[id],
│   │                           #   encounters/[id], events/[id], powers/[id], keywords/[id],
│   │                           #   acts/[id], ascensions/[id], intents/[id], orbs/[id],
│   │                           #   afflictions/[id], modifiers/[id], achievements/[id]
│   │                           #   i18n: [lang]/... mirrors all routes for 13 languages
│   ├── lib/
│   │   ├── api.ts              # API client + TypeScript interfaces
│   │   ├── fetch-cache.ts      # Client-side in-memory fetch cache (5min TTL)
│   │   ├── seo.ts              # Shared SEO utilities (stripTags, SITE_URL, SITE_NAME)
│   │   ├── jsonld.ts           # JSON-LD schema builders (BreadcrumbList, CollectionPage, Article, WebSite, FAQPage)
│   │   ├── ui-translations.ts # UI string translations for 13 languages
│   │   ├── languages.ts       # i18n config — 13 language codes, hreflang mappings
│   │   └── use-lang-prefix.ts # Hook for language-aware URL construction
│   └── Dockerfile
├── tools/
│   ├── spine-renderer/         # Headless Spine skeleton renderer
│   │   ├── render_webgl.mjs     # WebGL renderer (single skeleton) — no seam artifacts
│   │   ├── render_all_webgl.mjs # WebGL batch renderer (all .skel files)
│   │   ├── render.mjs           # Legacy canvas renderer (has triangle seams)
│   │   ├── render_all.mjs       # Legacy canvas batch renderer
│   │   ├── render_skins2.mjs    # Skin variant renderer
│   │   ├── render_utils.mjs     # Shared canvas rendering utilities
│   │   └── package.json
│   ├── diff_data.py            # Changelog diff generator
│   ├── update.py               # Cross-platform update pipeline
│   └── deploy.py               # Local Docker build + push to Docker Hub
├── data/                       # Parsed JSON data files
│   ├── {lang}/                 # Per-language directories (eng, kor, jpn, fra, etc.)
│   └── changelogs/             # Changelog JSON files (keyed by game version)
├── extraction/                 # Raw game files (not committed)
│   ├── raw/                    # GDRE extracted Godot project
│   └── decompiled/             # ILSpy output
├── docker-compose.yml          # Local dev
├── docker-compose.prod.yml     # Production
└── .forgejo/workflows/
    └── build.yml               # CI: builds + pushes to Docker Hub

Website Pages

Page Route Description
Home / Dashboard with entity counts, category cards, character links
Cards /cards Filterable card grid with modal detail view
Card Detail /cards/[id] Full card stats, upgrade info, image
Characters /characters Character overview grid
Character Detail /characters/[id] Stats, starting deck/relics, quotes, NPC dialogue trees
Relics /relics Filterable relic grid
Relic Detail /relics/[id] Full relic info with rich text flavor
Monsters /monsters Monster grid with HP, moves, Spine renders
Monster Detail /monsters/[id] HP, moves with intents/damage/powers/block, encounter links, power tooltips
Potions /potions Filterable potion grid (rarity, character pool)
Potion Detail /potions/[id] Full potion info
Enchantments /enchantments Enchantment list with card type filters
Enchantment Detail /enchantments/[id] Full enchantment info
Encounters /encounters Encounter compositions by act/room type
Encounter Detail /encounters/[id] Monster lineup, room type, tags
Events /events Multi-page event trees with expandable choices
Event Detail /events/[id] Full event pages, options, Ancient dialogue
Powers /powers Buffs, debuffs, and neutral powers
Power Detail /powers/[id] Power info with cards that apply this power
Keywords /keywords Card keyword list
Keyword Detail /keywords/[id] Keyword description with filterable card grid
Merchant /merchant Card/relic/potion pricing, card removal costs, fake merchant
Compare /compare Character comparison hub (10 pairs)
Compare Detail /compare/[pair] Side-by-side character comparison
Developers /developers API docs, widget docs, data exports
Showcase /showcase Community project gallery
Timeline /timeline Epoch progression with era grouping, unlock requirements
Act Detail /acts/[id] Bosses, encounters, events, ancients for an act
Ascension Detail /ascensions/[id] Ascension level description with prev/next navigation
Intent Detail /intents/[id] Intent icon, description
Orb Detail /orbs/[id] Orb icon, passive/evoke description
Affliction Detail /afflictions/[id] Affliction description, stackability
Modifier Detail /modifiers/[id] Run modifier description
Achievement Detail /achievements/[id] Achievement description
Reference /reference All items clickable — acts, ascensions, keywords, orbs, afflictions, intents, modifiers, achievements
Images /images Browsable game assets with ZIP download per category
Changelog /changelog Data diffs between game updates
About /about Project info, stats, pipeline visualization

API Endpoints

All data endpoints accept an optional ?lang= query parameter (default: eng). Responses are GZip-compressed and cached with Cache-Control: public, max-age=300.

Endpoint Description Filters
GET /api/cards All cards color, type, rarity, keyword, search, lang
GET /api/cards/{id} Single card lang
GET /api/characters All characters search, lang
GET /api/characters/{id} Single character (with quotes, dialogues) lang
GET /api/relics All relics rarity, pool, search, lang
GET /api/relics/{id} Single relic lang
GET /api/monsters All monsters type, search, lang
GET /api/monsters/{id} Single monster lang
GET /api/potions All potions rarity, pool, search, lang
GET /api/potions/{id} Single potion lang
GET /api/enchantments All enchantments card_type, search, lang
GET /api/enchantments/{id} Single enchantment lang
GET /api/encounters All encounters room_type, act, search, lang
GET /api/encounters/{id} Single encounter lang
GET /api/events All events type, act, search, lang
GET /api/events/{id} Single event lang
GET /api/powers All powers type, stack_type, search, lang
GET /api/powers/{id} Single power lang
GET /api/keywords Card keyword definitions lang
GET /api/keywords/{id} Single keyword lang
GET /api/intents Monster intent types lang
GET /api/intents/{id} Single intent lang
GET /api/orbs All orbs lang
GET /api/orbs/{id} Single orb lang
GET /api/afflictions Card afflictions lang
GET /api/afflictions/{id} Single affliction lang
GET /api/modifiers Run modifiers lang
GET /api/modifiers/{id} Single modifier lang
GET /api/achievements All achievements lang
GET /api/achievements/{id} Single achievement lang
GET /api/epochs Timeline epochs era, search, lang
GET /api/epochs/{id} Single epoch lang
GET /api/stories Story entries lang
GET /api/stories/{id} Single story lang
GET /api/acts All acts lang
GET /api/acts/{id} Single act lang
GET /api/ascensions Ascension levels (0–10) lang
GET /api/ascensions/{id} Single ascension level lang
GET /api/stats Entity counts across all categories lang
GET /api/languages Available languages with display names
GET /api/translations Translation maps for filter values and UI strings lang
GET /api/images Image categories with file lists
GET /api/images/{category}/download ZIP download of image category
GET /api/changelogs Changelog summaries (all versions)
GET /api/changelogs/{tag} Full changelog for a version tag
POST /api/feedback Submit feedback (proxied to Discord)

Rate limited to 60 requests per minute per IP. Feedback endpoint limited to 5 per minute per IP. Interactive docs at /docs (Swagger UI).

Localization

All game data is served in 14 languages using Slay the Spire 2's own localization files. Pass ?lang= to any data endpoint.

Code Language Code Language
eng English kor 한국어
deu Deutsch pol Polski
esp Español (ES) ptb Português (BR)
fra Français rus Русский
ita Italiano spa Español (LA)
jpn 日本語 tha ไทย
tur Türkçe zhs 简体中文

What's localized: All entity names, descriptions, card types, rarities, keywords, power names, monster names in encounters, character names, section titles — everything that comes from the game's localization data.

What stays English: UI chrome (navigation, filter labels, search placeholders), structural fields used for filtering (room_type, power type/stack_type, pool), site branding.

Filter parameters (type=Attack, rarity=Rare, keyword=Exhaust) always use English values regardless of language — the backend translates them to the localized equivalents before matching.

Example: GET /api/cards?lang=kor&type=Attack returns Korean card data where type is "공격", filtered correctly even though the parameter is English.

Rich Text Formatting

Text fields (description, loss_text, flavor, dialogue text, option title/description) may contain Godot BBCode-style tags preserved from the game's localization data:

Tag Type Example Rendered as
[gold]...[/gold] Color [gold]Enchant[/gold] Gold colored text
[red]...[/red] Color [red]blood[/red] Red colored text
[blue]...[/blue] Color [blue]2[/blue] Blue colored text
[green]...[/green] Color [green]healed[/green] Green colored text
[purple]...[/purple] Color [purple]Sharp[/purple] Purple colored text
[orange]...[/orange] Color [orange]hulking figure[/orange] Orange colored text
[pink]...[/pink] Color Pink colored text
[aqua]...[/aqua] Color [aqua]Ascending Spirit[/aqua] Cyan colored text
[sine]...[/sine] Effect [sine]swirling vortex[/sine] Wavy animated text
[jitter]...[/jitter] Effect [jitter]CLANG![/jitter] Shaking animated text
[b]...[/b] Effect [b]bold text[/b] Bold text
[i]...[/i] Effect [i]whispers[/i] Italic text
[energy:N] Icon [energy:2] Energy icon(s)
[star:N] Icon [star:1] Star icon(s)
[Card], [Relic] Placeholder [Card] Runtime-dynamic (italic)

Tags can be nested: [b][jitter]CLANG![/jitter][/b], [gold][sine]swirling vortex[/sine][/gold].

If you're consuming the API directly, you can strip these with a regex like \[/?[a-z]+(?::\d+)?\] or render them in your own frontend. The description_raw field (where available) contains the unresolved SmartFormat template.

Running Locally

Prerequisites

  • Python 3.10+
  • Node.js 20+

Backend

python -m venv venv
source venv/bin/activate      # Windows: venv\Scripts\activate
pip install -r backend/requirements.txt

cd backend
uvicorn app.main:app --host 0.0.0.0 --port 8000

Backend runs at http://localhost:8000.

Frontend

cd frontend
npm install
NEXT_PUBLIC_API_URL=http://localhost:8000 npm run dev

Frontend runs at http://localhost:3000.

Docker

docker compose up --build

Starts both services (backend on 8000, frontend on 3000).

Update Pipeline

A cross-platform Python script handles the full update workflow when a new game version is released:

# Full pipeline — extract game files, parse data, render sprites, copy images:
python3 tools/update.py

# Specify game install path manually:
python3 tools/update.py --game-dir "/path/to/Slay the Spire 2"

# Skip extraction (already have fresh extraction/ directory):
python3 tools/update.py --skip-extract

# Only re-parse data (no extraction or rendering):
python3 tools/update.py --parse-only

# Only re-render Spine sprites:
python3 tools/update.py --render-only

# Generate a changelog after updating:
python3 tools/update.py --changelog --game-version "0.98.2" --build-id "22238966"

The script auto-detects your OS and finds the Steam install directory. Requirements per step:

Step Tool Install
PCK extraction gdre_tools GDRE Tools releases
DLL decompilation ilspycmd dotnet tool install ilspycmd -g
Data parsing Python 3.10+ Built-in
Image copying Python 3.10+ Built-in
Spine rendering Node.js 20+ nodejs.org

Manual Steps

If you prefer to run steps individually:

# Parse all data (all 14 languages)
cd backend/app/parsers && python3 parse_all.py

# Parse a single language
cd backend/app/parsers && python3 parse_all.py --lang eng

# Copy images from extraction to static
python3 backend/scripts/copy_images.py

# Render Spine sprites (WebGL — no triangle seam artifacts)
cd tools/spine-renderer && npm install
npx playwright install chromium           # First time only
node render_all_webgl.mjs                 # All 138 skeletons via headless Chrome
node render_webgl.mjs <skel_dir> <out> [size]  # Single skeleton (e.g., hi-res ancient)

# Legacy canvas renderer (has triangle seam artifacts — avoid)
# node render_all.mjs / node render.mjs

Changelog System

Track what changes between game updates with field-level diffs across all entity categories.

Generating a Changelog

# Compare current data against a git ref:
python3 tools/diff_data.py HEAD~1 --format json \
    --game-version "0.98.2" --build-id "22238966" \
    --title "March Update"

# Preview as text or markdown:
python3 tools/diff_data.py HEAD~1 --format text
python3 tools/diff_data.py HEAD~1 --format md

Changelog Schema

Each changelog JSON file contains:

Field Description
app_id Steam App ID (2868840)
game_version Steam game version (e.g. "0.98.2")
build_id Steam build ID
tag Unique version key (e.g. "1.0.3")
date Date of the update
title Human-readable title
summary Counts: { added, removed, changed }
categories Per-category diffs with added/removed/changed entities

Deploying

CI/CD (Forgejo)

Pushes to main trigger .forgejo/workflows/build.yml which builds and pushes both images to Docker Hub via buildah.

Local Build + Push

Skip CI and push directly from your machine:

# Build and push both images:
python3 tools/deploy.py

# Frontend only:
python3 tools/deploy.py --frontend

# Backend only:
python3 tools/deploy.py --backend

# Test build without pushing:
python3 tools/deploy.py --no-push

# Tag a release:
python3 tools/deploy.py --tag v0.98.2

Auto-detects Apple Silicon and cross-compiles to linux/amd64 via docker buildx. Requires docker login first.

Production

# Pull and restart on production server:
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d

Production data is bind-mounted (./data:/data:ro). Container restart required after data changes.

Spine Renderer

Monster sprites in StS2 are Spine skeletal animations — each monster is a .skel (binary skeleton) + .atlas + .png spritesheet, not a single image. The renderer assembles these into static portrait PNGs.

WebGL Renderer (Current)

The WebGL renderer (render_webgl.mjs, render_all_webgl.mjs) uses Playwright + spine-webgl to render skeletons via headless Chrome's GPU. This produces clean renders with no triangle seam artifacts.

How it works:

  1. Launches headless Chrome via Playwright with WebGL enabled
  2. Loads skeleton data + atlas + textures as base64 into the browser page
  3. Creates a WebGL canvas, sets up spine-webgl shader + polygon batcher
  4. Applies the idle animation, calculates bounds (excluding shadow/ground slots)
  5. Renders via GPU triangle rasterization — no canvas clip paths, no seams
  6. Reads raw pixels via gl.readPixels, flips vertically (WebGL is bottom-up)
  7. Writes PNG via node-canvas to preserve transparency

Single skeleton:

node render_webgl.mjs <skel_dir> <output_path> [size]
node render_webgl.mjs ../../extraction/raw/animations/backgrounds/neow_room ../../backend/static/images/misc/neow.png 2048

Batch all skeletons:

node render_all_webgl.mjs  # Renders 138 skeletons to backend/static/images/renders/

Render coverage

Category Rendered Total Notes
Monsters 99 103 dirs All 111 game monsters have images (99 rendered + aliases/static)
Characters 16 16 Combat, rest site, and select poses
Backgrounds/NPCs 14 17 Neow, Tezcatara, merchant rooms, main menu
VFX/UI 9 22 Most VFX need specific animation frames
Total 138 158 20 skipped (no atlas, VFX-only, blank)

Legacy Canvas Renderer

The canvas renderer (render.mjs, render_all.mjs) uses spine-canvas with triangleRendering = true. This produces visible wireframe mesh artifacts due to canvas clip() path anti-aliasing between adjacent triangles. Use the WebGL renderer instead.

Dependencies

  • @esotericsoftware/spine-webgl ^4.2.107 — Spine runtime for WebGL (current)
  • playwright — Headless Chrome for WebGL rendering
  • @esotericsoftware/spine-canvas ^4.2.106 — Spine runtime for Canvas (legacy)
  • canvas ^3.1.0 — Node.js Canvas implementation

Extracting Game Files

If you need to extract from scratch:

# Extract PCK (GDRE Tools)
/path/to/gdre_tools --headless --recover="/path/to/sts2.pck" --output-dir=extraction/raw

# Decompile DLL (ILSpy CLI)
ilspycmd -p -o extraction/decompiled "/path/to/sts2.dll"

Steam install locations:

  • Windows: C:\Program Files (x86)\Steam\steamapps\common\Slay the Spire 2\
  • macOS: ~/Library/Application Support/Steam/steamapps/common/Slay the Spire 2/
  • Linux: ~/.local/share/Steam/steamapps/common/Slay the Spire 2/

Versioning

Spire Codex uses 1.X.Y semantic versioning:

Segment Meaning
1 Spire Codex major version (stays unless a full rewrite)
X Bumps when Mega Crit releases a game patch
Y Bumps for our own parser/frontend fixes and improvements

Examples: v1.0.0 = initial release, v1.0.1 = our bug fixes, v1.1.0 = first Mega Crit patch incorporated.

SEO

  • Structured data (JSON-LD): WebSite + VideoGame (home), CollectionPage + ItemList (list pages), Article + BreadcrumbList + FAQPage (detail pages), SoftwareApplication (developers)
  • Title format: "Slay the Spire 2 [Topic] - [Descriptor] | Spire Codex" — standardized across all pages
  • Sitemap: Flat XML at /sitemap.xml with force-dynamic (renders server-side, not build-time). ~20,000+ URLs including entity detail pages, browse matrix pages, and i18n detail pages for all entity types
  • International SEO: /{lang}/ routes for 13 non-English languages with hreflang alternates
  • Programmatic SEO: 41 card browse pages at /cards/browse/ (rare-attacks, ironclad-skills, etc.)
  • Internal linking: Powers ↔ cards, encounters → monsters, card keywords → keyword hub pages, monster moves → power pages (with tooltips), act pages → encounters/events, every reference entity clickable
  • Open Graph & Twitter Cards: Per-entity OG images, summary_large_image Twitter cards
  • Canonical URLs: Every page declares a canonical URL

Embeddable Widgets

Tooltip Widget

Add hoverable tooltips for all 13 entity types to any website:

<script src="https://spire-codex.com/widget/spire-codex-tooltip.js"></script>
<p>Start with [[Bash]] and [[relic:Burning Blood]].</p>

Changelog Widget

Embed an interactive changelog viewer:

<div id="scx-changelog"></div>
<script src="https://spire-codex.com/widget/spire-codex-changelog.js"></script>

Full docs: spire-codex.com/developers

Roadmap

  • Individual detail pages
  • Global search
  • Multi-language support (14 languages)
  • SEO (JSON-LD, OG/Twitter, sitemap, hreflang)
  • Tooltip widget (all 13 entity types)
  • Character comparison pages (10 pairs)
  • Keyword hub pages
  • Merchant guide (pricing from decompiled C#)
  • Developer docs + data exports
  • International SEO (13 language landing pages)
  • Card browse matrix (41 programmatic SEO pages)
  • Discord bot — Card lookup, patch alerts
  • Deck builder — Interactive deck theorycrafting
  • Database backend — Replace JSON loading with SQLite/PostgreSQL

Acknowledgments

Thanks to vesper-arch, terracubist, U77654, Purple Aspired Dreaming, and Kobaru for QA testing, bug reports, and contributions.

Tech Stack

  • Backend: Python, FastAPI, Pydantic, slowapi, GZip compression
  • Frontend: Next.js 16 (App Router), TypeScript, Tailwind CSS, 14-language support
  • Spine Renderer: Node.js, Playwright, @esotericsoftware/spine-webgl (WebGL via headless Chrome)
  • Infrastructure: Docker, Forgejo CI, buildah
  • Tools: Python (update pipeline, changelog diffing, image copying)

Disclaimer

This project is for educational purposes. Game data belongs to Mega Crit Games. This should not be used to recompile or redistribute the game.

About

A project for decompiling Slay the Spire 2 and making an API with it

Topics

Resources

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors