Website for the campervan control systems https://campercan.net
  • JavaScript 43.2%
  • HTML 31.8%
  • CSS 24.4%
  • Shell 0.4%
  • Dockerfile 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Robert Marshall 00a72a5072
All checks were successful
CI / check (push) Successful in 9s
CI / deploy (push) Successful in 5s
Merge pull request 'Fix grammar and punctuation across the site copy' (#26) from grammar-fixes into main
Reviewed-on: #26
2026-10-07 21:08:40 +00:00
.forgejo/workflows Rename registry secret to PACKAGE_TOKEN 2026-10-07 15:36:40 +01:00
fonts Add static site built from the CamperCan design 2026-10-07 11:38:03 +01:00
src Fix grammar and punctuation across the site copy 2026-10-07 22:08:18 +01:00
test Require the two questions and email on the register form 2026-10-07 21:33:20 +01:00
.dockerignore Add Node static server and Docker packaging 2026-10-07 11:46:01 +01:00
.gitignore Read Umami settings from env and build at container start 2026-10-07 16:08:28 +01:00
.htmlvalidate.json Add skip link, focus rings, landmarks and contrast fixes 2026-10-07 14:44:23 +01:00
build.js Fill in node specs, add spec copy and photos 2026-10-07 21:01:27 +01:00
compose.yaml Read Umami settings from env and build at container start 2026-10-07 16:08:28 +01:00
Dockerfile Read Umami settings from env and build at container start 2026-10-07 16:08:28 +01:00
README.md Read Umami settings from env and build at container start 2026-10-07 16:08:28 +01:00
server.js Fix grammar and punctuation across the site copy 2026-10-07 22:08:18 +01:00
site-config.js Read Umami settings from env and build at container start 2026-10-07 16:08:28 +01:00
site.js Fix grammar and punctuation across the site copy 2026-10-07 22:08:18 +01:00
styles.css Require the two questions and email on the register form 2026-10-07 21:33:20 +01:00
watch.sh Rewrite home and how-it-works copy, add watch script 2026-10-07 18:58:42 +01:00

CamperCan site

A small static site. Every page is a file in src/, and node build.js turns them into the finished site in dist/.

Edit it

Pages are src/index.html (home), how.html, nodes.html, install.html and register.html. Change the words in the file you want and rebuild. No other page is affected.

The header, footer and green feedback band are in src/partials/. They show on every page, so change them once. A page pulls one in with a line like <!-- include band -->. Delete that line to drop it from the page.

Every page starts with two comment lines, <!-- title: ... --> and <!-- description: ... -->. They set the browser tab title and the text shown when the page is shared. The build fails if either is missing. Spec sheets use the node's name and blurb instead.

The site's web address is in src/site.json. This is the one place to change the domain. https://campercan.net is canonical, and the hosts listed in redirectHosts there (campercan.io and the www names) 301 to it. NPM must forward the original Host header (it does by default), or the redirect never fires. The share image is src/og.png.

Node details are in src/nodes.json. Change a name, blurb or spec row there and the nodes page and that node's spec sheet both update. Every spec sheet uses the layout in src/spec.html.

Build it

You need Node installed. Nothing else. Run node build.js. Don't edit dist/, it is rebuilt each time.

Run it

On the host, CI pushes an image to the Forgejo registry on every merge to main. Pull and restart after each merge:

docker compose pull && docker compose up -d

If the package is private, run docker login git.robware.uk on the host once.

To run a local build instead:

docker build -t git.robware.uk/rob/campercan:latest .
docker compose up -d

The container serves plain HTTP on host port 34817 (8080 inside). In Nginx Proxy Manager, point the proxy host at port 34817 and turn on Force SSL and HSTS. NPM must pass X-Forwarded-For (it does by default), or every visitor shares one rate limit.

Registrations are printed to the container log as JSON (docker compose logs -f web) until the real API exists.

Deleting a record

Submissions live only in the container log for now. To honour a deletion request, first confirm the record with docker compose logs web | grep <email>. Then recreate the container with docker compose up -d --force-recreate. That drops the whole log, so every registration goes with it, not just that one. This changes once the real API exists.

Analytics

The site uses Umami. It sets no cookies, so there is no banner. Fill in umami.script (the full tracker URL, e.g. https://analytics.example.com/script.js) and umami.websiteId in src/site.json. While either is empty, nothing is added.

The env vars UMAMI_SCRIPT and UMAMI_WEBSITE_ID override site.json. The container builds the site on start, so on the host put them in a .env file next to compose.yaml:

UMAMI_SCRIPT=https://analytics.example.com/script.js
UMAMI_WEBSITE_ID=your-website-id

The register button sends a register event.

Test it

Run node --test. CI runs the same build, lint and tests on every PR.

To check accessibility with axe, build first, then run PLAYWRIGHT_DIR=/path/to/playwright-install CHROMIUM_PATH=/path/to/chrome node test/axe.js. The Playwright folder needs playwright and axe-core installed (or set AXE_PATH to axe.min.js). It prints violations per page and does nothing if PLAYWRIGHT_DIR is unset. It is not part of CI.