- A Svelte 5 + Vite 5 application that provides an offline-capable wiki for Cataclysm: Bright Nights game data
- The app is a mirror of game data. Upstream source code and data may live at
../Cataclysm-BN
- Node.js: 24
- pnpm: 10.x
- Core:
TypeScript5,Svelte5 +Vite7 - Testing:
vitest,puppeteer - Styling: Scoped CSS, custom design tokens in
/src/assets/game-palette.cssandsrc/assets/design.css.
src/: app source (key files:src/data.ts,src/types.ts; plus routing and type-specific views)src/types.ts: game data schema definitions, no app specific types herescripts/: development scripts_test/: test fixtures (all.json,all_mods.json)
pnpm dev- Start Vite dev server at http://localhost:3000
pnpm lint- Run linterspnpm check- Run checkspnpm lint:fix- Auto-fix linter issues
Prefer targeted tests first; run full suite only for cross-cutting changes.
If the command runs tests, add --no-color.
pnpm lintandpnpm check- Required before commitpnpm test:changed --maxWorkers=50% --bail 1- Tests related to changed filespnpm test:fast- All non-render-regression testspnpm check- TypeScript/Svelte correctnesspnpm vitest run <path/to/test.ts>- Run single test
Test matrix:
- Tiny/localized change:
pnpm lint && pnpm test:changed - Normal feature/bugfix:
pnpm lint && pnpm check && pnpm test:fast - Cross-cutting/data-model/routing change:
pnpm test --maxWorkers=50% --bail 1
src/all.X.test.ts: slow full-data rendering integration testssrc/routing.test.ts: slow full-data rendering integration testssrc/schema.test.ts: game data schema validation
pnpm fetch:fixtures:nightly- Download nightly test data required for testspnpm fetch:builds- Download builds.json index
- Route-Driven Remounting: main content components (
Thing,Catalog) are wrapped in{#key}blocks and destroyed/recreated on every navigation. Avoid prop-mirroring effects inside keyed components; route remounting is the source of truth. Most other components are mounted inside keyed parents. - Global Data:
datastore fromsrc/data.ts- write-once per page load - URL as Source of Truth: Version and search params drive app state (see
docs/routing.md) - Reactivity usage: read
docs/reactivity.md
- Strict mode enabled
- Always use explicit types for function parameters and return values
- Prefer
typeoverinterfacefor type definitions - Use discriminated unions for complex state (see
src/types.ts) - No implicit any: All values must be typed
- Use
<script lang="ts">for TypeScript - Component-scoped styles are preferred over global
- Mark intentional a11y violations with
<!-- svelte-ignore a11y-* -->
- Try-catch for I/O: localStorage, fetch, etc. with fallback behavior
- Sentry.io logging: Use
Sentry.captureException()for critical failures
- JSDoc: For public functions and complex logic
- Inline comments: For non-obvious decisions
- TODO comments: Format as
//TODO: description - Never remove comments that aren’t related to the current task
- Imports ordering: external packages, internal modules, type-only imports, alphabetically
- Always auto-format before commit via
pnpm lint:fix - Always use "Conventional Commits" format:
<type>(<optional scope>): <description>. Scopes:feat,fix,docs,style,refactor,perf,test,chore.
-
i18n: use
tfrom@transifex/nativefor all user-facing text. Usegame-localemodule for game-internal text. -
Truth:
_test/all.jsonis the compiled data blob (~30MB) -
NEVER grep the whole file: Use
jqto filter# Filter specific item jq '.data[] | select(.id=="<id>" and .type=="<type>")' _test/all.json # List all IDs of a type jq '.data[] | select(.type=="item") | .id' -r _test/all.json
-
Inheritance: Raw JSON uses
copy-from- check parent if property missing -
UI Verification:
.agent/rules/ui-verification.md
- Use Lightweight ADR format (read
docs/adr/README.mdfor index and usage) - Create ADR for significant architectural decisions
docs/architecture.md- High-level architecture overviewdocs/reactivity.md- Svelte reactivity and runes usage patternsdocs/routing.md- URL-based state management
- Review relevant docs/patterns before coding
- Implement with tests (or add tests immediately after)
- Run targeted checks first; reserve a full suite for cross-cutting work
- Format (
pnpm lint:fix), check types (pnpm check), then manually check UI changes
- Filter
_test/all.jsonwithjq(never grep the full blob) - Verify flatten/inheritance in
src/data.ts(copy-frompath)
- Run
pnpm check:types; fix with type guards/unknown(neverany)
Never add prop-mirroring effects inside {#key} blocks
Never run pnpm test:full by default for tiny/localized changes
Never commit without running pnpm check and pnpm lint