project-twitch-2k-wager updated 2026-04-12PlayMe2K
Vision
A peer-to-peer wager platform built for Twitch streams. Any player can challenge any other player — propose a bet, negotiate the terms, and play for real money. The drama IS the product: "my $20 to your $10" proposed live on stream, Marcus deciding whether to take it, chat losing their minds.
Marcus is Player 1, not an admin. The same interface, the same flow, the same energy — whether Marcus is challenging a viewer or a viewer is challenging Marcus. The architecture is player-to-player from day one, enabling friends to bet against each other on the same platform.
Core principles:
- Peer-to-peer, not admin-customer. No special roles. Everyone is a player with a pool, proposals, and games. Marcus happens to be the streamer — the system doesn't care.
- Pool model for instant bets. Players deposit once via Stripe, then bet freely from their pool. Proposals lock funds instantly — no Stripe redirect per game. Withdraw whenever.
- The proposal IS the content. "My $50 to your $10" is trash talk in dollar form. Accept, counter, decline — every interaction is a stream moment. The negotiation is as entertaining as the game.
- Bidirectional proposals. Marcus challenges viewers. Viewers challenge Marcus. Eventually viewers challenge each other. Same flow, same UI, same language.
User Stories
| Key | Role | Success Metric |
|---|---|---|
| player-pool | Any Player | Deposit once, bet instantly from pool. No Stripe redirect per game. |
| player-propose | Any Player | "My $X to your $Y" sent in under 5 seconds. Proposal visible to both sides immediately. |
| player-decide | Challenged Player | Accept, counter, or decline within the stream moment. Funds lock on accept. |
| game-result | Any Player | Result declared, pot moves to winner's pool instantly. Email notification sent. |
| player-withdraw | Any Player | Withdraw pool balance to bank via Stripe payout anytime. |
| observability | Operator | MTTR under 5 minutes during stream hours. |
Architecture
Data model (evolved):
Player Pool:
player_id → Keycloak user (Twitch OAuth)
balance → available to bet (cents)
locked → committed to active proposals/games (cents)
Proposal:
from_player_id → proposer
to_player_id → challenged player
my_amount → proposer's stake
your_amount → challenged player's stake
status → pending / accepted / countered / declined / expired
Game:
proposal_id → accepted proposal
player_1_id → from original proposal
player_2_id ��� from original proposal
pot_amount → my_amount + your_amount
result → player_1_win / player_2_win / null
Deposit: Stripe Checkout → adds to balance
Propose: locks my_amount from proposer's balance
Accept: locks your_amount from accepter's balance → creates Game
Counter: unlocks original, creates new proposal with different terms
Decline: unlocks proposer's amount, no game
Result: winner's balance += pot, both locked amounts cleared
Withdraw: Stripe payout from balance → player's bank
Key decisions: SvelteKit with server routes (adapter-node). Keycloak brokers Twitch OAuth. Postgres on shared CNPG cluster. Service key = playme2k. Pool model — one Stripe deposit, instant in-database bets. Standard Stripe payouts for withdrawals (2-3 business days).
Routes
Critical routes for validation. Every route must return HTTP 200 during post-merge validation.
| Route | Who | What it does |
|---|---|---|
/ |
Everyone | Landing page — pitch, how it works |
/play |
Authenticated players | Dashboard — pool balance, proposals (sent + received), active games, results |
/deposit |
Authenticated players | Add funds to pool via Stripe Checkout |
/terms |
Everyone | How it works, payout details, FAQ |
Board
Status
2026-04-05: MVP live (fixed tiers, pay-per-game, admin/challenger split). Vision evolved to peer-to-peer pool model. 26 items done. Next: proposal flow + pool model (#66), win/lose emails (#60). ArgoCD namespace fix merged (#95). Gmail OAuth configured (playme2kbet@gmail.com).
Milestones
- MVP (done): Fixed tiers, Stripe Checkout per game, admin queue, result declaration, payouts
- v2 (next): Pool model, bidirectional proposals ("my X to your Y"), unified player interface
- v3 (future): Player-to-player (viewers challenge each other), counter-offers, public proposal feed
Repos
| Repo | Platform | Role | Status |
|---|---|---|---|
| forgejo_admin/twitch-2k-wager | Forgejo | SvelteKit app + server routes | Live in production |
| forgejo_admin/pal-e-services | Forgejo | Terraform: Keycloak, funnel, CNPG | Applied |
| forgejo_admin/pal-e-deployments | Forgejo | Kustomize overlay (overlays/twitch-2k-wager/) | Live |