No routing rules
QBSheet keeps its state on the device, not in the address bar. Every screen lives at one URL, so nothing needs routing and there’s no single-page-app fallback to configure. Default static hosting settings work.
QBSheet builds into a folder of static files. Put that folder on a web host and you have your own working copy, with no application server behind it and no accounts for the people scoring with it.
From clone to kickoff
Setting QBSheet up and updating it later are the same short process.
Build the site.
QBSheet needs Node.js 20 or later. Run npm ci to install dependencies, then npm run build. The finished site lands in dist/. Neither the build nor the site it produces contacts anything we run.
Put dist/ on a web host.
GitHub Pages, Cloudflare Pages, a school web server, a machine on the venue network. Asset paths are relative, so one build works at a domain root or inside a repository path without rebuilding it. Set BASE_PATH only if your host needs an absolute prefix.
Rebuild when you want a newer version.
Pull, build again, replace the folder. Devices already in a game keep running the build they started on. The new one installs quietly and waits until somebody confirms the round is over.
QBSheet keeps its state on the device, not in the address bar. Every screen lives at one URL, so nothing needs routing and there’s no single-page-app fallback to configure. Default static hosting settings work.
Games stay on the device that scored them. You won’t be provisioning storage, running backups, or keeping a server reachable while a round is going.
Scorekeepers don’t sign in. There are no users to create, no passwords to reset, and nobody locked out at the table waiting on you.
Your copy doesn’t talk to any server we run. If rooms connect to tournament control, they connect to your tournament server over QBTCP, and QBSheet is only the scoresheet.
Anywhere static
If a host serves static files over HTTPS, it can serve QBSheet.
npm run build and the output directory to dist/. Netlify and similar hosts take the same two settings.dist/ to the rooms around it. Once a game is open, QBSheet doesn’t need anything past that laptop.The offline part
The offline shell is a service worker, and browsers only install one on a secure origin. In practice that means HTTPS, or localhost while you’re testing. Over plain HTTP the scorer still loads and still scores, but nothing is cached, so the next device that starts cold needs the network again.
If offline scoring is why you’re hosting this, put a certificate in front of it. Rooms that connect to tournament control need one anyway, because QBTCP is a connection your tournament server owns rather than anything QBSheet hosts.
Open by design
QBSheet is licensed under the GNU AGPL, version 3 or later. You can host it, modify it, and run your league’s own version of it.
One obligation comes with that. If you change QBSheet and then let other people use your changed version over a network, the AGPL asks you to offer them the source for what they’re using. Hosting an unmodified build doesn’t involve that step.
The whole setup is four commands, and the first one is git clone.