myboker.org
Flask app for running home-poker leagues without keeping a spreadsheet open all night.
The current app is account-based and league-based. League owners/managers record sessions and ledger events, viewers can inspect public-facing league data, and site-admin access is reserved for internal tooling.
What It Does
- account signup, login, and email verification
- league creation, invitations, ownership transfer, and member roles
- player, season, session, and ledger management per league
- append-only ledger events with void/correction support
- public/private league visibility
- leaderboards, charts, dashboard stats, and session summaries
- CSV import/export for league ledgers
Stack
- Python
- Flask
- SQLAlchemy / Flask-Migrate
- Jinja templates
- Chart.js
- plain CSS
Project Layout
app.pyis the deployment entrypoint forflask --app appand Gunicorn.boker/contains the Flask application package, routes, models, services, repositories, and config.templates/andstatic/contain Jinja views and public assets.migrations/contains Alembic migrations for database deploys.tests/contains the committed regression suite.
Ledger Model
Each ledger row is an event, not a final snapshot. Corrections are made by appending or voiding events, so the history remains auditable.
Current event types:
buyinfrontdebt_repaymentwriteoffcashoutpaid_outrollover_inpayout_carry_inrollover_outnotesession_opensession_close
Accounting keeps poker results separate from banker cashflow:
- poker investment is
buyin + front + rollover_in - poker net is
cashout - poker investment - real cash in is
buyin + debt_repayment - real cash out is
paid_out rollover_outsettles the source session without counting as cash outrollover_inenters play in the destination session without counting as cash inpayout_carry_inrecords prior-session value carried into a later payout without counting as poker investment or cash inwriteoffresolves a receivable without counting as cash in
Older imports may still contain paid, front_collected, or front_writeoff; those are read as aliases for paid_out, debt_repayment, and writeoff.
Running Locally
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python app.py
Then open:
http://127.0.0.1:5000
Environment Values
The app reads these from .env. Use .env.example for local development and .env.production.example as the production checklist.
SECRET_KEYAPP_ENVDATABASE_URLAPP_BASE_URLRATELIMIT_STORAGE_URIMAIL_SERVERMAIL_PORTMAIL_USE_TLSMAIL_USE_SSLMAIL_USERNAMEMAIL_PASSWORDMAIL_DEFAULT_SENDER
For local development, omit DATABASE_URL to use the default SQLite database at data/boker-dev.sqlite3.
For public deployments, set APP_ENV=production. Production mode enables secure cookies and refuses to start with the development SECRET_KEY or any SQLite database. Use PostgreSQL for DATABASE_URL, install dependencies from requirements.txt, then run:
flask --app app db upgrade
Set RATELIMIT_STORAGE_URI to a shared backend such as Redis so login and signup limits are enforced across processes.
Site Admin Access
Internal admin access uses normal database-backed accounts, not hardcoded .env credentials.
Grant access:
flask --app app grant-site-admin user@example.com
Revoke access:
flask --app app revoke-site-admin user@example.com
The old single-password /admin system has been removed.