- The campaign page shows one part at a time, picked from a row of
buttons under its name: Overview (characters and encounters), NPCs,
Locations, Weapons, Items, Spells, Monsters, Notes and Settings for
the DM; Overview, Places and Notes for a player. Each button counts
what is in its part. On a phone the row scrolls sideways. The part
showing is in the address (?view=weapons), so the back button steps
through the parts.
- NPCs, weapons, items, spells and monsters are lists of short rows.
Clicking a row opens a pop-out with everything about it and
everything that can be changed. Adding one, by hand or from the
library, is a pop-out too: a window on a wide screen, the whole
screen on a phone.
- "Search this campaign" looks through everything added to the
campaign at once: characters, encounters, locations and notes, and
for the DM also NPCs, weapons, items, spells and monsters. Each of
the DM's lists has a search box of its own as well.
- With three pages or more, the page number of a paged list is a menu
to jump straight to any page.
- The invite code, the party and archive or delete are under Settings.
- A weapon's properties and range, and a spell's casting time, range
and duration, are shown in its pop-out.
- All packages at version 1.13.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Live updates start on plain requests and move up to a websocket when
one gets through. The site used to ask for the websocket first, with
no way back: behind a proxy that does not pass the upgrade, nothing
live arrived at all.
- A browser asks the API's leave before a request, the site and the API
being on different hosts. It now remembers the answer for two hours,
where it used to ask before nearly every request.
- A built file is kept by the browser for good: its name changes when
its contents do. Each used to be checked again on every page load.
- For a real websocket through nginx, the blocks that pass requests to
the API need "proxy_http_version 1.1", "proxy_set_header Upgrade
$http_upgrade" and "proxy_set_header Connection "upgrade"".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- An action in an encounter no longer loads the encounter again: the
answer to the action already holds it. Live updates that arrive
together are answered with one reload, of the encounter or character
that changed, where each used to reload every one on screen.
- Everything the site sends is compressed. Nothing in front of it did
that (frp only tunnels), so the API and the built site now do it
themselves: the main script is 100 kB on the wire, down from 330 kB.
- Each page is its own download, fetched the first time it is opened,
so signing in does not wait on the encounter tracker or the builder.
- The library is fetched when one of its pickers is opened, where the
campaign page used to fetch it on every visit by the DM.
- The database has indexes on the columns every list is looked up by,
and checking that someone is in a campaign takes one query, not two.
- On a server: "npm install", then "npm run deploy", then build the
frontend again and restart both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A weapon, item, spell or monster from the library can be added to a
campaign once. Adding it again is refused: "Longsword is already in
this campaign."
- The library list leaves out what the campaign already has, so what is
left is what can still be added. When nothing is left it says so.
- An entry counts as added while the campaign has one by that name,
whatever its capitals. Rename or delete the campaign's copy and the
library offers it again. This also covers what a world's seed put in.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A DM can start a campaign from a ready-made world by typing its
six-character code: "+ New Campaign" on the Campaigns page, then "Or
start from a ready-made world". The whole world is built in one go
with them as its DM: locations, weapons, items, spells, monsters,
NPCs, encounters and notes. ALDENF is Aldenfell, HOLLOW is Hollowcrown.
- A world is one file in /backend/seeds. Drop another in and its code
works straight away, with no restart. "npm run seeds:check" lists
every world, or what is wrong with one: a misspelt field, a name used
twice, an encounter pointing at something the file does not have. A
file with a mistake in it is never offered. docs/SEEDS.md has the
format.
- A seed can now hold everything a campaign can: gear effects, an NPC's
wares and exchange rate, things for sale at an encounter, and rewards
in silver, copper and cash.
- The database seed creates the admin account and nothing else. The
Aldenfell and Hollowcrown seed commands are gone: worlds come from
codes.
- Hollowcrown follows the V3 book: 4 starting items and 3 things
equipped, the book's effects on every weapon and item, armor as items
(library, modern and magic), worn gear at the book's levels, damage
types on monsters, ten shop scenes with prices and stock, five money
changers, Meridian loot as cash and mixed hoards as gold, silver and
copper.
- Aldenfell: the Shield and Leather Armor change AC, Mireille and the
Founding Fair stalls sell things, and the book's missing scenes are in
(E5, E7, E15, E16, E18, E23-24, E26, the Drowned Shrine, Sevrisk's
Hollow, a wyvern pass). The locket is found with Investigation, as the
book has it.
- Packages are up to date: Prisma 7 (with the pg driver adapter and a
prisma.config.js that holds the database URL), Express 5, zod 4,
dotenv 18, jest 30, bcrypt 6 and TypeScript 7. "npm audit" finds
nothing. Install scripts are approved for Prisma and bcrypt. On a
server: "npm install", then "npm run deploy".
- The frontend's five lint warnings are fixed; useAuth and usePagination
have files of their own.
- All packages at version 1.12.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A player can no longer heal or hurt their own character: the Damage,
Heal and Temp HP controls on the sheet are the DM's, and the server
refuses the change from anyone else. Players still roll their own
death saves.
- A player can no longer add money to their own purse or write it off:
recording a gain or a spend is the DM's, in any coin or in cash, on
the sheet and on the server.
- Players still exchange gold, silver and copper on the sheet, give
money to another character, and buy from or change money with an NPC.
- All packages at version 1.11.1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Weapons and items can carry effects: bonuses and penalties to AC, speed,
initiative, max HP, passive Perception, ability scores, saving throws
and skills, plus a note. They apply on their own while equipped and stop
when the thing comes off. Armor is an item with an AC effect. The DM
sets them with "Effects" on a row in the weapon or item pool.
- The sheet's "armor bonus" is now "Extra AC", the DM's own adjustment on
top of gear, and only the DM can set it.
- Only what is equipped counts: a weapon has to be equipped to be used in
an encounter. A character can have two things equipped at once, one of
them a weapon (campaign settings). Equipping at the limit is refused
with a message, and can be changed at any time, mid-encounter included.
- A built-in item library: armor, shields, worn gear and supplies, with
their effects set. The weapon library gains paired weapons (a pair of
daggers is one weapon).
- A floating character button on every page opens a panel with a
character's numbers and everything they hold, with equip ticks. Players
get their own characters, the DM everyone's, and each character card in
an encounter has an Inventory button. It replaces the quick stats drawer.
- A player's own characters stand out: marked and highlighted in
encounters, with a button that jumps to their card; highlighted on the
party screen; and listed once, not twice, on the campaign page.
- All packages at version 1.11.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The main destinations are always on screen: Campaigns, Campaign and
Party (for the campaign last visited, from any page) and Account. They
are links along the top bar on a wide screen, and a bar along the
bottom on a phone or small tablet (900px or less).
- Nothing floats over the page on a phone: the dice roller is the last
button of the bottom bar, and quick stats sits in the top bar.
- The campaign page and the character sheet start with a row of links to
their sections.
- On a small screen every table is a stack of labelled cards, rows of
controls wrap, fields shrink to fit, and things to tap are bigger.
- The encounter list is paged, ten to a page, as is the archived list.
Moving an encounter still works across pages.
- Text boxes with no type given, and native checkboxes and dropdowns, now
match the dark theme. Long monster notes and item descriptions wrap
inside their table cell.
- All packages at version 1.10.1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- An NPC can change gold and cash at a rate of their own ("2 gold = $15"),
the same both ways. Only gold and cash are taken: no silver, no copper
and no change, and the amount has to be a whole multiple of the rate.
- An NPC can sell weapons and items from the campaign pools, each with a
price in any coin or in cash, a level and an optional stock. The wares
follow the NPC into every quest. An encounter can sell things itself
too, for a stall with nobody behind it.
- Trading is open only in an NPC quest in progress, never in a battle,
with an NPC who is in the scene and standing, for a character who is in
it. Players see every rate and ware and trade for their own character
in a new Trade card; the DM can trade for anyone.
- Only the DM sets trade up: "Trade" on an NPC's row on the campaign page,
and the DM's part of the Trade card for an encounter's own wares. A
ware's price and stock can be edited afterwards.
- Every exchange and purchase is written to the character's money log.
- All packages at version 1.10.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- "+ Add Monster" takes the whole stat block: challenge rating, speed, the
six ability scores, special trait and notes, as well as name, AC, HP,
attack and damage. Damage can name its type ("1d6+2 necrotic").
- Monsters can be edited: "Edit" on a row opens the same form filled in.
Copies already in encounters show the new stat block.
- The monster list shows each full stat block, the library picker shows
speed and ability scores too, and removing a monster asks first.
- Characters have a fourth balance, cash ($), for crossover worlds. It is
gained, spent, given and awarded like a coin, but it has no worth in
coins: it is never exchanged or used to make change.
- `npm test` in the backend runs again (the script pointed at a jest path
that does not exist in the workspace).
- All packages at version 1.9.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- In a battle in progress, whoever is on turn is at the top of the list
with those still to act beneath them. Each combatant whose turn has
passed drops to a "Next Round" section at the bottom, and a new round
puts everyone back.
- All packages at version 1.8.1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A dead character, or a monster or NPC at 0 HP, is out of the fight: the
server no longer sends it to players, target marks included, and it has
no turn. Healing or reviving brings it straight back.
- The DM's screen leaves the fallen out too until "Show dead" is ticked,
which lists them in a group of their own, marked hidden.
- Players see dead characters by name in a Fallen box. The player whose
character is on turn in a battle gets "Try revive" there if that
character is on their feet and knows a spell that revives, at a level
they can cast. The dead come back at 1 HP.
- Spells have a "Revives" tick in the campaign's spell list. Revivify and
Raise Dead have it, in the library and in existing campaigns.
- A dead character cannot be added to an encounter until revived.
- All packages at version 1.8.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- In a battle under way, whoever is on turn has no Target button on their
card, and the server refuses a target list that includes them.
- All packages at version 1.7.2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The amount an area attack adds to each target's AC per extra target is
now set per campaign, from 0 (no penalty) to 10. It starts at 2, so
existing campaigns behave as before.
- The DM changes it in the campaign settings; the attack bar and the
targets' cards use it.
- All packages at version 1.7.1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- More than one combatant can be marked as a target; the Target button now
adds to the targets instead of moving the mark.
- Several targets make an area attack, which is harder to land: every
target's AC counts as 2 higher for each target beyond the first. The
attack bar shows the AC to beat, and each target's card names the penalty.
- The DM unticks any target the roll missed, then applies one total: split
evenly between those hit (remainder to the first marked), or the full
amount to each. Each share is shown before it is applied.
- The single target column from V1.6.0 becomes a list, carried over by the
migration.
- All packages at version 1.7.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- One combatant at a time can be marked as the target with the Target
button on its card. The DM can mark anyone at any time; a player can
while their own character is on turn in a battle.
- The target's card is outlined for everyone and names who is going for it.
- While a target is marked the DM gets an attack bar above the list: who is
attacking whom, the target's AC and HP, the attacker's weapons, spells or
monster attack, and a box to apply damage or healing straight away.
- The target is cleared when the turn or round moves on, when the encounter
begins, ends or is reopened, or when the target is removed.
- All packages at version 1.6.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A character at 0 HP is Dying, Stable or Dead. The tallies live on the
character, so the sheet and the encounter card always agree.
- Death saves are typed in as the d20 showed: 10 or more succeeds, less
fails, a 1 fails twice, a 20 puts the character back up at 1 HP. Three
successes make them stable; three failures kill.
- Damage taken at 0 HP is a failed save and ends stable. A blow that leaves
as much as max HP still to take after reaching 0 kills outright.
- Healing from 0 clears the tallies. The dead cannot be healed; the DM
revives them at 1 HP.
- A player rolls and stabilises for their own character; the DM for anyone,
and only the DM sets tallies by hand or revives.
- The party overview, campaign list and quick stats show the state.
- All packages at version 1.5.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A character's purse holds gold, silver and copper as separate coins:
1 gold = 10 silver = 100 copper. The money log records each entry's coin.
- Spending and giving are paid from the whole purse: coins of the kind
named go first, then the nearest bigger coin is broken (change comes back
in as few coins as possible), then smaller coins are counted out. A
payment is refused only when the whole purse isn't worth enough.
- Exchange converts one coin into another at the fixed worth.
- Encounter rewards and gifts between characters can be in any coin; the
party overview shows the whole purse.
- All packages at version 1.4.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Quests take initiative rolls like battles do; each quest group lists
highest first. The total is roll plus bonus and can exceed 20 (test added).
- Info tooltips are drawn against the viewport, so the party overview
table (or any scrolling container) can't cut them off.
- backend: `npm run deploy` applies migrations and regenerates the Prisma
client in one step; README explains why both are needed on a server.
- All packages at version 1.3.1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Hollowcrown: The Rift Between Worlds as its own seed (npm run
seed:hollowcrown), built from the campaign book: pools, 58 monsters,
57 NPCs, 28 locations, 72 encounters with rewards, and DM notes. Shared
seeding logic moved to prisma/seedCampaign.js.
- What players can see: only encounters their own character is in; only
the pool entries their character holds (plus starting options while
building); only locations their character has been to; no invite code;
no gold, inventory or money log of other players' characters. Socket
events carry ids only and campaign rooms are members-only.
- Encounters have a location; while one is in progress its characters are
there, and visits are remembered.
- Campaign setting to show players a health bar only for monsters and NPCs.
- Initiative is entered as the d20 roll (1-20) and the bonus is added;
players can enter their own character's roll.
- Number fields enforce their limits when typing, and the API enforces
the same limits.
- Temp HP shows on HP bars and absorbs damage before real HP.
- All packages at version 1.3.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Campaigns: DM can archive/restore; owner can delete. Archived campaigns
move off the main list and stop accepting invite codes.
- Encounters: DM can archive/restore and delete, and arrange the campaign's
own order; the list can also be sorted by name, status, type or date.
Archived encounters are hidden from players' lists.
- Account page with change password (POST /auth/password).
- Seed is now additive (safe on a live database; --reset for the old wipe)
and builds a fuller Aldenfell: earned weapons, item pool, spells, NPCs,
and 28 battle/quest scenes with descriptions, DM notes and rewards.
- Vite preview host config for the deployed site.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Characters
- Builder: pick-then-Next on every step with live preview, Back button,
plain-language help throughout, and "Suggest for me" for ability scores
- Motivation is picked from a list; new steps for special abilities,
background and appearance, all composed from fixed lists and DM-only
to edit afterwards
- Copy a character to another campaign
- Characters can give gold, weapons, items and spells to each other
- Money tracker: gold only changes through a logged ledger
- Fixes: level/XP/location are DM-only, HP stays within 0..max, physical
dice ability rolls, every die is rolled once
Gear
- DM-managed item pool; weapons, items and spells are handed out by the DM
- Starting-option flag per pool entry
- Gear levels 1-9 per held copy with a damage ladder, growth rate and
starting level; spells gated by spell level with a fixed damage value
- Spell library carries default damage; damage is picked from a list
Encounters
- Battle and NPC quest modes, turn tracking, scene description, DM notes
- NPCs, richer combatant cards, conditions from a list
- Rewards (gold, weapons, items) lined up and awarded, with gold splitting
- Character HP is shared between the sheet and the encounter
- Monster stat blocks and NPC secrets are never sent to players
Other
- Dice roller on every page
- Docs for characters, weapons, spells, items, encounters, monsters and
NPCs, with full lists generated from the data (npm run docs:lists)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Seed now resets the database and seeds the Aldenfell campaign from the
campaign book: admin DM user, default weapons, locations, bestiary,
pre-built encounters, and DM/shared notes
- Default weapon/spell/monster library, character profile fields,
locations and dice mode (new migration)
- Party overview page, pagination, info tips, build preview calc
- Remove stale demo-login hint; notes preserve line breaks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>