Host QBSheet yourself

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

Three steps, and then the same three steps again

Setting QBSheet up and updating it later are the same short process.

  1. Build

    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.

  2. Serve

    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.

  3. Update

    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.

What you don’t have to run

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.

No database

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.

No accounts

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.

Nothing of ours in the loop

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

Somewhere to put it

If a host serves static files over HTTPS, it can serve QBSheet.

GitHub Pages
Project repositories are served from a subpath, which the relative asset paths already handle. The default build works there with no configuration.
Cloudflare Pages
Set the build command to npm run build and the output directory to dist/. Netlify and similar hosts take the same two settings.
Your own server
Apache, nginx, Caddy, or whatever static hosting your school is already paying for.
A venue laptop
A laptop can serve dist/ to the rooms around it. Once a game is open, QBSheet doesn’t need anything past that laptop.

The offline part

Serve it over HTTPS

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

Yours to change

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.

Ready to host it?

The whole setup is four commands, and the first one is git clone.