No description
  • TypeScript 71.6%
  • CSS 24.9%
  • JavaScript 2.5%
  • Dockerfile 0.8%
  • Shell 0.2%
Find a file
Kira f48e576ca3
Some checks failed
CI / lint-and-unit (push) Has been cancelled
CI / e2e (push) Has been cancelled
add files
2026-05-21 00:48:46 +02:00
.cursor add files 2026-05-21 00:48:46 +02:00
.github/workflows add files 2026-05-21 00:48:46 +02:00
.vscode add files 2026-05-21 00:48:46 +02:00
docker add files 2026-05-21 00:48:46 +02:00
prisma add files 2026-05-21 00:48:46 +02:00
public add files 2026-05-21 00:48:46 +02:00
scripts add files 2026-05-21 00:48:46 +02:00
src add files 2026-05-21 00:48:46 +02:00
tests add files 2026-05-21 00:48:46 +02:00
.dockerignore add files 2026-05-21 00:48:46 +02:00
.env.example add files 2026-05-21 00:48:46 +02:00
.gitignore add files 2026-05-21 00:48:46 +02:00
AGENTS.md add files 2026-05-21 00:48:46 +02:00
CLAUDE.md add files 2026-05-21 00:48:46 +02:00
docker-compose.yml add files 2026-05-21 00:48:46 +02:00
Dockerfile add files 2026-05-21 00:48:46 +02:00
eslint.config.mjs add files 2026-05-21 00:48:46 +02:00
next.config.ts add files 2026-05-21 00:48:46 +02:00
package-lock.json add files 2026-05-21 00:48:46 +02:00
package.json add files 2026-05-21 00:48:46 +02:00
playwright.config.ts add files 2026-05-21 00:48:46 +02:00
postcss.config.mjs add files 2026-05-21 00:48:46 +02:00
README.md first commit 2026-05-21 00:47:51 +02:00
tsconfig.json add files 2026-05-21 00:48:46 +02:00
vitest-env.d.ts add files 2026-05-21 00:48:46 +02:00
vitest.config.ts add files 2026-05-21 00:48:46 +02:00

Piccolus

A small party game for your phone: pick a deck, add the players, pass the phone around. Cards can include $P / $P1, $P2, … placeholders that get filled in with a random player on every draw.

You can also create your own categories, decks, and cards from the built-in admin UI.

Run it with Docker

The easiest way to host Piccolus is with Docker Compose. You only need Docker (with the Compose plugin) installed.

# 1. Get the code
git clone <repo-url> piccolus
cd piccolus

# 2. Configure two secrets
cp .env.example .env
# then edit .env and set:
#   ADMIN_PASSWORD=<your admin password>
#   AUTH_SECRET=<at least 32 random characters>
# Tip: openssl rand -base64 32

# 3. Start it
docker compose up -d --build

Open http://localhost:3000.

The admin UI is at http://localhost:3000/admin. Log in with the password from ADMIN_PASSWORD.

A fresh install starts with an empty database. The home screen detects the empty state and shows a single "Open admin" button so new operators know exactly where to go. Sign in with the password from ADMIN_PASSWORD and create your first categories, decks, and cards.

The example seed (prisma/seed.ts) is a dev/E2E-only helper and is not shipped in the Docker image, so production deployments can never be accidentally populated with demo content.

Updating

git pull
docker compose up -d --build

The database schema is applied automatically on startup. Your data and uploaded card images are kept in Docker named volumes (db and uploads) and survive rebuilds.

Backups

Both the database and the uploaded images live on volumes:

# back up everything
docker run --rm \
  -v piccolus_db:/db -v piccolus_uploads:/uploads \
  -v "$PWD":/out alpine \
  tar -C / -czf /out/piccolus-backup.tgz db uploads

Restore by extracting the archive back into the same volumes.

Configuration

Set these in .env:

Variable Required Notes
ADMIN_PASSWORD yes Password for /admin/login. Pick a strong one.
AUTH_SECRET yes Secret used to sign the admin session cookie. Use at least 32 random characters.
PORT no Host port to expose the app on. Defaults to 3000.

Reverse proxy / TLS

Piccolus listens on plain HTTP inside the container. Put it behind a reverse proxy (Caddy, Traefik, nginx, etc.) to terminate TLS. A Strict-Transport-Security header is set automatically when the app sees NODE_ENV=production (which the Docker image does).

Using the app

Hosting a game

  1. Open the home page on the phone you'll pass around.
  2. Pick a category, then a deck. (Or pick Everything to draw from every deck.)
  3. Type in the player names (at least two). Add more with Add.
  4. Hit Start. Each card may contain $P, which is replaced with a randomly chosen player for that draw. Use $P1, $P2, … when the same player must appear more than once — the same number always refers to the same person.
  5. Tap Next to pull the next card.

If a card needs more players than you've seated, it's skipped and you're told how many were excluded.

Managing content

Sign in at /admin/login.

  • Categories: top-level groups shown on the home screen.
  • Decks: collections of cards inside a category.
  • Cards: text + rarity tier + optional image. Use $P in the card text for any spot that should become a player name. Multiple $Ps in one card pick different players. Use $P1, $P2, … for stable references — the same number always maps to the same player within a single draw (e.g. $P1 dares $P2 … $P1 drinks too).
  • Drop rate: 1 in 5 is the most common tier; 1 in 100 is the rarest. Rarity controls how often the card surfaces during a shuffled run.

That's it. There are no user accounts to manage; the password in ADMIN_PASSWORD is the whole auth surface.

Local development

If you'd rather run it without Docker:

npm install
cp .env.example .env       # then fill in ADMIN_PASSWORD + AUTH_SECRET
npm run dev                # applies the schema + seeds example data, then boots

npm run dev runs an idempotent pre-step that applies the Prisma schema and seeds an example library (two categories, three decks, a handful of cards). The seed is non-destructive: it only adds missing example rows and never overwrites your edits, so it's safe on every boot. Use npm run db:reset to wipe and re-seed when you want a clean slate.

Useful scripts: npm test, npm run test:e2e, npm run lint, npm run db:studio, npm run db:seed. Architecture notes for contributors live in AGENTS.md.