Files
Dimension-47/.planning/research/FEATURES.md

314 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Feature Research
**Domain:** PF2e TTRPG companion app — next milestone (Level-Up + PWA + Battle-Display + Dice/Chat + GM Live Tools + Obsidian Vault)
**Researched:** 2026-04-27
**Confidence:** HIGH (PF2e rules + PWA tech are HIGH; competitor UX details are MEDIUM)
## Scope Note
This is a **subsequent milestone** for an existing app. Already-shipped features (HP, conditions, skills, saves, inventory, alchemy, rest, alchemy-tab, character-import, battle-MVP, GM-library, JWT-auth) are NOT re-evaluated here. The categorization below applies **only to the new milestone scope**.
The bar for "table stakes" is calibrated to the actual user — the **own gaming group at the table**. Things that would be table-stakes for a public SaaS (multi-tenant onboarding, account recovery flows, etc.) are not table-stakes here.
## Feature Landscape
### Table Stakes (Without these, the milestone fails its goal)
#### Level-Up System
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| **Attribute Boosts at level 5/10/15/20** (4 free boosts; +2 to four different attributes, capped at +4 / 18) | PF2e core rule, every PF2e tool implements it | MEDIUM | Trigger HP-Max recompute on CON-Boost; +1 trained skill on INT-Boost |
| **Class feat at every even level** (2, 4, 6, 8, 10, 12, 14, 16, 18, 20) | PF2e core rule | HIGH | Filter by class + level + prerequisites; many feats have multi-condition prereqs (skill rank, other feat, ancestry) |
| **Skill feat at every even level** (2, 4, 6, ...) | PF2e core rule | MEDIUM | Filter by skill rank prereq; some require Trained/Expert/Master/Legendary in named skill |
| **General feat every 4 levels** (3, 7, 11, 15, 19) | PF2e core rule | MEDIUM | Skill feats ALSO count as general feats (one-way) |
| **Skill increase at level 3 and every 2 levels thereafter** (3, 5, 7, 9, 11, 13, 15, 17, 19) | PF2e core rule, Rogues earlier/more | MEDIUM | Untrained→Trained, Trained→Expert (level 3+), Expert→Master (level 7+), Master→Legendary (level 15+) |
| **Ancestry feat at level 5, 9, 13, 17** | PF2e core rule | MEDIUM | Filter by ancestry, heritage, prerequisites |
| **Class features per class table** (e.g. Fighter Bravery at 3, Weapon Mastery at 5, etc.) | PF2e core rule, class-specific | HIGH | Per-class lookup table; some grant additional choices (e.g. specialization) |
| **Prerequisite validation** (e.g. "Trained in Athletics required") | Without this it's not "regelkonform" | HIGH | Need to evaluate prerequisite expressions: skill rank, feat ownership, level, ancestry, deity, spellcasting tradition |
| **Auto-recompute derived stats** (HP-Max, Save proficiency increases, AC proficiency, Class DC) | Core promise of "regelkonform" — values must be correct after Level-Up | HIGH | Class-specific proficiency progression tables; HP-Max = ancestry HP + (class HP + CON-Mod) × Level |
| **Undo / Cancel before commit; commit creates change record** | Already in PROJECT.md as requirement; users will misclick | MEDIUM | Implement as draft state; on commit, write all changes atomically |
| **Free Archetype variant rule** (extra archetype-only feat at every even level) | Group's preferred PF2e variant; Pathbuilder + Foundry's PF2e Leveler both support it | MEDIUM | Toggle per character; second feat slot, restricted to archetype feats only |
| **Spellcaster slot/cantrip progression on Level-Up** | Spellcasters need correct slot tables to play | HIGH | Per-tradition progression; spell repertoire/preparation also needs increment for spontaneous casters |
#### PWA
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| **Web App Manifest + Icons + Splash + Service Worker registration** | Without manifest, app can't be installed | LOW | Standard Vite PWA plugin (`vite-plugin-pwa`) handles boilerplate |
| **Cache-first read of own character sheet (offline)** | "Always-on companion at the table" with flaky table Wi-Fi | MEDIUM | Cache GET responses for `/characters/:id`, `/equipment/:id`, `/feats/:id` etc.; show "offline" indicator |
| **"Add to Home Screen" prompt** (Android automatic via `beforeinstallprompt`, iOS guided manual) | Without it users won't install and miss push | LOW | iOS needs in-app instruction overlay since no programmatic prompt — see PITFALLS |
| **Web Push for GM→player ping** (turn alert, dice request, custom message) | Whole point of having a PWA at the table | HIGH | VAPID keys, Service Worker `push` event handler, Push subscription persisted per device, opt-in flow per user |
#### Multi-Screen Battle Display
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| **Read-only Display-Mode route** (e.g. `/battle/:id/display`) | Existing battle page is GM-only mixed; table screen needs a "no controls" view | MEDIUM | Same WebSocket subscription, conditionally hide drag handles + controls; optimize layout for landscape table screen |
| **Display-Mode auth model** (player or shared GM session, no controls) | Tisch-Display likely runs as a shared/auto-login terminal | MEDIUM | Either anonymous read-only via session token OR dedicated "display" pseudo-user with read-only role |
| **Initiative Tracker as sortable list with current-turn highlight** | Currently only badges on tokens; players need to see "wer ist dran" at a glance from across the table | LOW-MEDIUM | Sorted list; large-font for table-display readability; "next" button on GM side; advances turn via WebSocket event |
| **Token effects/conditions/auras on Display-Mode** | Players need to see "I'm flat-footed and frightened 2" without asking GM | MEDIUM | Already have conditions on character; need same model on tokens; per-token condition list rendered on/near token + in init list |
| **Token add/remove broadcast as WebSocket event** (not just query-invalidate) | Currently mid-battle changes desync until refresh | LOW | Existing gateway pattern; add `token:added` / `token:removed` events |
#### Dice + Chat
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| **In-app dice with PF2e notation (`1d20+7`, `2d6+3`)** | Primary play mechanic; no external dice tabs | MEDIUM | Use `@dice-roller/rpg-dice-roller` or `dice-notation-js`; standard d4/6/8/10/12/20/100 |
| **Crit success / crit failure flagging** (PF2e: nat 20 / +10 / +0 / -10) | PF2e's defining mechanic — degree of success | MEDIUM | Compare result vs DC; degree-of-success calc lives in app (not in dice lib) |
| **Roll log per campaign + per battle, visible to all** | Without log, contested rolls become arguments | LOW | Append-only log table; WebSocket broadcast on new roll |
| **Roll attribution** (who rolled, what for, when) | Logs without attribution are useless | LOW | User + character + label (e.g. "Athletics Check") + timestamp |
| **In-game chat per campaign + per battle** | GM/player coordination during play | LOW-MEDIUM | Append-only message table; same WebSocket pattern; rendered with roll embeds inline |
#### GM Live Tools
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| **GM can set HP / damage / heal on player character** | Already infra exists; just needs GM-facing UI | LOW | Reuse existing `character:update` events; add GM permission check + "GM action" log entry |
| **GM can add/remove/update conditions on player character** | Same | LOW | Reuse existing condition gateway events |
| **GM can give item to player character** | Loot distribution | LOW | Reuse existing inventory events; pick from equipment DB |
| **GM can adjust money (credits)** | Loot/cost management | LOW | Reuse existing money events |
| **GM can send push/chat ping to specific player(s) or all** | "Du bist dran" workflow | MEDIUM | Combines push (Web Push) with in-app chat — see Pitfalls about double-delivery |
#### Obsidian Vault Read-Only
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| **Markdown rendering** (CommonMark + GFM tables/code blocks/images) | Bare-minimum vault reader | LOW | `react-markdown` + `remark-gfm` + `rehype-sanitize` |
| **Wikilinks `[[Note]]` and `[[Note\|Alias]]`** | Obsidian's primary linking syntax — without this, every link is broken | MEDIUM | `@portaljs/remark-wiki-link` or `@flowershow/remark-wiki-link` (handles shortest-path) |
| **Image embeds `![[image.png]]`** | Notes are useless if maps/illustrations don't render | MEDIUM | Custom remark plugin or extension of wiki-link; serve via vault endpoint |
| **Folder tree navigation** | Vaults aren't flat; navigation must mirror structure | LOW | Tree control over directory listing endpoint |
| **Full-text search** | Vaults grow large; finding "the inn name" without search is painful | MEDIUM | Server-side grep-like or `flexsearch`-style index over markdown body; Postgres FTS is acceptable |
| **Cache last-N read notes for offline** | "I want to look up that NPC" while at the table without Wi-Fi | MEDIUM | Service-Worker cache-on-read with LRU eviction; server stays source-of-truth |
### Differentiators (would make Dimension47 noticeably better than Pathbuilder/Foundry/Owlbear for this group)
| Feature | Value Proposition | Complexity | Notes |
|---------|-------------------|------------|-------|
| **German UI everywhere — including PF2e rules text** | Pathbuilder is English-only; Foundry's PF2e is partial-German with Babele/translation modules. Dimension47 already has a translation pipeline (Claude-API cached) | MEDIUM | Extend existing translation cache to feats and class-features text on Level-Up |
| **One-screen, integrated experience** (character sheet ↔ battle ↔ vault notes ↔ chat) without context-switching apps | At the table users today juggle Pathbuilder + Discord + Obsidian + a dice-roller — all in one app reduces friction | MEDIUM | Architecture choice: deep-linking + state-preserving navigation; vault note can be opened side-by-side with character |
| **PF2e dice with degree-of-success + auto-condition application** (e.g. "Frightened 1 on critical hit with X spell") | Most VTTs roll dice but leave degree-of-success and condition-application to player; auto-application removes one-step-per-attack friction | HIGH | Spell/attack-templates with embedded "on-hit"/"on-crit" effects; data model heavy — defer to v1.x |
| **Animated transition: GM "Du bist dran" ping → player phone vibrates → in-app initiative-card pop-up** | Combines push + visual + haptic; nobody else does it well at-the-table because nobody else is PWA-first | MEDIUM | Layer Web Push + Vibration API + in-app modal |
| **Battle-Display dark/cinematic mode** (large initiative card for active turn, dimmed for off-turn) | The table screen is part of the table aesthetic; sterile Foundry UI breaks immersion | LOW | CSS-only theme variant for `/battle/:id/display` route |
| **Vault note → character "see also" chips** (note marked with frontmatter `npc: true` shows as hoverable chip in chat / battle) | Connects worldbuilding (Obsidian) to play (battle/chat) without manual lookup | HIGH | Frontmatter parsing + tag/type indexing; defer to v1.x |
| **Roll history per character is exportable** (matches existing HTML-export ethos) | Group keeps session memory beyond runtime | LOW | Reuse export-character-html pattern |
| **Offline-cached vault search** (FlexSearch index served as static asset for installed PWA) | Read-and-search Obsidian notes with zero connectivity | HIGH | Build-step or on-demand index download; defer to v1.x or call out as risky |
| **GM can assign initiative roll-prompt** ("Roll Initiative for Perception" → all players get push + dice button pre-populated) | Removes 30-second "everyone roll initiative" coordination at the table | MEDIUM | Combines GM-tools + dice + push |
### Anti-Features (Commonly tempting, deliberately NOT building)
| Feature | Why Tempting | Why Problematic | Alternative |
|---------|--------------|-----------------|-------------|
| **Bidirectional Obsidian sync** (write-back from app to vault) | "Wouldn't it be great to edit notes from phone too" | Conflict resolution is its own product; group already uses Obsidian on desktop for editing | Read-only is explicitly in PROJECT.md Out of Scope |
| **Offline editing with sync queue** (offline character changes that re-sync later) | Looks pro, modern PWAs have it | Two players editing same character offline = last-write-wins corruption; complexity vs value at the table is bad — game is online anyway | PROJECT.md already excludes this; offline is read-only |
| **Native app (Capacitor / React Native wrapper)** | "Better push reliability, better install UX, app-store presence" | App-store overhead, build pipelines, two more codebases. PWA solves 95 % of need | PWA + careful Service-Worker; iOS Safari supports installed-PWA Push since 16.4 |
| **In-app character creation from scratch** | "Why force users out to Pathbuilder?" | Pathbuilder is a 5-year-mature character builder; rebuilding it duplicates years of work for one-time-per-character benefit | Pathbuilder import stays. Level-Up in app handles ongoing changes |
| **Generic VTT (other systems, D&D 5e, etc.)** | "More users" | Self-hosted for own group; data model is PF2e-specific (action-economy, proficiency tiers, archetypes); generalizing kills sharpness | Keep PF2e-only |
| **Public multi-tenant SaaS / signup flow** | Default mental model for "web app" | Self-hosted for own group; account-onboarding is 0-value | No public registration; ADMIN provisions accounts |
| **Presence indicators** ("Alex is viewing the map", "Spieler X tippt...") | Social-app default | Real value tiny vs WebSocket complexity, especially with mobile screen-locks | PROJECT.md already excludes this |
| **Fog of War on battle map** | Owlbear/Foundry have it | Group plays in-person with 3D minis on a table screen; fog of war with a flat overhead in-person doesn't make sense | Already out-of-scope in PROJECT.md |
| **Voice chat / video** | Discord-replacement temptation | Discord works fine; reinventing it costs a milestone for zero gain | Use existing Discord |
| **3D dice physics** (rolling animation, ringtone) | Feels premium | Burns CPU on mobile, distracts from in-person play, every player has real dice on the table anyway | Plain text "rolled 17" with crit-color highlight |
| **Real-time collaborative vault editing** (Obsidian Live-style) | Trendy | Group edits Obsidian on desktop; collaborative-CRDT for Markdown is a quarter-of-engineering for unclear gain | Read-only stays read-only |
| **AI-generated NPCs / encounters** | LLM hype | Out of scope; group's GM has Obsidian for prep | Vault read is enough |
| **Dynamic lighting** (Foundry's flagship feature) | "Looks like a real VTT" | In-person with table screen and minis; lighting is the room's lighting | No |
| **Token vision / line-of-sight calc** | Same | Same — minis on a table | No |
| **Auto-applying attack rolls to enemy HP** | "PF2e is so click-heavy, just automate it!" | High data-model cost (every attack-feat needs structured "on hit"/"on crit"/save-DC linking); error-recovery is messy when GM disagrees | GM applies HP changes manually via Live-Tools — already in-scope |
| **Marketplace for community NPCs / maps** | "GMs would love to share" | Group of 1 GM + N players; library is internal; sharing is out-of-scope (self-hosted, single-tenant) | GM-Library is internal-only |
## Feature Dependencies
```
PWA Manifest + Service Worker
├──enables──> Web Push
│ └──used-by──> GM "Du bist dran" ping
│ └──used-by──> Dice-roll-request push
└──enables──> Offline-cache
├──used-by──> Character sheet offline read
└──used-by──> Vault notes offline read
Web Push subscription endpoint persistence
└──requires──> Per-user device-list table (server-side)
Level-Up system
├──requires──> Feat-prerequisite evaluator (DSL or interpreter)
├──requires──> Class-progression-table data (per-class proficiency by level)
├──requires──> Boost-cap recomputation (HP, save bonuses, AC)
└──enables──> "Level" WebSocket event already exists, Level-Up can broadcast
Battle Display-Mode read-only route
├──requires──> Auth model decision (anon-token vs display-pseudo-user)
├──requires──> Token-effect data model (new schema)
└──requires──> WebSocket event for token-add/remove (not query-invalidate)
Initiative Tracker upgrade
└──depends-on──> Existing battle-session schema; pure UI + small server change
Dice roller
├──requires──> Roll-log table (campaign + battle scoped)
├──enables──> Chat with embedded rolls
└──enables──> GM "request roll" feature (combines push + dice)
In-game Chat
├──requires──> Message table (campaign + battle scoped)
├──depends-on──> Existing JWT/role for whisper/visibility
└──integrates-with──> Dice-roll-log (rolls render inline)
GM Live-Tools UI
└──reuses──> All existing character WebSocket events (HP, conditions, items, money)
└──just-needs──> GM-facing UI surface (no new server events)
Obsidian Vault
├──requires──> Vault-endpoint protocol decision (HTTP-served-files vs Git-pull vs custom)
├──requires──> Markdown renderer (react-markdown + remark-wiki-link)
├──requires──> Image proxy for ![[image.png]]
└──enables──> Vault-search (FlexSearch or Postgres FTS)
GM Push-Ping → Player feature
├──requires──> Web Push (PWA prerequisite)
├──requires──> In-game Chat (so the message has a destination)
└──requires──> GM Live-Tools UI (the trigger surface)
```
### Dependency Notes
- **Web Push depends on PWA Manifest + Service Worker.** Cannot ship Push before installable PWA exists.
- **iOS Push requires installed-to-Home-Screen PWA** (Safari 16.4+). Test plan must include "is the PWA actually installed?" check.
- **Level-Up auto-recompute depends on per-class progression tables.** These are not currently in the DB schema (the existing app reads class-features from Pathbuilder import only, no progression model). New table needed: class progression by level, per-class.
- **Free Archetype is a per-character toggle**, not a global config. UI must show this toggle on character creation/edit.
- **GM-Live-Tools requires no new server events** — everything reuses existing character/inventory/condition/money WebSocket events. Risk: existing events probably don't enforce "is the actor a GM in this campaign" — needs server-side authorization audit.
- **Display-Mode auth needs a decision early.** Anonymous-token vs pseudo-user has long downstream effects on chat/roll attribution from the table screen.
- **Vault endpoint protocol is unresolved.** PROJECT.md says "selbst-gehosteter Endpoint, Protokoll noch zu wählen" — research/spike needed before vault phase.
## MVP Definition
(For the new milestone — not the whole app)
### Launch With (milestone v1)
Minimum viable to ship the milestone:
- [ ] **Level-Up regelkonform** — all six choice points (boost / class feat / skill feat / general feat / skill increase / ancestry feat / class feature) with prerequisite validation, auto-recompute, undo-before-commit, Free Archetype variant. Spellcaster slot/cantrip progression included.
- [ ] **PWA Manifest + Service Worker + Add-to-Home-Screen flow** — Android automatic, iOS guided
- [ ] **Cache-first offline read** for character sheet, inventory, feats, actions, alchemy, vault notes (already-visited only)
- [ ] **Web Push for GM→player ping** — VAPID keys, subscription persistence, GM-trigger UI
- [ ] **Battle Display-Mode route** — read-only, large initiative tracker, token effects/conditions visible
- [ ] **Token-effect data model + GM editor** — per-token list of named effects with optional duration
- [ ] **Token add/remove WebSocket event** — convert existing query-invalidate
- [ ] **Initiative Tracker upgrade** — sortable list, current-turn highlight, GM next-turn button
- [ ] **In-app dice with PF2e notation + degree-of-success + roll log** per campaign and battle, broadcast via WebSocket
- [ ] **In-game chat** per campaign and battle, with inline roll embeds
- [ ] **GM Live-Tools UI** — set HP/conditions/items/money on player character via existing events; send-message-to-player UI
- [ ] **Obsidian Vault read-only browser** — folder tree, file read, markdown + wikilinks + image embeds, full-text search, last-N offline-cached
- [ ] **German translation cache extension** for new feat-prereq text and class-feature descriptions
### Add After Milestone (v1.x — defer if scope tight)
- [ ] **Animated push-ping arrival** with vibration + in-app initiative-card overlay
- [ ] **Battle Display cinematic theme** — dim off-turn, large active-turn card
- [ ] **GM "request roll" from player** — combined push + pre-populated dice button
- [ ] **Roll-history export** to HTML/PDF
- [ ] **Vault frontmatter NPC chips** — type-tagged notes auto-link in chat/battle
- [ ] **Level-up history view** on character — what was chosen at each level
### Future Consideration (post-milestone)
- [ ] **Auto-condition application from spells/attacks** — heavy data-model cost, defer until Level-Up + Battle stabilize
- [ ] **Vault offline FlexSearch index** — full vault offline-search; only matters if vault grows large
- [ ] **Background-sync of stale character data** — limited iOS support; complex; nice-to-have
- [ ] **Multi-language UI beyond German** — only relevant if new players join who don't read German
## Feature Prioritization Matrix
| Feature | User Value | Implementation Cost | Priority |
|---------|------------|---------------------|----------|
| Level-Up: 6 choice points + validation + auto-recompute | HIGH | HIGH | P1 |
| Level-Up: Free Archetype variant | HIGH (group uses it) | MEDIUM | P1 |
| Level-Up: Spellcaster progression | HIGH (group has casters) | HIGH | P1 |
| PWA installable + offline character read | HIGH | MEDIUM | P1 |
| Web Push GM→player | HIGH | HIGH | P1 |
| Battle Display-Mode read-only route | HIGH | MEDIUM | P1 |
| Initiative tracker upgrade | HIGH | LOW-MEDIUM | P1 |
| Token effects/conditions | HIGH | MEDIUM | P1 |
| Token add/remove WebSocket | MEDIUM | LOW | P1 |
| Dice roller + roll log | HIGH | MEDIUM | P1 |
| In-app chat | HIGH | LOW-MEDIUM | P1 |
| GM Live-Tools (HP/conditions/items/money) | HIGH | LOW | P1 |
| Obsidian read + wikilinks + images | HIGH | MEDIUM | P1 |
| Vault search | MEDIUM-HIGH | MEDIUM | P1 |
| Vault offline-cache (last-N) | MEDIUM | MEDIUM | P1 |
| Battle cinematic theme | MEDIUM | LOW | P2 |
| Animated push-ping with vibration | MEDIUM | MEDIUM | P2 |
| GM "request roll" feature | MEDIUM-HIGH | MEDIUM | P2 |
| Level-up history view | MEDIUM | LOW | P2 |
| Vault frontmatter NPC chips | MEDIUM | HIGH | P3 |
| Auto-condition from spells | MEDIUM | HIGH | P3 |
| Vault offline FlexSearch full-index | LOW-MEDIUM | HIGH | P3 |
## PF2e-Specific Complexity Notes (Level-Up)
The Level-Up feature is structurally the most complex single piece in this milestone. Worth calling out:
1. **Six independent choice axes per level** (not all triggered every level): attribute boost, class feat, skill feat, general feat, skill increase, ancestry feat, class feature. Each has its own filter logic.
2. **Prerequisites are a mini-DSL.** Examples:
- `"Trained in Athletics"` → simple skill-rank check
- `"Strength 14, trained in Intimidation"` → composite check
- `"Power Attack, level 4"` → feat ownership + level
- `"Cleric"` → class check
- Roughly 200+ feats have non-trivial prereqs; treating each as a free-text string and asking the GM is the cheap way out — but kills the "regelkonform" promise.
3. **Class progression tables vary widely.** Fighter has 5 weapon-specialization steps; Wizard has school-specific arcana progressions; Rogue has skill-increases at every level (not every other). No single shared table.
4. **Boost rules have an "above 18" cap rule.** Each boost is +2, but if attribute is already 18+, only +1. This is one of the most frequently-misunderstood PF2e rules — must be implemented correctly.
5. **Free Archetype variant** doubles the class-feat slots but restricts to archetype feats only AFTER dedication is taken. Once a dedication is chosen, the slot can take any feat from THAT archetype's list.
6. **Skill-increase scaling caps.** Trained→Expert allowed at level 3+; Expert→Master at level 7+; Master→Legendary at level 15+. Pre-cap selections must be filtered out.
7. **Multiple-class-feature characters.** A Champion at level 9 might have: Champion's Reaction, Deity's Domain Spell, Divine Ally, an Ancestry feat slot, a Class feat slot, plus a Free Archetype slot. UI needs to make this navigable, not overwhelming.
**Recommendation:** Phase Level-Up as its own implementation phase. Treat prerequisite-DSL as a sub-deliverable. Plan for an "escape hatch" where a non-evaluated prerequisite shows as a warning ("kann nicht automatisch geprüft werden") rather than a hard block, so unusual feats don't break the flow.
## Competitor Feature Analysis
| Feature | Pathbuilder 2e | Wanderer's Guide | Foundry VTT (PF2e) | Owlbear Rodeo | Our Approach |
|---------|----------------|------------------|---------------------|---------------|--------------|
| Level-Up | Full, mature, English-only | Full, web-based, English-only | Full via PF2e Leveler / PF2e Level-Up Wizard modules | N/A (no character system) | Full, German, integrated, with Free Archetype |
| Dice roller | Basic | Basic | Excellent (PF2e-specific) | Built-in, simple | PF2e degree-of-success + roll log + chat embed |
| Chat | None | None | Yes, with whisper/blind | Yes, simple | Yes, with roll embed + push-ping |
| Battle map | None | None | Heavy, feature-rich (lighting, vision, fog) | Lightweight, fast, in-person-friendly | Lightweight + dedicated table-display mode |
| Player display screen | N/A | N/A | Possible via second browser, not optimized | Cast feature (Chromecast/separate monitor) — fully read-only player view | Dedicated `/battle/:id/display` route, read-only, optimized for embedded table screen |
| Push notifications | None | None | None (it's Electron, not PWA) | None | Web Push with VAPID, GM→player ping |
| Offline | No (web app) | No (web app) | Local install, but no field offline | Browser-cached after load | Service Worker cache-first for read |
| Obsidian integration | No | No | Possible via 3rd-party module | No | Native vault browser |
| German UI | No | No | Partial via Babele + community pack | Partial | Full, including auto-translated PF2e text |
| Hosting model | SaaS | SaaS | Self-hosted | SaaS (free + paid tiers) | Self-hosted (matches PROJECT.md) |
| Mobile-first | Tablet-first | Desktop+tablet | Desktop, mobile painful | Mobile-acceptable | Yes (already shipped for character sheet) |
| Cost | One-time app purchase | Free | One-time license fee | Free + paid tiers | Self-hosted, group only |
### Key Takeaways
- **No competitor combines all six target areas** of this milestone in one app. Pathbuilder excels at character (esp. level-up) but is character-only. Foundry has battle + chat + dice but desktop-heavy and module-fragmented. Owlbear has the cleanest player-display-screen story but no character system. Obsidian is its own thing entirely.
- **The "all-in-one for our group, in German, on mobile-first PWA" niche is unoccupied.** This is the differentiator.
- **PF2e Leveler and PF2e Level-Up Wizard (Foundry modules) prove that prerequisite-validating Level-Up is feasible** — they exist and are maintained. We can study their data models without using their code (license / system difference).
- **Owlbear's "cast" feature is the closest to our table-display goal** — read-only, joins as fake-player, cannot see GM-only content. That's a solid mental model.
## Sources
- [Pathfinder 2e Leveling Up — Archives of Nethys](https://2e.aonprd.com/Rules.aspx?ID=2065)
- [Pathfinder 2e Ability Boosts — Archives of Nethys](https://2e.aonprd.com/Rules.aspx?ID=75)
- [Pathfinder 2e Skill Increases — Archives of Nethys](https://2e.aonprd.com/Rules.aspx?ID=2109)
- [Pathfinder 2e Free Archetype — Archives of Nethys](https://2e.aonprd.com/Rules.aspx?ID=2751)
- [Wanderer's Guide character builder](https://wanderersguide.app/)
- [PF2e Leveler — Foundry VTT module](https://foundryvtt.com/packages/pf2e-leveler)
- [PF2e Level-Up Wizard — Foundry VTT module](https://foundryvtt.com/packages/pf2e-level-up-wizard)
- [Owlbear Rodeo Casting documentation](https://docs.owlbear.rodeo/docs/casting/)
- [Foundry VTT Basic Dice](https://foundryvtt.com/article/dice/)
- [Roll20 Dice Reference](https://help.roll20.net/hc/en-us/articles/360037773133-Dice-Reference)
- [PWA Best Practices 2026 — Wirefuture](https://wirefuture.com/post/progressive-web-apps-pwa-best-practices-for-2026)
- [PWA iOS Limitations and Safari Support 2026 — MagicBell](https://www.magicbell.com/blog/pwa-ios-limitations-safari-support-complete-guide)
- [Apple reverses decision about blocking web apps in EU — TechCrunch](https://techcrunch.com/2024/03/01/apple-reverses-decision-about-blocking-web-apps-on-iphones-in-the-eu/)
- [@portaljs/remark-wiki-link — npm](https://www.npmjs.com/package/@portaljs/remark-wiki-link)
- [react-markdown documentation](https://remarkjs.github.io/react-markdown/)
- [airjp73/dice-notation — GitHub](https://github.com/airjp73/dice-notation)
- [Foundry VTT vs Roll20 vs Owlbear Rodeo 2026](https://gmcrafttavern.com/foundry-vs-roll20-owlbear-2026/)
---
*Feature research for: Dimension47 next milestone (PWA + multi-screen battle + extended WebSockets + Obsidian read-only vault + full PF2e Level-Up)*
*Researched: 2026-04-27*