Files
tavolo/README.md
T
woggioni 12fa3f5aae
CI / Build and push docker image (push) Failing after 39s
Rebuild the web UI on Bootstrap 5 with the dark felt theme
The lobby was hand-rolled CSS and looked plain. Vendor Bootstrap 5.3
(MIT) under web/vendor so builds stay offline, load it in dark mode and
bridge the felt/gold palette onto Bootstrap's CSS variables in a new
theme.css; style.css now only owns the game table, cards and scoring
summary.

Rebuild the lobby, waiting room and shared chrome with Bootstrap
components: a shared navbar, creation form as cards with schema-driven
controls, roster as a list group with seat/team badges, a seats progress
bar and a copy-to-clipboard button on the join code. History,
leaderboard, connection/error states and the 404 page use cards, tables
and buttons too; the play table itself is unchanged.

The copy feedback timer is cancelled when the waiting room is rebuilt by
another player joining, fixing a disposed-signal panic that froze the
page mid-match.
2026-09-21 23:40:44 +08:00

87 lines
3.2 KiB
Markdown

# tavolo
A platform for multiplayer card games. The first game is **scopone
scientifico** — the four-player, fixed-partnership Italian card game:
- **`server/`** — backend: Python + [kaya](https://github.com/woggioni/kaya)
framework, OIDC login, live games in Redis, match statistics in Postgres.
A monorepo of three distributions sharing the `tavolo` namespace: the
game-independent `tavolo-platform`, the scopone game `tavolo-scopone`,
and the `tavolo-app` composition root wiring them together.
See [server/README.md](server/README.md).
- **`web/`** — frontend: Rust + [Sycamore](https://sycamore.dev) compiled to
WebAssembly, built with [Trunk](https://trunkrs.dev) and styled with
[Bootstrap](https://getbootstrap.com) 5.3 (MIT, vendored under
`web/vendor/` so builds work offline) plus the custom felt theme in
`web/theme.css`. Card images are the
CC0 *woodcut napoletane* deck traced from a 1902 Naples print
([SONDLecT/woodcut-napoletane](https://github.com/SONDLecT/woodcut-napoletane)).
## Run the whole stack
```sh
docker compose up --build
```
Postgres, Redis, a mock OIDC provider (test users `alice`, `bob`, `carol`,
`dave`), the database migrator and the app all come up together. The app —
frontend and API — listens on `http://127.0.0.1:8080`.
Because both the browser and the app talk to the OIDC issuer at
`http://mockoauth:8180/tavolo`, add a host entry once:
```sh
echo "127.0.0.1 mockoauth" | sudo tee -a /etc/hosts
```
## Between hands
When a hand ends but the match is not decided, the game pauses on a
**scoring summary screen**: every player sees how each category was won
(carte, denara, settebello, primiera, scope — plus napola when enabled)
with the running totals and
must click "Understood" before the next hand is dealt. If someone is away
the next hand is dealt automatically after `HAND_ACK_TIMEOUT_SECONDS`
(default 30s). The match-ending hand is explained on the final screen.
## On your turn
Every turn shows a countdown (`TURN_TIMEOUT_SECONDS`, default 30s). If a
player does not move — disconnected or fallen asleep — the server plays a
random legal card for them (randomizing among the legal captures when the
rules require a capture), so one absent player cannot stall the table.
## Development
Backend (from `server/`):
```sh
cd server
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pip install -e ./packages/tavolo-platform -e ./packages/tavolo-scopone -e './packages/tavolo-app[dev]'
.venv/bin/python -m unittest discover -s tests -t .
.venv/bin/python -m unittest discover -s packages/tavolo-platform/tests
.venv/bin/python -m unittest discover -s packages/tavolo-scopone/tests
```
Frontend (from `web/`), with the backend running on :8080:
```sh
cd web
trunk serve # SPA on http://localhost:8000, /api /auth /ws proxied
```
Trunk proxies `/api`, `/auth` and `/ws` to `127.0.0.1:8080` (see
`web/Trunk.toml`). For the login redirect to land back on the dev server,
run the backend with:
```sh
OIDC_POST_LOGIN_REDIRECT=http://localhost:8000/ \
OIDC_POST_LOGOUT_REDIRECT=http://localhost:8000/ \
.venv/bin/granian --host 127.0.0.1 --port 8080 tavolo.app:app
```
Card images are committed under `web/assets/cards/`; `web/fetch-cards.sh`
re-downloads them if needed.