Skip to content

Publishing a copy

thaneye edited this page Oct 25, 2026 · 2 revisions

Publishing a copy

Building a copy of the pages for a web site, the visit counter, and the deploy workflow.

python tools/build_site.py --out site writes only what a web site needs (index.html, public/, LICENSE, NOTICE) and marks the copy as hosted in public/config.js. On a hosted copy the Tor choice is not offered (an .onion address cannot be reached from an https page in an ordinary browser) and the session is kept in the browser only if the visitor ticks Keep this session in this browser. A local run, a file:// copy and any copy you host from the repository as it is keep the open edition's behaviour.

Counting visits is off unless you ask for it: --stats-code MYCODE (a GoatCounter site code) or --stats-endpoint https://… (your own GoatCounter) makes the published pages count which page was opened and which features were used, by name only (public/js/hopline-stats.js). It is an image request, so no script from the counting service runs on the page; nothing from the address bar, the graph, the labels or the notes is sent; no cookies are set; and a browser that sends Do Not Track or Global Privacy Control is not counted. The pages then say so. --version "$(git rev-parse --short HEAD)" adds ?v= to every script and style address, so a browser cannot mix new pages with old scripts after a deploy.

It also writes a _headers file (no referrer, no content sniffing, no framing) that Cloudflare and Netlify read. .github/workflows/deploy.yml publishes to Cloudflare on every push to master once the unit and tool tests pass: it runs this script and uploads only its output to a Cloudflare Pages project (Direct Upload; the project name and production branch are set at the top of the workflow). It needs the secrets CLOUDFLARE_API_TOKEN (a token that can edit Cloudflare Pages) and CLOUDFLARE_ACCOUNT_ID and, to count visits, the variable GOATCOUNTER_CODE.

A second copy on GitHub Pages. .github/workflows/pages.yml builds the same folder after the same tests and publishes it with GitHub's own Pages actions at https://<owner>.github.io/<repository>/. It needs no secrets, only Settings, Pages, Source: GitHub Actions, and it runs apart from the Cloudflare deploy, so either can fail without stopping the other. On a project site the pages live under /<repository>/, so the build is given --base-path "/<repository>/": the 404 page's "Back to Hopline" link is the one address that cannot be relative. The visit counter is left off in this copy, because it would add its numbers to the main site's. GitHub Pages cannot send custom headers, so the _headers file has no effect there: every page also asks for no referrer with a <meta name="referrer"> tag, but nothing there stops the pages from being shown in another site's frame. Pages tells browsers to keep files for 10 minutes, so a page can be up to 10 minutes old after a deploy (the scripts carry the commit in ?v=). Browser storage is separate for each address, so a session saved on one copy is not visible on the other. GitHub's terms do not allow commercial or SaaS-style sites on Pages.

Clone this wiki locally