multiplayer-game-discord

byBrandon

I want to create a multiplayer game that can be played from Discord using their new GUI, or on a web browser. React will be the front end. Node can be the backend. I want to use MongoDB. I haven't decided on a theme but the game basics: It will be flat, with only text and buttons. Nothing too graphical. I like simple. Players will have on hand cash. They can also deposit into a bank. Cash can be stolen, or used to buy items. Features: Work - every hour players can collect a random amount of cash $100-$300 and once they claim, the counter starts again. Lottery - Every 24 hours there is a lottery. Players can get into the lottery by clicking or entering the lottery. Winners get $500-$750 Rob - Players can Rob other players cash on hand with a probability. If they fail, there's also a probability of being caught by police and placed into jail. Jail - Players who get sent to jail cannot work, rob others, lottery, etc until their 1-2 hours are up. They can attempt escaping every 30 minutes. Bank - Players can deposit their on hand cash to keep it safe. They can also withdraw. Blackjack - Players can play a game of blackjack using on hand cash. Heist - Players can team up (up to 4) to rob a bank. There is a low % of success and if failing, ther is a % they will be sent to jail for double the amount compared to robbing someone. But if the bank does get robbed, the value is all the players banked money, split between the people who robbed the bank. There needs to be a way to announce events (players was robbed, winning money, etc) but when someone deposits or withdraws, that is not announced. Accounts will be using discord or google, and I want it to be simple enough that when someone plays from Discord, they don't need to goto a separate login page or anything. It just gets their details from their logged in discord and uses that for their account (email based?) Let's start there. Help me design the UI for this and a theme that would fit this design.

Landing
Landing

Comments (0)

No comments yet. Be the first!

System Requirements

System Requirements Document for multiplayer-game-discord

1. Introduction

multiplayer-game-discord is a simple, flat, text-and-button multiplayer crime-economy game. It is played two ways: from inside Discord using Discord's new GUI, and from a web browser. The product intent is a fast-to-read social economy where players hold on-hand cash, protect it in a bank, steal from each other, gamble it, and team up for high-risk bank heists — all rendered as a legible instrument panel of numbers, timers, probabilities and ruled data rows rather than a graphical game.

The audience is Discord-native players (roughly 18–30) who already live in flat, text-dense dark interfaces and expect to read balances, countdowns and odds at a glance. The game is deliberately un-graphical: no illustration, no casino imagery, no decorative motion. The visual content is the data itself.

The product is built with a React front end, a Node backend, and MongoDB for persistence. Accounts are established through Discord or Google, and a player entering from Discord never sees a separate login page — their logged-in Discord identity is used directly for their account.

Page 1 of 44

2. System Overview

The game is a persistent multiplayer economy. Every player has two money positions — on-hand cash and banked cash — plus a set of timed states (work cooldown, lottery entry, jail sentence, escape gate, heist membership). All of these are durable and shared across players, so the backend owns balances, timers, jail state, lottery participation, blackjack outcomes, heist membership and event records, and background automation resolves the hourly work window, the 24-hour lottery draw, jail release and escape timing, and heist resolution.

Players act through a small set of flat, text-and-button surfaces: a public Landing entry, an authenticated Dashboard overview, and dedicated surfaces for Work, Lottery, Rob, Jail, Bank, Blackjack, Heist and Events. A persistent player plate shows Cash, Bank and Net worth as ruled label/value rows on every authenticated screen, and a single-line event ticker announces robberies, lottery wins and heist outcomes — while deposits and withdrawals are never announced.

Actors. The accepted active human personas are Player and Heist Teammate. Discord and Google are provider-owned authentication surfaces, not personas. The backend and its background automation are system processes.

Narrow exclusions. The UI stays flat with only text and buttons and nothing too graphical. Deposits and withdrawals are never announced. Playing from Discord must not require a separate login page. Jailed players cannot work, rob, enter the lottery, or take other actions until their sentence ends.

Page 2 of 44

2a. Product Interpretation and Delivery Boundary

Current delivery. The current product is a first-party web application (React front end, Node backend, MongoDB) plus a Discord-side entry. The web application owns the Landing entry, the authenticated game surfaces, and all game state. Discord's GUI is a provider-owned surface that hands the already-authenticated Discord user into the game; the player does not pass through a separate login page there. Google sign-in is a provider-owned authentication surface used from the web entry.

Access ownership. The Landing page is anonymously reachable and explains the game and its two entry paths. Everything that reads or changes a player's durable state — Dashboard, Work, Lottery, Rob, Jail, Bank, Blackjack, Heist, Events — requires an established player identity. Identity is established by Discord or Google; the game binds that provider identity to a player account (email-based) and keeps balances, timers and outcomes attached to the correct player. Identity continuity is required because money, jail sentences, lottery entries and heist membership must remain bound to the right participant across sessions and across the two entry surfaces.

Current vs. future. Everything described in this document is current. No future-horizon features are accepted in the authoritative thread; the "buy items" mention in the source is a stated property of on-hand cash (cash can be used to buy items) and is recorded as a constraint on cash, not as a current item-shop capability.

2b. Source Content Inventory

Not applicable — no reference directive in this request declares a content_source.

2c. Page Content and Component Coverage

Page 3 of 44

Landing

  • Information/state: Anonymous first impression. Oversized two-line headline "GET RICH / GET LOCKED UP" in Archivo 700 uppercase, flush-left on the graphite ground; the game's one-line rule set beneath it at 16px; a hairline rule; two 44px rectangular entry buttons. Right side: a bordered "state of the city" plate with four ruled rows (Cash in circulation, Players in jail, Next lottery, Heist success %) in tabular amber numerals, and beneath it the single-line event ticker.
  • Primary actions: "Play in Discord" (signal-orange, rectangular) — enters the game through the Discord GUI using the logged-in Discord identity, with no separate login page. "Open in browser" (outlined, rectangular) — enters the web application, where identity is established via Discord or Google.
  • Supporting actions: None beyond the two entry paths.
  • Domain entities: Public aggregate readouts only (circulating cash, jailed player count, next lottery time, heist success percentage), public event ticker entries.
  • Component responsibilities: Hero headline block; rule-set line; entry button bar; state-of-the-city plate with four ruled label/value rows; event ticker (single-line marquee, amber timestamps, 1px vertical rules, deposits and withdrawals excluded by rule).
  • States: Loading — plate rows and ticker show placeholder rules until public aggregates resolve. Empty — if no public events exist yet, the ticker shows a single quiet "No events yet" row rather than an empty strip. Success — plate and ticker render live values. Error — if public aggregates fail, the plate shows "—" in each value column and the entry buttons remain usable. Recovery — the plate retries on next view; entry is never blocked by a failed readout.
Page 4 of 44

Dashboard

  • Information/state: Authenticated overview. Persistent left rail player plate (avatar initial, handle, and three ruled rows: Cash in amber, Bank, Net worth, all tabular numerals); numbered action tabs 01–06 (Work, Rob, Bank, Lottery, Blackjack, Heist) as a vertical list with hairline separators and a 2px orange underline on the active item; main panel showing current status — work cooldown remaining, lottery entry state and next draw, jail state if any, and the event ticker.
  • Primary actions: Continue into any of the six numbered action tabs; open Jail when jailed; open Events.
  • Supporting actions: Refresh status.
  • Domain entities: Player account (handle, avatar initial, email-based identity), on-hand cash, banked cash, net worth, work cooldown, lottery entry, jail sentence and escape gate, heist membership, event records.
  • Component responsibilities: Player plate (gauge-like balance readout; its rule colour flips to signal orange while jailed); numbered tab list; status ledger of ruled label/value rows; event ticker; jail countdown block when jailed.
  • States: Loading — plate rows and status rows show ruled placeholders. Empty — a brand-new player shows Cash 0, Bank 0, Net worth 0 and a Work tab ready to claim. Success — balances, timers and status render with tabular numerals. Error — a failed status read shows "—" per row with a retry control; the player plate keeps its last known values. Recovery — retry re-reads status; if the session has expired, the player is returned to Landing to re-establish identity.
Page 5 of 44

Work

  • Information/state: The hourly work claim. Shows the claim button, the payout range ($100–$300), and the countdown to the next claim once the current one is taken.
  • Primary actions: Claim the hourly work payout.
  • Supporting actions: None.
  • Domain entities: Work cooldown timestamp, claimed payout amount, on-hand cash.
  • Component responsibilities: Claim button (44px, signal orange, disabled while the counter runs); countdown numerals (tabular, ticking in place); payout readout that counts up in 400ms tabular steps on claim.
  • States: Loading — countdown shows ruled placeholder. Empty — no claim taken yet: button is enabled and the counter reads ready. Success — a random $100–$300 is added to on-hand cash, the amount counts up, and the counter restarts from one hour. Error — a failed claim leaves the counter unchanged and shows a retry; no cash is granted. Recovery — retry re-attempts the claim; if the counter had already restarted server-side, the button shows the remaining time instead of double-paying. Blocked — while jailed, the claim is unavailable and the Jail countdown block replaces the action grid.
Page 6 of 44

Lottery

  • Information/state: The 24-hour lottery. Shows entry state (entered / not entered), the countdown to the next draw, and the winner payout range ($500–$750).
  • Primary actions: Enter the lottery by clicking or entering it.
  • Supporting actions: None.
  • Domain entities: Lottery round, entry record per player, draw time, winner, payout amount.
  • Component responsibilities: Entry button (44px, signal orange, disabled once entered or while jailed); draw countdown numerals; entry-state row; winner/payout readout.
  • States: Loading — draw countdown shows ruled placeholder. Empty — before any round has resolved, the panel shows the next draw time and an enabled entry button. Success — entry is recorded and the button shows entered state until the draw; on draw, winners receive $500–$750 and the win is announced in the ticker. Error — a failed entry leaves the player unentered and shows a retry. Recovery — retry re-attempts entry; a duplicate entry attempt for the same round is rejected without charging or double-entering. Blocked — jailed players cannot enter.
Page 7 of 44

Rob

  • Information/state: Target selection and robbery resolution. Shows a list of other players with their on-hand cash, the robbery success probability as a line-art gauge (1px rule with a filled signal-orange segment and the exact percentage in tabular numerals at the right end), and the outcome of the last attempt.
  • Primary actions: Select a target and attempt the robbery.
  • Supporting actions: Refresh the target list.
  • Domain entities: Target player, target on-hand cash, robbery success probability, failure outcome, police-catch probability, jail sentence.
  • Component responsibilities: Target list as ruled rows; probability gauge; attempt button (44px, signal orange); outcome readout.
  • States: Loading — target rows show ruled placeholders. Empty — if no other players hold on-hand cash, the list shows a quiet empty row and the attempt button is disabled. Success — on a successful robbery the stolen cash moves from the target's on-hand cash to the robber's on-hand cash, both balances update, and the robbery is announced in the ticker. Failure — the robbery fails and no cash moves; a separate probability may then place the robber in jail, which is announced. Error — a failed request leaves both balances untouched and shows a retry. Recovery — retry re-attempts against the current target list; a target who no longer holds cash is removed from the list. Blocked — jailed players cannot rob.
Page 8 of 44

Jail

  • Information/state: The jailed state. The action grid is replaced by one oversized tabular countdown at clamp(40px, 9vw, 76px) showing the remaining 1–2 hour sentence, plus a single "Attempt escape" button whose disabled state shows the 30-minute gate. The player plate's rule colour flips to signal orange.
  • Primary actions: Attempt escape (available once every 30 minutes).
  • Supporting actions: None.
  • Domain entities: Jail sentence start and end, sentence length (1–2 hours), escape attempt gate (30 minutes), escape outcome.
  • Component responsibilities: Oversized countdown block; escape button with disabled gate state; blocked-action notice listing what is unavailable (work, rob, lottery, etc.).
  • States: Loading — countdown shows ruled placeholder. Empty — not applicable; this surface only exists while jailed. Success — a successful escape ends the sentence early and returns the player to normal play; the release is announced. Failure — a failed escape leaves the sentence running and re-arms the 30-minute gate. Error — a failed escape request leaves the gate unchanged and shows a retry. Recovery — retry is available once the gate re-opens. Expiry — when the sentence reaches zero the player is released automatically and normal actions become available again.
Page 9 of 44

Bank

  • Information/state: Private deposit and withdrawal between on-hand cash and banked cash. Shows both balances as ruled label/value rows and the amount input.
  • Primary actions: Deposit on-hand cash into the bank; withdraw banked cash to on-hand.
  • Supporting actions: None.
  • Domain entities: On-hand cash, banked cash, deposit amount, withdrawal amount.
  • Component responsibilities: Amount input; deposit button; withdraw button (both 44px, signal orange, never both orange-and-amber on one control); balance rows in tabular numerals.
  • States: Loading — balance rows show ruled placeholders. Empty — a player with no cash sees both balances at 0 and disabled actions. Success — the amount moves between the two balances and both rows update; no announcement is produced. Error — a failed deposit or withdrawal leaves both balances untouched and shows a retry. Recovery — retry re-attempts the movement; an amount exceeding the source balance is rejected without partial movement. Privacy rule — deposits and withdrawals never appear in the event ticker.
Page 10 of 44

Blackjack

  • Information/state: A blackjack game wagering on-hand cash. Shows the wager input, the dealt hand, the dealer's hand, and the round result.
  • Primary actions: Place a wager and deal; hit; stand.
  • Supporting actions: Start a new round after a resolved one.
  • Domain entities: Wager amount, player hand, dealer hand, round outcome, on-hand cash.
  • Component responsibilities: Wager input; deal/hit/stand button bar (44px, signal orange); hand readouts as ruled rows; result readout that counts in 400ms tabular steps.
  • States: Loading — hand rows show ruled placeholders. Empty — no active round: wager input and deal button are enabled. Success — a won round adds the payout to on-hand cash and the result counts up; a lost round deducts the wager; a push returns the wager. Error — a failed deal or action leaves on-hand cash untouched and shows a retry. Recovery — retry resumes the round from its last resolved state; a wager exceeding on-hand cash is rejected. Blocked — jailed players cannot play.
Page 11 of 44

Heist

  • Information/state: Team formation and shared bank robbery. Shows the current team (up to 4 players), the heist success probability as a line-art gauge, the doubled jail risk on failure, and — on success — the pooled banked money to be split.
  • Primary actions: Form or join a team of up to four; commit the team to the heist.
  • Supporting actions: Leave a team before commitment.
  • Domain entities: Heist team (max 4), team members, heist success probability, failure jail risk (double the robbery sentence), pooled banked money, per-member split.
  • Component responsibilities: Team roster as ruled rows with member slots; probability gauge; commit button (44px, signal orange, disabled below the required team state); outcome readout.
  • States: Loading — roster and gauge show ruled placeholders. Empty — no team formed: the roster shows open slots and the commit button is disabled until the team is ready. Success — the bank is robbed, the pooled banked money is split between the robbers, each member's balances update, and the heist is announced. Failure — the heist fails and a percentage chance places members in jail for double the robbery sentence; the bust is announced. Error — a failed commit leaves team state and balances untouched and shows a retry. Recovery — retry re-attempts the commit; a team exceeding four members is rejected. Blocked — jailed players cannot join or commit.
Page 12 of 44

Events

  • Information/state: The visible announcement record. A single-line moving ticker of timestamped events (robberies, lottery wins, heist outcomes) in 14px tabular type with amber timestamps, separated by 1px vertical rules, plus a scrollable list of the same events for reading at length.
  • Primary actions: None required; the surface is read-only.
  • Supporting actions: Scroll the event list.
  • Domain entities: Event record (type, actor, timestamp, outcome detail).
  • Component responsibilities: Single-line marquee ticker; static scrollable event list; rule that deposits and withdrawals are never rendered.
  • States: Loading — ticker and list show ruled placeholders. Empty — no events yet: a quiet "No events yet" row. Success — events render newest-first with amber timestamps. Error — a failed read shows a retry and keeps the last known events. Recovery — retry re-reads the event record. Reduced motion — the ticker becomes a static, scrollable list in which every item can be brought fully into view.
Page 13 of 44

3. Functional Requirements

FR-1 — Play from Discord's GUI. As a Player, I should be able to play the game from inside Discord using Discord's new GUI, so that I can play without leaving Discord. (explicit)

  • Trigger/input: the player opens the game from Discord's GUI.
  • Observable result: the game surfaces render inside Discord and the player's Discord identity is used for their account.
  • Access state: no separate login page is shown; the logged-in Discord user's details are used directly.
  • Failure/recovery: if the identity handoff fails, the player is told the game could not be opened and can retry from Discord.
  • Continuation: the player lands on their authenticated game overview.

FR-2 — Play from a web browser. As a Player, I should be able to play the same game from a web browser, so that I can play without Discord. (explicit)

  • Trigger/input: the player opens the web application.
  • Observable result: the same game surfaces and the same durable player state are available.
  • Access state: identity is established through Discord or Google.
  • Failure/recovery: a failed sign-in returns the player to the entry surface with a retry.
  • Continuation: the player lands on their authenticated game overview.
Page 14 of 44

FR-3 — React front end, Node backend, MongoDB. As a Player, I should experience a game built with a React front end, a Node backend, and MongoDB, so that the product runs on the stated stack. (explicit)

  • Observable result: the interface is served by the React front end and all game state is served and persisted by the Node backend and MongoDB.
  • Failure/recovery: backend or database unavailability surfaces as a retryable error state rather than silent data loss.

FR-4 — Flat, text-and-button UI. As a Player, I should see a flat interface made of only text and buttons with nothing too graphical, so that the game stays simple and fast to read. (explicit)

  • Observable result: every surface is composed of ruled panels, label/value rows, tabular numerals and rectangular buttons; no illustration, photography, characters, casino imagery or decorative graphics appear.
  • Failure/recovery: not applicable; this is a presentation constraint.

FR-5 — On-hand cash and banked cash. As a Player, I should hold on-hand cash and be able to deposit it into a bank and withdraw it, so that I can protect money or keep it available. (explicit)

  • Trigger/input: the player enters an amount and chooses deposit or withdraw.
  • Observable result: the amount moves between on-hand cash and banked cash and both balances update.
  • Failure/recovery: an amount exceeding the source balance is rejected without partial movement; a failed request leaves both balances untouched.
  • Continuation: the player remains on the Bank surface with updated balances.
Page 15 of 44

FR-6 — Cash can be stolen. As a Player, I should be able to have my on-hand cash stolen by other players, so that holding cash carries risk. (explicit)

  • Trigger/input: another player attempts a robbery against me.
  • Observable result: on a successful robbery my on-hand cash decreases by the stolen amount and the robber's on-hand cash increases by the same amount.
  • Failure/recovery: a failed robbery moves no cash.
  • Continuation: I see the change in my balances and the robbery is announced in the event ticker.

FR-7 — Cash can be used to buy items. As a Player, I should be able to use on-hand cash to buy items, so that cash has a spending purpose beyond holding and gambling. (explicit)

  • Observable result: on-hand cash is the currency used for purchases.
  • Note: the authoritative thread states this as a property of on-hand cash; no item catalogue, shop surface or item list is specified, so no item-purchasing surface is created in this document.

FR-8 — Hourly work. As a Player, I should be able to collect a random $100–$300 once every hour, so that I have a recurring income. (explicit)

  • Trigger/input: the player claims the work payout.
  • Observable result: a random amount between $100 and $300 is added to on-hand cash and the counter restarts from one hour.
  • Failure/recovery: a failed claim grants no cash and leaves the counter unchanged; a claim already taken server-side shows the remaining time instead of paying twice.
  • Continuation: the player sees the restarted countdown and can return to other activities.
  • Blocked: while jailed, work is unavailable.
Page 16 of 44

FR-9 — 24-hour lottery. As a Player, I should be able to enter a lottery that runs every 24 hours, so that I have a chance at a large payout. (explicit)

  • Trigger/input: the player enters the lottery by clicking or entering it.
  • Observable result: the entry is recorded for the current round; when the round resolves, winners receive $500–$750.
  • Failure/recovery: a failed entry leaves the player unentered; a duplicate entry for the same round is rejected without double-entering.
  • Continuation: the player sees their entered state and the countdown to the next draw.
  • Blocked: while jailed, lottery entry is unavailable.

FR-10 — Rob other players. As a Player, I should be able to rob another player's on-hand cash with a probability of success, so that I can take cash from others. (explicit)

  • Trigger/input: the player selects a target and attempts the robbery.
  • Observable result: on success, the target's on-hand cash decreases and the robber's on-hand cash increases by the stolen amount; the robbery is announced.
  • Failure/recovery: on failure no cash moves, and a separate probability may place the robber in jail.
  • Continuation: the player sees the outcome and can attempt again against the current target list.
  • Blocked: while jailed, robbing is unavailable.
Page 17 of 44

FR-11 — Police and jail on failed robbery. As a Player, I should face a probability of being caught by police and placed in jail when a robbery fails, so that robbing carries real risk. (explicit)

  • Trigger/input: a robbery attempt fails.
  • Observable result: with the stated probability the robber is placed in jail for 1–2 hours and the jailing is announced.
  • Failure/recovery: if the catch probability does not trigger, the robber remains free.
  • Continuation: a jailed robber moves to the Jail surface; a free robber can continue playing.

FR-12 — Jail blocks actions. As a Player, I should be unable to work, rob others, enter the lottery, or take other actions while jailed, until my 1–2 hours are up, so that jail is a real lockout. (explicit)

  • Trigger/input: the player is jailed.
  • Observable result: the action grid is replaced by the jail countdown and the blocked actions are unavailable.
  • Failure/recovery: not applicable; the lockout holds until release.
  • Continuation: when the sentence reaches zero the player is released and normal actions return.
Page 18 of 44

FR-13 — Escape attempts every 30 minutes. As a Player, I should be able to attempt an escape every 30 minutes while jailed, so that I have a chance to end my sentence early. (explicit)

  • Trigger/input: the player presses "Attempt escape" once the 30-minute gate is open.
  • Observable result: a successful escape ends the sentence early and returns the player to normal play; a failed escape leaves the sentence running and re-arms the gate.
  • Failure/recovery: a failed escape request leaves the gate unchanged and can be retried once the gate re-opens.
  • Continuation: the player either resumes normal play or waits out the remaining sentence.

FR-14 — Bank deposits and withdrawals. As a Player, I should be able to deposit on-hand cash to keep it safe and withdraw it again, so that banked money is protected from robbery. (explicit)

  • Trigger/input: the player enters an amount and chooses deposit or withdraw.
  • Observable result: the amount moves between on-hand cash and banked cash; banked cash is not stealable by robbery.
  • Failure/recovery: an amount exceeding the source balance is rejected without partial movement.
  • Continuation: the player remains on the Bank surface with updated balances.
Page 19 of 44

FR-15 — Blackjack with on-hand cash. As a Player, I should be able to play a game of blackjack using on-hand cash, so that I can gamble my available money. (explicit)

  • Trigger/input: the player places a wager and deals, then hits or stands.
  • Observable result: a won round adds the payout to on-hand cash, a lost round deducts the wager, and a push returns the wager.
  • Failure/recovery: a wager exceeding on-hand cash is rejected; a failed action leaves on-hand cash untouched.
  • Continuation: the player can start a new round.
  • Blocked: while jailed, blackjack is unavailable.

FR-16 — Heist team of up to 4. As a Heist Teammate, I should be able to team up with up to four players to rob a bank, so that we can attempt a high-value shared crime. (explicit)

  • Trigger/input: a player forms a team and other players join, up to four members.
  • Observable result: the team roster shows the members and the heist can be committed.
  • Failure/recovery: a team exceeding four members is rejected; a member may leave before commitment.
  • Continuation: the team commits the heist or disbands.
  • Blocked: while jailed, a player cannot join or commit.
Page 20 of 44

FR-17 — Heist success and failure risk. As a Heist Teammate, I should face a low success percentage, and on failure a percentage chance of being sent to jail for double the amount compared to robbing someone, so that the heist is the highest-risk activity. (explicit)

  • Trigger/input: the team commits the heist.
  • Observable result: on success the bank is robbed; on failure a percentage chance places members in jail for double the robbery sentence.
  • Failure/recovery: if the jail chance does not trigger, the members remain free.
  • Continuation: the outcome is announced and members continue from their resulting state.

FR-18 — Heist payout split. As a Heist Teammate, I should receive an equal share of the robbed banked money when the heist succeeds, so that teaming up pays out. (explicit)

  • Trigger/input: the heist succeeds.
  • Observable result: the value of all the players' banked money is taken and split between the players who robbed the bank; each member's balances update.
  • Failure/recovery: on failure no banked money is taken.
  • Continuation: the heist outcome is announced and members continue from their resulting state.
Page 21 of 44

FR-19 — Event announcements. As a Player, I should see announcements of game events such as a player being robbed or winning money, so that the shared world feels alive. (explicit)

  • Trigger/input: an announceable event occurs (robbery, lottery win, heist outcome, jailing, escape).
  • Observable result: the event appears in the single-line event ticker with an amber timestamp and in the scrollable event list.
  • Failure/recovery: a failed event read shows a retry and keeps the last known events.
  • Continuation: the ticker continues to move one row per new event.

FR-20 — Deposits and withdrawals are never announced. As a Player, I should never see deposits or withdrawals announced, so that my banking stays private. (explicit)

  • Observable result: no deposit or withdrawal ever appears in the event ticker or the event list.
  • Failure/recovery: not applicable; this is an enforced exclusion in the announcement component.

FR-21 — Discord or Google accounts. As a Player, I should be able to use Discord or Google for my account, so that I do not have to create and remember a separate game password. (explicit)

  • Trigger/input: the player enters through Discord or chooses Google on the web entry.
  • Observable result: the provider identity is bound to a player account and the player's durable state is attached to it.
  • Failure/recovery: a failed provider sign-in returns the player to the entry surface with a retry.
  • Continuation: the player lands on their authenticated game overview.
Page 22 of 44

FR-22 — No separate login page from Discord. As a Player, I should be able to play from Discord without going to a separate login page, so that entry is frictionless. (explicit)

  • Trigger/input: the player opens the game from Discord's GUI.
  • Observable result: the game uses the logged-in Discord user's details directly for their account, with no login page shown.
  • Failure/recovery: if the identity handoff fails, the player is told the game could not be opened and can retry from Discord.
  • Continuation: the player lands on their authenticated game overview.

FR-23 — Provider identity establishes or returns the account. As a Player, I should have my Discord or Google identity establish my account on first use and return it on later use, so that my money and state persist across sessions and across both entry surfaces. (required_inference)

  • Trigger/input: a provider identity is presented.
  • Observable result: a matching account is returned, or a new account is created and bound to that provider identity (email-based).
  • Failure/recovery: an unresolvable identity returns the player to the entry surface with a retry.
  • Continuation: the player's balances, timers, jail state, lottery entry and heist membership are the same regardless of which surface they entered from.

FR-24 — Durable game state. As a Player, I should have my balances, timers, jail state, lottery participation, blackjack outcomes, heist membership and event records persist, so that the game is continuous and shared. (required_inference)

  • Observable result: state survives reloads and is consistent between the Discord and browser entries.
  • Failure/recovery: a failed state read shows a retry and preserves the last known values.
Page 23 of 44

FR-25 — Background automation of timed mechanics. As a Player, I should have the hourly work window, the 24-hour lottery draw, jail release and escape timing, and heist resolution resolved automatically, so that the game runs without me or anyone else triggering them. (required_inference)

  • Observable result: work counters restart, the lottery draws every 24 hours, jail sentences expire, escape gates re-open every 30 minutes, and heists resolve.
  • Failure/recovery: a missed resolution is retried so that no player loses a payout or stays jailed past their sentence.

4. User Personas

Page 24 of 44

Player

Product context. The Player is the core human actor of multiplayer-game-discord. They arrive either from inside Discord — where the game opens using their already-logged-in Discord identity and no login page — or from a web browser, where they establish identity with Discord or Google. They are Discord-native and comfortable reading dense, flat, dark interfaces; they expect numbers, timers and odds to be legible at a glance.

Primary goal. Accumulate and protect cash: earn it hourly, keep it safe in the bank, take it from others, gamble it, and return to normal play after jail.

Distinct accepted responsibilities. The Player works the hourly claim for a random $100–$300; enters the 24-hour lottery for a $500–$750 payout; robs other players' on-hand cash with a probability of success and a probability of being caught and jailed on failure; deposits and withdraws at the bank to protect cash; plays blackjack wagering on-hand cash; and, while jailed, waits out a 1–2 hour sentence and attempts escape every 30 minutes.

Relevant inputs and decisions. How much to keep on hand versus banked; which target to rob and whether the success probability justifies the jail risk; whether to enter the current lottery round; how much to wager at blackjack; whether to attempt an escape now or wait for the next 30-minute gate.

Interactions with other accepted participants. The Player's robbery directly changes another Player's on-hand cash, and that other Player sees the change in their balances and the announcement in the ticker. The Player also reads the shared event ticker, which carries other players' robberies, lottery wins and heist outcomes.

Page 25 of 44

Observable success. Balances update correctly and immediately; the work counter restarts after a claim; lottery entry is recorded and a win pays $500–$750; a successful robbery moves cash and is announced; a failed robbery may jail them; jail blocks work, robbery, lottery and other actions until release; deposits and withdrawals move money and are never announced.

Heist Teammate

Product context. The Heist Teammate is a Player acting in the distinct team-up workflow of a heist. This is a materially different activity from solo robbing: it requires assembling a group, carries a shared low success probability, and pays out a shared pool rather than a single target's cash.

Primary goal. Coordinate a team attempt on the bank and share the payout, while accepting the doubled jail risk if it fails.

Distinct accepted responsibilities. Forming or joining a team of up to four players; committing the team to the heist; accepting the low success percentage; accepting that on failure there is a percentage chance of jail for double the amount compared to robbing someone; and, on success, receiving an equal split of the value of all the players' banked money.

Relevant inputs and decisions. Who to team with, whether the roster is ready to commit, and whether the heist odds justify the doubled jail risk.

Interactions with other accepted participants. The Heist Teammate's outcome is bound to the other team members: the success or failure applies to the whole team, the jail risk applies to the whole team, and the payout is split between the players who robbed the bank. The result is announced to all Players through the event ticker.

Observable success. The roster shows up to four members; the commit is accepted or rejected at the four-member limit; on success each member's balances reflect their split and the heist is announced; on failure the jail chance resolves for members and the bust is announced.

Page 26 of 44

5. Core User Flows

Flow 1 — Entering the game from Discord (Player)

  1. The Player opens multiplayer-game-discord from Discord's new GUI.
  2. The game uses the logged-in Discord user's details directly for their account — no separate login page is shown.
  3. The Player's provider identity establishes their account on first use or returns their existing account (email-based).
  4. The Player lands on the Dashboard, where the player plate shows Cash, Bank and Net worth as ruled rows in tabular numerals.
  5. Failure/recovery: if the identity handoff fails, the Player is told the game could not be opened and can retry from Discord.
  6. Next step: the Player continues into any of the six numbered action tabs.

Flow 2 — Entering the game from a web browser (Player)

  1. The Player opens the web application and arrives on the Landing page, which explains the game and offers two entry paths.
  2. The Player chooses "Open in browser" and establishes identity with Discord or Google.
  3. The Player's provider identity establishes their account on first use or returns their existing account.
  4. The Player lands on the Dashboard with the same durable state they would have from Discord.
  5. Failure/recovery: a failed sign-in returns the Player to the Landing page with a retry.
  6. Next step: the Player continues into any of the six numbered action tabs.
Page 27 of 44

Flow 3 — Claiming the hourly work payout (Player)

  1. From the Dashboard, the Player opens the Work tab (01).
  2. The Work panel shows the claim button and the payout range of $100–$300.
  3. The Player claims the payout.
  4. A random amount between $100 and $300 is added to on-hand cash, the amount counts up in 400ms tabular steps, and the counter restarts from one hour.
  5. Failure/recovery: a failed claim grants no cash and leaves the counter unchanged; if the claim had already been taken server-side, the button shows the remaining time instead of paying twice.
  6. Next step: the Player returns to the Dashboard or continues to another activity; the countdown ticks down in place.

Flow 4 — Entering the 24-hour lottery (Player)

  1. From the Dashboard, the Player opens the Lottery tab (04).
  2. The Lottery panel shows the entry state, the countdown to the next draw, and the winner payout range of $500–$750.
  3. The Player enters the lottery by clicking or entering it.
  4. The entry is recorded for the current round and the button shows the entered state until the draw.
  5. When the round resolves, winners receive $500–$750 and the win is announced in the event ticker.
  6. Failure/recovery: a failed entry leaves the Player unentered with a retry; a duplicate entry for the same round is rejected without double-entering.
  7. Next step: the Player waits for the draw and continues with other activities.
Page 28 of 44

Flow 5 — Robbing another player (Player)

  1. From the Dashboard, the Player opens the Rob tab (02).
  2. The Rob panel lists other players with their on-hand cash and shows the robbery success probability as a line-art gauge with the exact percentage in tabular numerals.
  3. The Player selects a target and attempts the robbery.
  4. On success: the stolen cash moves from the target's on-hand cash to the robber's on-hand cash, both balances update, and the robbery is announced in the event ticker.
  5. On failure: no cash moves, and a separate probability may place the robber in jail for 1–2 hours; the jailing is announced.
  6. Failure/recovery: a failed request leaves both balances untouched and shows a retry; a target who no longer holds cash is removed from the list.
  7. Next step: the Player attempts again against the current target list, or — if jailed — moves to the Jail surface.

Flow 6 — Being robbed and seeing the announcement (Player, as the affected participant)

  1. Another Player attempts a robbery against this Player.
  2. On success, this Player's on-hand cash decreases by the stolen amount and the robber's on-hand cash increases by the same amount.
  3. This Player sees the change in their balances on the player plate and in the Dashboard status.
  4. The robbery appears in the event ticker with an amber timestamp and in the scrollable event list.
  5. Failure/recovery: if the robbery fails, no cash moves and this Player's balances are unchanged.
  6. Next step: this Player can bank remaining cash to protect it, or attempt a robbery of their own.
Page 29 of 44

Flow 7 — Depositing and withdrawing at the bank (Player)

  1. From the Dashboard, the Player opens the Bank tab (03).
  2. The Bank panel shows on-hand cash and banked cash as ruled label/value rows and an amount input.
  3. The Player enters an amount and chooses deposit or withdraw.
  4. The amount moves between on-hand cash and banked cash and both rows update.
  5. No announcement is produced — the deposit or withdrawal never appears in the event ticker or the event list.
  6. Failure/recovery: an amount exceeding the source balance is rejected without partial movement; a failed request leaves both balances untouched and shows a retry.
  7. Next step: the Player remains on the Bank surface with updated balances, or returns to the Dashboard.

Flow 8 — Playing blackjack (Player)

  1. From the Dashboard, the Player opens the Blackjack tab (05).
  2. The Blackjack panel shows the wager input and the hand readouts.
  3. The Player places a wager using on-hand cash and deals, then hits or stands.
  4. A won round adds the payout to on-hand cash and the result counts up in 400ms tabular steps; a lost round deducts the wager; a push returns the wager.
  5. Failure/recovery: a wager exceeding on-hand cash is rejected; a failed action leaves on-hand cash untouched and shows a retry.
  6. Next step: the Player starts a new round or returns to the Dashboard.
Page 30 of 44

Flow 9 — Being jailed and attempting escape (Player)

  1. The Player is jailed — either by being caught by police on a failed robbery, or by the heist failure jail chance.
  2. The Jail surface replaces the action grid with one oversized tabular countdown at clamp(40px, 9vw, 76px) showing the remaining 1–2 hour sentence, plus a single "Attempt escape" button whose disabled state shows the 30-minute gate. The player plate's rule colour flips to signal orange.
  3. While jailed, the Player cannot work, rob others, enter the lottery, play blackjack, or join or commit a heist.
  4. Every 30 minutes the escape gate opens and the Player may attempt an escape.
  5. On success: the sentence ends early, the Player returns to normal play, and the release is announced.
  6. On failure: the sentence continues and the 30-minute gate re-arms.
  7. Failure/recovery: a failed escape request leaves the gate unchanged and can be retried once the gate re-opens.
  8. Next step: when the sentence reaches zero the Player is released automatically and normal actions become available again.

Flow 10 — Forming a heist team (Heist Teammate)

  1. From the Dashboard, the Player opens the Heist tab (06).
  2. The Heist panel shows the team roster with open slots, the heist success probability as a line-art gauge, and the doubled jail risk on failure.
  3. The Player forms a team, and other Players join, up to four members.
  4. The roster shows the members and the commit button becomes available once the team is ready.
  5. Failure/recovery: a team exceeding four members is rejected; a member may leave before commitment.
  6. Next step: the team commits the heist, or disbands.
Page 31 of 44

Flow 11 — Committing the heist and sharing the outcome (Heist Teammate)

  1. The team commits the heist from the Heist surface.
  2. On success: the bank is robbed, the value of all the players' banked money is taken and split between the players who robbed the bank, each member's balances update, and the heist is announced in the event ticker.
  3. On failure: the heist fails and a percentage chance places members in jail for double the amount compared to robbing someone; the bust is announced.
  4. Each Heist Teammate sees their own resulting state — their split on success, or their jail sentence on failure — on their own player plate and Jail surface.
  5. Failure/recovery: a failed commit leaves team state and balances untouched and shows a retry.
  6. Next step: members continue from their resulting state — normal play after a successful split, or the Jail surface after a bust.
Page 32 of 44

Flow 12 — Reading the event announcements (Player)

  1. From any authenticated surface, the Player sees the single-line event ticker moving one row per new event, with amber timestamps separated by 1px vertical rules.
  2. The Player opens the Events surface to read the same events as a scrollable list, newest first.
  3. Announced events include robberies, lottery wins, heist outcomes, jailings and escapes.
  4. Deposits and withdrawals never appear in the ticker or the list.
  5. Failure/recovery: a failed event read shows a retry and keeps the last known events.
  6. Reduced motion: the ticker becomes a static, scrollable list in which every item can be brought fully into view.
  7. Next step: the Player returns to whatever activity they were pursuing.
Page 33 of 44

6. Visuals, Colors and Theme

Muse and headline. Dieter Rams — Less, but better: a Braun-panel crime economy you can read at a glance. The product must feel like an honest instrument: every number, timer and probability legible in one glance, nothing decorative competing with the ledger.

Palette (dark mode).

RoleHexUse
Background#1C1B18Warm graphite ground
Surface#26241FPanel surfaces, one step up from ground
Rule#3A372F1px hairline rules — the dominant graphic element
Text#F2EFE6Warm off-white body and headings
Primary#E8551FSignal orange — the ONLY action colour
Accent#E3B23CAmber — money numerals, lottery/odds readouts, ticker timestamps
Muted#8C887CSecondary labels and disabled states

Proportion: 80% neutral ground/surfaces, 15% text, 5% signal. Signal orange is reserved for actions (Work, Rob, Heist, Blackjack deal buttons, the jail countdown, the active-tab underline). Amber is reserved for money numerals, lottery/odds readouts and event ticker timestamps — never for a button. Orange and amber never appear on the same button.

Page 34 of 44

Typography. Headings: Archivo in 600/700, uppercase, letter-spacing 0.02em, tight leading (0.95) for the oversized hero and section titles. Label text: 11–12px uppercase Archivo 600 with 0.12em tracking, exactly like a Braun control panel silkscreen. Body: Archivo. Numerals always tabular (font-variant-numeric: tabular-nums) so balances, timers and odds align in columns. No display serif, no rounded face, no italic.

Type scale. 1.25 modular on a 4px baseline: 11 / 12 / 14 / 16 / 20 / 25 / 31 / 39 / 49 / 61 / 76. Hero display uses clamp(40px, 9vw, 76px) mobile→desktop; page titles clamp(25px, 4.5vw, 39px); body 16px/1.5; data rows 14px; labels 11px.

Shape language. Functional geometry only: 4px and 8px radii on buttons and panels (never pills, never blobs); 1px hairline rules as the dominant graphic element; square corners on data tables and the ticker. Controls are rectangles with a visible 1px border and a 2px inner highlight on press; every affordance looks like a switch you could physically flip. No shadows except a 0 1px 0 rgba(0,0,0,.4) seat under sticky bars; no gradients, no glass, no glow.

Layout. A fixed 12-column modular grid at 1280px (max-width 1120px, 32px gutters), collapsing to a single column at 375px with 16px gutters. Persistent left rail (240px) holds the player plate — avatar initial, handle, Cash / Bank / Net worth in three ruled rows with tabular numerals — plus the six action tabs (Work, Rob, Bank, Lottery, Blackjack, Heist) as a numbered vertical list 01–06. The main panel is a ruled ledger: label/value pairs aligned on a shared right edge, section headers with a full-width hairline and a small caps label, actions pinned to the bottom-right of each panel in a consistent 44px-tall button bar. On mobile the rail becomes a sticky top plate (balances in one 3-column row) with the action tabs as a horizontal scroll-snap strip of numbered chips. Every panel is the same width and rhythm; the grid never breaks, only the column count changes.

Page 35 of 44

Imagery. No illustration, no photography, no characters, no icons beyond a 16px geometric glyph set drawn on the 4px grid (a clock, a dial, a lock, a card, a coin as a plain circle). The visual content is the data itself: ruled tables, probability readouts, timers, and the event ticker. Where a diagram is needed (heist success odds, blackjack table) it is drawn as line art in 1px strokes with the accent used only on the live value.

7. Signature Design Concept

The public entry is a full-width instrument panel, not a marketing block.

Left — 7 columns. An oversized two-line headline in Archivo 700 uppercase at clamp(40px, 9vw, 76px) — "GET RICH / GET LOCKED UP" — set flush-left on the graphite ground, with the game's one-line rule set beneath it at 16px and two 44px rectangular buttons sitting under a hairline rule: signal-orange "Play in Discord" and outlined "Open in browser".

Right — 5 columns. A live "state of the city" plate: a bordered surface panel with four ruled rows — Cash in circulation, Players in jail, Next lottery, Heist success % — in tabular amber numerals, updating as a mock feed. Beneath it, the event ticker as a single-line marquee of timestamped events separated by 1px vertical rules.

Composition rules. No centred headline, no gradient, no blob: the composition is an asymmetric two-panel instrument with a hard vertical rule between them. The concept recomposes only accepted content, states and controls — the two accepted entry paths, the public aggregate readouts, and the event ticker — and introduces no new behaviour, page or destination.

Page 36 of 44

8. Interaction Model & Motion Direction

Interaction Model: Static Motion Tempo: restrained Hero Dimensionality: flat

Landing Hero Motion Brief.

  • Focal subject: the asymmetric two-panel instrument — the oversized "GET RICH / GET LOCKED UP" headline on the left and the bordered "state of the city" plate with its four ruled amber rows on the right.
  • Input → transformation → outcome thesis: as public aggregates and events arrive, the plate's four ruled rows update in place and the ticker advances one row per new event; the outcome is a live instrument reading of the city's state, with the two entry buttons unchanged and always available.
  • Motion vocabulary: mechanical and instant — state changes at 120ms linear, no bounce, no easing theatrics. One purposeful loop only: the countdown numerals tick down in place and the event ticker slides one row per new event. Press feedback is a 1px translate plus a border colour flip to signal orange. Numbers count up on claim (Work payout, lottery win, blackjack result) in 400ms steps of tabular digits.
  • Composed first frame: graphite ground #1C1B18; flush-left two-line headline in warm off-white #F2EFE6; a hairline rule #3A372F beneath it; the signal-orange #E8551F "Play in Discord" button and the outlined "Open in browser" button side by side; a hard vertical rule; the bordered surface panel #26241F with four ruled label/value rows in amber #E3B23C tabular numerals; the single-line ticker beneath with amber timestamps separated by 1px vertical rules.
  • Reduced-motion state: counts snap to final values and the ticker becomes a static, scrollable list in which every item can be brought fully into view.
Page 37 of 44

9. Non-Functional Requirements

NFR-1 — Flat, un-graphical presentation. The interface must be flat with only text and buttons and nothing too graphical. (explicit)

  • Rationale: the user explicitly asked for a simple, flat, text-and-button game.

NFR-2 — Legibility at every viewport. Headlines, wordmarks, labels, numbers and controls must stay entirely inside the viewport and their container at 375px, 768px and 1280px, wrapping or scaling (for example font-size: clamp(...) with its mobile size) to fit, with no other element covering any part of them. (explicit, from the creative direction's readability rule)

  • Rationale: the game's value is reading numbers and timers at a glance; clipped or covered data defeats the product.

NFR-3 — Tabular numerals everywhere numbers appear. Balances, timers, odds and payouts must use tabular numerals so they align in columns. (explicit, from the creative direction)

  • Rationale: the ledger is the interface; misaligned digits make it unreadable.

NFR-4 — Durable, shared state. Player balances, timers, jail state, lottery participation, blackjack outcomes, heist membership and event records must persist and be consistent between the Discord and browser entries. (required_inference)

  • Rationale: the game is multiplayer and continuous; state must survive reloads and be shared across players.
Page 38 of 44

NFR-5 — Timed mechanics resolve automatically. The hourly work window, the 24-hour lottery draw, jail release and escape timing, and heist resolution must resolve without a player or operator triggering them. (required_inference)

  • Rationale: the accepted mechanics are time-based and must not depend on anyone being online.

NFR-6 — Announcement privacy rule. Deposits and withdrawals must never be announced, enforced as a rule in the announcement component rather than by convention. (explicit)

  • Rationale: the user explicitly excluded banking from announcements.

NFR-7 — No separate login page from Discord. Playing from Discord must not require a separate login page. (explicit)

  • Rationale: the user explicitly required frictionless Discord entry.

NFR-8 — Reduced-motion support. With prefers-reduced-motion, counts snap to final values and the ticker becomes a static, scrollable list in which every item can be brought fully into view. (explicit, from the creative direction)

  • Rationale: accessibility for players who cannot tolerate motion.
Page 39 of 44

10. Tech Stack

  • Front end: React. (explicit — user-stated)
  • Backend: Node. (explicit — user-stated)
  • Database: MongoDB. (explicit — user-stated)
  • Discord integration: Discord's new GUI as a provider-owned entry surface that passes the logged-in Discord user's identity into the game without a separate login page. (explicit — user-stated)
  • Authentication providers: Discord and Google, bound to an email-based player account. (explicit — user-stated)
  • Background automation: a scheduled/background process for the hourly work window, the 24-hour lottery draw, jail release and escape timing, and heist resolution. (required_inference)
  • Containerization: Docker / docker-compose for the front end, backend and database. (Default — not specified by user)
Page 40 of 44

11. Assumptions and Constraints

Constraints (binding).

  • The UI must be flat with only text and buttons; nothing too graphical. (explicit)
  • Jailed players cannot work, rob others, enter the lottery, or take other actions until their 1–2 hours are up. (explicit)
  • Escape attempts are limited to every 30 minutes while jailed. (explicit)
  • Work payout is claimable once per hour and the counter restarts after claiming. (explicit)
  • The lottery runs every 24 hours. (explicit)
  • Heist teams are limited to up to 4 players. (explicit)
  • The heist has a low success percentage, and failure carries a percentage chance of jail for double the amount compared to robbing someone. (explicit)
  • Deposits and withdrawals must not be announced. (explicit)
  • Playing from Discord must not require a separate login page. (explicit)
Page 41 of 44

Assumptions (narrow, labeled).

  • The exact robbery success probability, the exact police-catch probability, the exact heist success percentage, and the exact heist-failure jail percentage are not specified by the user; they are tunable game-balance values and are not fixed by this document. (assumption)
  • The exact jail sentence within the stated 1–2 hour range is determined per event by the game; the range is the binding constraint. (assumption)
  • "Cash can be used to buy items" is recorded as a property of on-hand cash; no item catalogue, shop surface or item list is specified, so no item-purchasing surface is created. (assumption)
  • The player account is email-based, derived from the Discord or Google provider identity. (explicit — user-stated)
  • The event ticker is a single-line moving row; deposits and withdrawals are excluded from it by rule. (explicit — from the creative direction)
Page 42 of 44

12. Glossary

  • On-hand cash — the money a player currently holds, which can be stolen by other players, wagered at blackjack, deposited into the bank, and used to buy items.
  • Banked cash — money deposited in the bank, kept safe from robbery, and withdrawable back to on-hand cash.
  • Net worth — the combined value of a player's on-hand cash and banked cash, shown on the player plate.
  • Work — the hourly claim that grants a random $100–$300 and restarts a one-hour counter.
  • Lottery — the 24-hour draw that players enter by clicking or entering it, paying winners $500–$750.
  • Rob — the attempt to take another player's on-hand cash, resolved with a success probability and, on failure, a probability of being caught by police and jailed.
  • Jail — the lockout state a player enters when caught, lasting 1–2 hours, during which work, robbery, lottery and other actions are unavailable; escape may be attempted every 30 minutes.
  • Escape gate — the 30-minute interval that must pass before a jailed player may attempt another escape.
  • Heist — the team activity in which up to four players rob a bank, with a low success percentage, a doubled jail risk on failure, and an equal split of the robbed banked money on success.
  • Heist Teammate — a player acting in the heist team-up workflow, sharing the team's outcome and payout.
  • Event ticker — the single-line moving announcement row carrying timestamped events such as robberies, lottery wins and heist outcomes; deposits and withdrawals never appear in it.
Page 43 of 44
  • Player plate — the persistent balance readout showing Cash, Bank and Net worth as ruled label/value rows in tabular numerals, present on every authenticated screen.
  • Probability gauge — the line-art readout drawn as a 1px horizontal rule with a filled signal-orange segment and the exact percentage in tabular numerals, used wherever a chance exists (rob success, escape chance, heist odds).
Page 44 of 44
Landing design preview
Landing: View landing page
Landing: Sign in via Discord or Google
Dashboard: 1. View overview
Heist: 2. Join team
Heist: 3. View roster status
Heist: 4. Leave team before commit
Heist: 5. Commit heist
Heist: 6. View success split
Jail: 7. View doubled sentence
Jail: 8. Attempt escape
Jail: 9. Escape succeeds
Jail: 10. Escape fails
Events: 11. View heist announcement
Landing design preview
Landing: View landing page
Landing: Sign in via Discord or Google
Dashboard: 1. View overview
Heist: 2. Join team
Heist: 3. View roster status
Heist: 4. Leave team before commit
Heist: 5. Commit heist
Heist: 6. View success split
Jail: 7. View doubled sentence
Jail: 8. Attempt escape
Jail: 9. Escape succeeds
Jail: 10. Escape fails
Events: 11. View heist announcement