Sites
Conventions for every website an SVRBC project serves, whatever it’s built with or hosted on. Stack covers what a site is built with, and Hosting where it runs.
Special pages
Section titled “Special pages”Every site serves /_/, an index of its special pages: pages about the
site, rather than its content. They’re for the people who maintain the site,
and for anyone curious how it works. Every hostname a site answers serves
them (on a multi-tenant site, every tenant), and they’re marked noindex.
/_/ names the commit the site was deployed from, linked to it on
GitLab (https://gitlab.com/svrbc/<project>/-/commit/<sha>), with the
release’s tag when it has one. Anyone looking at the site can then tell what
is live and read exactly the source behind it, without working it out from
pipelines. It’s the deployed commit, not the newest on master: a merge
without a release changes master but not the site.
The deploy job writes it in, not the build: the job knows the commit
($CI_COMMIT_SHA, and $CI_COMMIT_TAG for a release), and a build that
contained it would differ on every commit, so the release could never reuse
the build cached from master’s pipeline. The page carries a
placeholder that the deploy job replaces in the built files, failing if it
finds none. This handbook’s is the example:
docs/_/index.md
and the pages job in
.gitlab-ci.yml.
/_/ starts with one page, which every site has:
/_/architecture, the architecture. How the site is built, deployed and served, with an SVG diagram: where the request goes (DNS, CDN, origin, any assets domain), how a change becomes a release, and links to the source repository and itsinfra/records. The diagram is a file in the repository, inlined into the page so it follows the site’s light or dark theme. A merge request that changes the architecture updates the diagram too.
Others get added to /_/ as a site needs them. Prefix any new one with
/_/ rather than inventing a top-level path, so it can’t collide with the
site’s own pages. A site with analytics links
analytics.svrbc.org from its /_/ rather
than showing its numbers itself.
doreancon.org’s are the example:
/_/architecture, from
src/special/
and src/assets/architecture.svg.
svrbc-audit checks that each site answers /_/ and
/_/architecture, and that its /_/ links the commit it was deployed from.
Analytics
Section titled “Analytics”A site that counts its visitors uses PostHog, without cookies. No site has to have analytics, but one that does follows this, so every SVRBC site’s numbers live in one place, read the same way, and none of them needs a consent banner.
-
One PostHog project for every site,
sites, in SVRBC’s organization on PostHog’s US cloud (us.posthog.com), on the free plan. PostHog records the host on every event, so a breakdown by$hostsplits the sites (and a multi-tenant site’s tenants), and every site uses the same key:posthog.init('phc_rHc6WofJM9x8MqQjHpnUrxqzJAUPbSiBuWSTrbLq3Pbn', {api_host: 'https://us.i.posthog.com',defaults: '2026-08-30',cookieless_mode: 'always',person_profiles: 'identified_only',}) -
One project, so the free plan. It allows one project per organization (
organizations_projects, limit 1, checked 2026-10-05); its monthly allowance of events is on the billing page, beside what the sites use. A project per site would need the pay-as-you-go plan (six projects, a card on file) for nothing a$hostfilter doesn’t already give; considered and declined 2026-10-07. A site that ever needs its own (other people’s access, its own retention) is the time to upgrade. -
Cookieless, always.
posthog-jsruns withcookieless_mode: 'always': no cookies, no local or session storage, so nothing that calls for a consent banner. PostHog tells visitors apart by a hash it computes on its servers, which resets daily, so a returning visitor counts again the next day. The project has to allow it (Settings → Web analytics → Cookieless server hash mode, orcookieless_server_hash_mode: 2through the API); without that PostHog drops every cookieless event, silently. -
No session replay, nor anything else that needs browser storage. Clicks are autocaptured, and pageviews follow the router (
defaults: '<date>'turns oncapture_pageview: 'history_change'). To name a button in the reports, give it adata-ph-capture-attribute-*attribute rather than writingposthog.capture()calls. -
Nothing is sent from local development: the client skips initialization in dev builds, so the numbers are visitors’.
-
No secrets. The project API key (
phc_…) can only send events, and is meant to be public, so it goes in the site’s committed config, like Nuxt’sruntimeConfig.public. -
analytics.svrbc.org shows them all, in one place, from one dashboard (
svrbc/analytics.svrbc.org). It counts every site together, and its comparisons break down by$host(users, sessions, pageviews; top pages by full URL), so a new site appears there by itself, with nothing to add. A site links it from its/_/; it doesn’t embed its own dashboard, and doesn’t need a/_/analytics. -
The numbers are public. Visitor counts for SVRBC’s sites aren’t sensitive, so the dashboard is shared publicly (Share → share publicly, then the
https://us.posthog.com/embedded/…link) and analytics.svrbc.org is a public, developer-facing Pages site that embeds it. Sharing is read-only, and the page needs no API key. Making them private would take more than Pages access control: a share link works for anyone who has it, so a members-only page around it would hide the link without protecting the data. -
The dashboard is edited in PostHog, not in a repository, and shows a change at once; only its share link is in analytics.svrbc.org’s
site/index.html. It started from the Website Metrics template, with tiles for pageviews by$hostand autocaptured clicks by$el_text.
doreancon.org is the example of a site that counts its visitors:
src/components/Analytics.astro.
One thing trips up a new project, should SVRBC ever make another:
- A new project’s dashboards sit behind PostHog’s onboarding screen,
which returns on every visit until onboarding is marked done. Skipping
through it doesn’t always stick; marking it done through the API does:
PATCH /api/environments/<id>/with{"has_completed_onboarding_for": {"product_analytics": true, "web_analytics": true}}.
svrbc-audit checks that a project using posthog-js
runs it cookieless and sends to the shared project, and warns about other
analytics packages.