An in-person companion app for The Resistance: Avalon. Everyone sits around a real table; each player's phone handles the secret stuff (roles, votes, mission cards) so you don't need a physical deck. By default the app runs the whole game, but it can hand off as much of that as you want back to the table — see How much the app does below.
NOTE: Not affiliated with the official Avalon game or its creators.
Host: open the app, tap Host, enter your name. You'll land in a lobby with a 4-character room code.
Everyone else: open the app, tap Join, enter the room code and your name.
In the lobby, drag the player list into your real seating order around the table — this drives leader rotation and, if enabled, who starts holding the Lady of the Lake. The host picks settings (below) and taps Start game once at least 5 players have joined.
Each step (role reveal, who's Evil, who Merlin sees, who Percival sees, dawn) shows a hold-to-reveal button — press and hold to see your info privately, release to hide it again. Tap I'm ready once you've seen it; the app auto-advances to the next step once everyone's ready, so no one has to announce anything out loud. The host also has a manual Next button as a fallback if someone's stuck.
The current leader picks a team. Depending on settings, everyone either votes/plays mission cards in-app, or the table just discusses and plays out loud while the host records the outcome (see How much the app does). Rejected proposals rotate the leader; enough rejections in a row ends the game for Evil unless Force approve last proposal is on.
Lady of the Lake (if enabled) kicks in after missions 2, 3, and 4 — the current holder privately investigates one other player's alignment, then passes the token to them.
Assassination: if Good wins 3 missions with Merlin in play, the Assassin gets one guess at who Merlin is before the game ends.
Game over shows the winner and everyone's true role. The host can tap Play again to spin up a fresh room with the same roster and settings — no need to re-enter names. Leadership continues where it left off: whoever would have proposed next leads the rematch.
| Setting | What it does |
|---|---|
| Starting leader | Pick who proposes first, or leave it Random. |
| Special roles | Toggle Merlin, Percival, Morgana, Mordred, Oberon, Assassin on/off. |
| Custom Good/Evil counts | Override the standard player-count table. |
| Max rejected proposals | How many rejections in a round before Evil wins. |
| Force approve last proposal | Auto-approves the proposal that would otherwise end the game for Evil. |
| Lady of the Lake | Enables Lady of the Lake. |
| Simplified voting / Simplified missions / Host can act on a player's behalf | See below. |
| Team only mode | See below. |
These settings sit on a scale from fully app-driven (the default — every vote and mission card goes through each player's phone) to almost entirely in-person, where the app steps back and the table just plays it out loud. Dial it to wherever your group prefers:
- Simplified voting — proposal votes happen out loud; the host taps Approve/Reject on the outcome instead of everyone voting in-app.
- Simplified missions — mission cards are played physically (face-down cards, thumbs, whatever); the host taps in the fail count.
- Host can act on a player's behalf — lets the host propose a team, choose a Lady of the Lake target, or choose an assassination target for whoever's turn it is (the original is still able to act, too).
- Team only mode — the far end of the scale: the app only handles role assignment. Once the night phase ends, it shows a plain "game in progress" screen and steps out of the way entirely — proposals, votes, missions, Lady of the Lake, assassination, all played at the table with no app involvement. The host just taps Good wins or Evil wins when the table's decided the outcome. (Every other proposal/mission/Lady setting is irrelevant in this mode and gets hidden from the lobby.)
Press and hold the header for a few seconds (host only) to open the game admin panel:
- New room for everyone — abandon the current game and start fresh with the same roster, from any point in the game.
- Troll mode — a per-player prank toggle that makes a Loyal Servant briefly think they were supposed to be Merlin or Oberon. Purely cosmetic, never changes actual odds.
- Reveal all roles — hold-to-reveal the full role list.
cp .env.example .env # fill in DATABASE_URL, PORT, and ADMIN_PASSWORD
docker compose up -d db # or point DATABASE_URL at your own Postgres
npm install
npm run db:deploy
npm run devThen open http://localhost:3000.
Other useful scripts: npm run lint, npm run format / format:check (Prettier), npm run test:e2e (Playwright), npm run db:studio.
/admin, gated by the ADMIN_PASSWORD env var, lists past games (sorted by creation time) with delete, and lets you drill into a game's raw event log for debugging.