Build and balance Pathfinder 2e encounters: browse every creature and NPC from the Archives of Nethys, filter by level, type, traits, rarity, size, family, alignment, source or Legacy/Remastered edition, and assemble an encounter with live XP budgeting per the GM Core encounter rules — including Weak and Elite variant adjustments, which most similar tools overlook.
Live site: https://maxiride.github.io/pf2e-encounters/
| Layer | Choice |
|---|---|
| Framework | Vue 3 + Quasar 2 (Vite), TypeScript strict |
| State | Pinia |
| Data | Static JSON snapshot of AoN's public Elasticsearch index, refreshed monthly by CI |
| Tests | Vitest (rules logic) + Playwright (UI smoke) |
| Analytics | Self-hosted Umami, production builds only, no cookies |
| Hosting | GitHub Pages (gh-pages branch), no backend |
Prerequisites: Node ≥ 20 and pnpm.
pnpm install
pnpm dev # dev server on http://localhost:9000Creature data (public/creatures.json + public/metadata.json) is committed, so the app works
offline out of the box. To refresh it from AoN:
pnpm run generate:data # skipped if data is fresher than 7 days
pnpm run generate:data --force # always downloadPlease be considerate: the Archives of Nethys is a community-run resource. The fetch script is deliberately a single HTTP request with a freshness guard — don't loop it. See ADR 0001.
| Command | What it does |
|---|---|
pnpm dev |
Dev server with HMR, type checking and linting |
pnpm build |
Production SPA build into dist/spa |
pnpm lint |
ESLint over src/ |
pnpm test |
Unit + E2E suites |
pnpm test:unit |
Vitest — encounter math and analytics contract |
pnpm test:e2e |
Playwright smoke suite (starts the dev server itself; first run needs pnpm exec playwright install chromium) |
pnpm run generate:data |
Refresh creature data from AoN |
├── src/
│ ├── components/ # CreaturesTable, EncounterList, ThreatBar, ...
│ ├── stores/ # Pinia stores — encounter-store.ts holds ALL the rules math
│ ├── pages/ layouts/ # single-page shell
│ └── boot/ # app startup (creature data fetch)
├── public/ # committed creature data snapshot
├── tools/aon-downloader/ # data fetch script (plain Node, zero deps)
├── e2e/ # Playwright smoke tests
├── docs/adr/ # architecture decision records — start here to understand "why"
└── .github/workflows/ # ci.yml, deploy.yml, update-creatures.yml
The encounter math (XP budgets, creature XP by level delta, weak/elite adjustments) lives entirely in
src/stores/encounter-store.ts with the relevant rulebook links
inline. If you touch it, encounter-store.spec.ts encodes the
GM Core tables row by row.
- A monthly GitHub Action pulls every creature and NPC (~4.7k records) from AoN's public Elasticsearch endpoint in one request and commits the JSON — see ADR 0001 and ADR 0002.
- The SPA loads that JSON at startup; filtering happens client-side.
- Pushes to
mainbuild and publish to thegh-pagesbranch.
Issues and PRs welcome.
- Read the ADRs first — they explain the non-obvious choices and their trade-offs.
- Branch model: work lands on
dev,mainis what production builds from and the target for PRs. - CI (lint + unit + E2E) must pass; it runs automatically on pushes and PRs.
- Rules discussions should cite the relevant Archives of Nethys rules page — the tool intentionally implements rules-as-written with no house rulings (see #62 for an example of that policy).
Code: see LICENSE. Game content is used under Paizo's Community Use Policy — full notices in LICENSE_AON.md. This tool is not published, endorsed, or approved by Paizo or the Archives of Nethys.
Do you like my work? Every cup of coffee brings me back to the desk!
