Easy-to-manage touch screens
Free, open-source touch screens. Guided USB setup, a drag-and-drop editor and local control. Made for Home Assistant.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
Loading the full README. The saved excerpt is shown below.
Poker With Friends · פוקר עם חברים A private poker-night manager for groups of friends. It does not deal cards — people play a real, physical game around a real table. The app handles the money: buy-ins, chips issued, the clock, the final chip count, profit and loss, and who owes whom at the end of the night. The interface is Hebrew-first and RTL, designed for a phone in one hand. Setup: see docs/SETUP.md for the Supabase and Vercel configuration. Nothing in this repository needs editing to get running.Read the full README ↗
A private poker-night manager for groups of friends. It does not deal cards — people play a real, physical game around a real table. The app handles the money: buy-ins, chips issued, the clock, the final chip count, profit and loss, and who owes whom at the end of the night.
The interface is Hebrew-first and RTL, designed for a phone in one hand.
Setup: see
docs/SETUP.mdfor the Supabase and Vercel configuration. Nothing in this repository needs editing to get running.
| Open a table | Buy-in amount, chips per buy-in, max entries, start and end time, join mode, visibility, counting mode. Defaults: 50₪ = 500 chips, 6 entries max. |
| Invite | A 5-character join code (A7K92) with a share link and native share sheet. The code never grants admin rights. |
| Join | Registered users, or guests with no account at all. |
| Play | Live dashboard: players, entries, pot, chips on the table, countdown. Players request another entry; the admin approves or rejects. |
| Count | Admin counting or self-counting, with chip-discrepancy detection before anything is finalised. |
| Settle | Profit/loss per player and the minimal set of transfers: "דניאל מעביר לאילן 80₪". |
| Remember | History, statistics, records, profit charts and per-group leaderboards. |
| Compare | An opt-in global leaderboard of registered players, ranked on realised profit from finished games only. |
| Tidy up | A table that never started can be deleted by its owner. |
| Leave early | A player can cash out mid-game: they declare their chips, their result is settled by the same accounting as everyone else, and the game carries on. |
src/
app/ routes (App Router, all screens Hebrew/RTL)
table/[id]/ live dashboard, counting, results, leaderboard
join/[code]/ guest and member joining
profile/ overview · history · stats · tables · settings
components/
ui/ design-system primitives (RTL-aware)
table/ join/ profile/ charts/ layout/
lib/
domain/ pure, unit-tested business logic
actions/ server actions — the only write path
data/ server-side read models
supabase/ browser · server · service-role · middleware clients
supabase/migrations/ schema, functions, RLS, realtime, storage
tests/ Vitest suites over the domain layer
Every mutation goes through a Server Action → SECURITY DEFINER Postgres
function. Those functions derive the actor from auth.uid() themselves and
take row locks before they read totals, so the rules hold under concurrency and
cannot be bypassed by a crafted request. The TypeScript in
src/lib/domain/permissions.ts mirrors the same rules purely so the UI can hide
controls that would fail — if the two ever disagree, the database wins.
The source of truth for seated-versus-left is table_players.left_at — null
while seated, a timestamp once the leave flow completed. Nothing else decides
it: not a chip submission, not an approved count, not a status value. The
predicates in src/lib/domain/participation.ts treat anything that is not a
real timestamp as seated, so a missing column can never mark a playing
participant as having left.
A player who cashes out keeps status = 'ACTIVE' and gains a left_at
timestamp. That is deliberate: their buy-ins are in the pot and their issued
chips came off the rack, so they are still a participant in that game.
compute_final_rows, the chip-conservation check and finalize_game all select
status = 'ACTIVE' and are therefore untouched — the leaver's profit and loss is
computed by exactly the same code as everyone else's. There is no second
accounting path. What left_at changes is only the right to keep playing: no
further buy-ins and no rebuy requests.
buyin_transactions is an append-only ledger. A mistaken entry is
corrected with a REVERSAL row, never by editing history.total_paid, chips_issued, buy_in_count) are derived by a view
over that ledger. There is no client-written counter anywhere.finalize_game recomputes the results itself and rejects any settlement
plan that does not exactly resolve every balance.request_id is covered by a unique index. A double-tap, or two admins tapping
at once, cannot produce two buy-ins.reverses_transaction_id, so a buy-in can be reversed
at most once.A visitor who joins with a code is given a Supabase anonymous session, minted
server-side, stored in httpOnly cookies. That means a guest holds a real
signed JWT and a real auth.uid(), so:
This is the beginning of the README. Read the rest at the original. Read the full README ↗