{"id":16963077,"url":"https://github.com/obilodeau/ceopardy","last_synced_at":"2026-05-31T18:00:52.083Z","repository":{"id":55015348,"uuid":"84966147","full_name":"obilodeau/ceopardy","owner":"obilodeau","description":"Game Board for NorthSec's Hacker Jeopardy since 2017","archived":false,"fork":false,"pushed_at":"2026-05-27T05:46:19.000Z","size":1377,"stargazers_count":14,"open_issues_count":4,"forks_count":12,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-05-27T07:23:02.082Z","etag":null,"topics":["board","flask","game","hacker","jeopardy","sqlalchemy"],"latest_commit_sha":null,"homepage":"https://www.nsec.io/competition/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/obilodeau.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2017-03-14T15:35:23.000Z","updated_at":"2026-05-27T05:45:39.000Z","dependencies_parsed_at":"2024-10-28T13:21:38.566Z","dependency_job_id":"d3dfc392-6fba-4310-98ea-8bbeb2e69221","html_url":"https://github.com/obilodeau/ceopardy","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/obilodeau/ceopardy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obilodeau%2Fceopardy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obilodeau%2Fceopardy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obilodeau%2Fceopardy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obilodeau%2Fceopardy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/obilodeau","download_url":"https://codeload.github.com/obilodeau/ceopardy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obilodeau%2Fceopardy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33742187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["board","flask","game","hacker","jeopardy","sqlalchemy"],"created_at":"2024-10-13T23:23:31.139Z","updated_at":"2026-05-31T18:00:52.078Z","avatar_url":"https://github.com/obilodeau.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ceopardy\n\nThe Hacker Jeopardy Game Board we use at NorthSec.\n\n## Screenshots\n\nThis is what the crowd sees:\n\n![The Viewer Interface Displaying the Game Board](docs/images/viewer-board.png)\n\nWhen a clue is displayed:\n\n![The Viewer Interface Displaying a Clue](docs/images/viewer-clue.png)\n\nThis is the host interface, how you control the game:\n\n![The Host Interface](docs/images/host.png)\n\nNote that there are two drawers that can be opened by clicking on the brown\narrows at the top and at the bottom of the screen. The top drawer contains\nthe functions to change team names. The bottom drawer provides functions to\ndisplay a custom message on the board or to pause a game.\n\n\n## Architecture\n\nStarting with v0.5, Ceopardy is split in two parts:\n\n- A Python/Flask back-end that exposes a small REST API (`/api/v1/...`) and\n  broadcasts state changes over a single Socket.IO namespace (`/game`).\n- A Vite + Vue 3 + TypeScript front-end (in `frontend/`) that powers the\n  crowd-facing viewer, the host UI, and the start screen.\n\nCeopardy is designed for single-operator local-network use: the server binds\nto `127.0.0.1` and there is no authentication on the host UI. If you need to\nexpose it on a LAN, put your own reverse proxy (and auth) in front.\n\n\n## Running Ceopardy (operators)\n\nFor people who just want to host a game.\n\nInstall [pipx](https://pipx.pypa.io/), then install the latest release wheel\n(requires `curl` and `jq`):\n\n    pipx install \"$(curl -fsSL https://api.github.com/repos/obilodeau/ceopardy/releases/latest | jq -r '.assets[] | select(.name | endswith(\".whl\")) | .browser_download_url')\"\n\nOr pin a specific version from the\n[releases page](https://github.com/obilodeau/ceopardy/releases):\n\n    pipx install https://github.com/obilodeau/ceopardy/releases/download/v0.8.0/ceopardy-0.8.0-py3-none-any.whl\n\nThen scaffold a per-game directory and start the server:\n\n    mkdir my-game \u0026\u0026 cd my-game\n    ceopardy init               # writes data/ + game-media/ starter content\n    # edit data/Questions.cp and data/1st.round to set up your game\n    ceopardy serve              # starts the server on http://127.0.0.1:5000/\n    ceopardy serve --debug      # add verbose logging + auto-reload\n\nOpen the two URLs `ceopardy serve` prints:\n\n- Viewer: \u003chttp://localhost:5000/\u003e — what the crowd sees on the projector.\n- Host:   \u003chttp://localhost:5000/host\u003e — what you (the operator) drive.\n\n`ceopardy init` never overwrites existing files; it's safe to re-run. The\nSQLite database, round files, and uploaded media all resolve relative to the\ndirectory you run `ceopardy` from, so **keep one directory per game**.\n\n\u003e **Note:** Ceopardy persists transactions to a SQLite database as the host\n\u003e submits points, so a crash doesn't lose the game state. The flipside is\n\u003e that games must be finalized (click \"Game over\") before a new one can be\n\u003e started in the same directory.\n\n\n## Hacking on Ceopardy (developers)\n\nYou need Python 3.11+, pip, virtualenv, and Node.js (LTS).\n\n    git clone https://github.com/obilodeau/ceopardy.git\n    cd ceopardy\n    make venv                          # creates .venv/ + installs deps\n    source .venv/bin/activate          # bash/zsh\n    source .venv/bin/activate.fish     # fish\n    make init                          # seeds data/ + game-media/\n    make run                           # starts Flask (:5000) + Vite (:5173)\n\nThen open \u003chttp://localhost:5173/\u003e — Vite hot-reloads the UI and proxies\n`/api` and `/socket.io` to Flask on `:5000`. **In dev, always use the Vite\nURL** (`:5173`); the Flask port serves the *built* SPA which gets stale.\n\n### Optional: direnv\n\nIf you use [direnv](https://direnv.net/), the repo ships an `.envrc` that\nauto-activates `.venv` on `cd`. Run `make venv` first (direnv won't), then\n`direnv allow`.\n\n### Before committing\n\nRun the full CI suite — same checks GitHub Actions runs:\n\n    make ci      # ruff lint + format check + prettier + vue-tsc + pytest\n\nTo auto-fix Python formatting first:\n\n    make format\n\nSee `AGENTS.md` for the conventions the codebase follows.\n\n### Building a wheel locally\n\n`make build` reproduces the release path (frontend bundle + sdist + wheel):\n\n    make build\n    pipx install --force dist/ceopardy-*.whl   # test the wheel end-to-end\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobilodeau%2Fceopardy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobilodeau%2Fceopardy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobilodeau%2Fceopardy/lists"}