- JavaScript 43.2%
- HTML 31.8%
- CSS 24.4%
- Shell 0.4%
- Dockerfile 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| fonts | ||
| src | ||
| test | ||
| .dockerignore | ||
| .gitignore | ||
| .htmlvalidate.json | ||
| build.js | ||
| compose.yaml | ||
| Dockerfile | ||
| README.md | ||
| server.js | ||
| site-config.js | ||
| site.js | ||
| styles.css | ||
| watch.sh | ||
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.