AGENTS.md

This file provides guidance to LLM agents when working with code in this repository.

What This Is

A client-side Slay the Spire 2 run history dashboard. Parses .run JSON files exported by the STS Collector mod and renders interactive charts and per-run breakdowns. All processing happens in the browser — no server required in production.

Architecture

Data flow: .run files → _parse.js_stats.js_charts-plot.js + _app.js DOM rendering

Files

State

Single state object in _app.ts:

const state = {
    dirHandle, // FileSystemDirectoryHandle
    rawRunsData, // raw JSON keyed by timestamp
    allRuns, // parsed summary objects (ParsedRun[])
    currentStats, // result of computeStats()
    tableSortKey, // column key for table sort
    tableSortDir, // 1 or -1
    runTypeFilter, // { normal, daily, custom }
    _rtfDebounce, // debounce timer ref
    _runDetailCache, // Map of parsed run details (filename -> RunDetail)
    _runDetails, // all run details for the current load
    currentRun, // currently open run detail (null when modal closed)
};

IndexedDB Schema

StoreKeyValue
handles"dir"FileSystemDirectoryHandle
handles"cache"{ savedAt, rawRunsData, runDetails } (pre-parsed details)
detailsfilename (string)parsed run detail object

DB version: 3. If the schema changes, update _idb.ts and add an onupgradeneeded handler.

Note: The details store is keyed by filename (not timestamp). Run details are parsed synchronously during finishLoad() and stored both in the in-memory _runDetailCache and cached to IndexedDB.

Chart Rendering

Charts are rendered with Observable Plot (imported as @observablehq/plot). Two rendering strategies:

  1. Immediate — above-fold charts render synchronously in renderAll()
  2. Deferred — below-fold charts use IntersectionObserver (rootMargin: 200px) to defer rendering until scrolled into view

Chart elements carry a _lazyRender property referencing their render function. This is set in _app.js’s chartIdMap.

Key Conventions