furtka/website/README.md
Daniel Maksymilian Syrnicki 2fbafd5c77
Some checks failed
CI / test (push) Waiting to run
Build ISO / build-iso (push) Successful in 18m1s
CI / lint (push) Successful in 24s
CI / markdown-links (push) Successful in 18s
CI / validate-json (push) Successful in 21s
Deploy site / deploy (push) Has been cancelled
feat(website): logo poll at /logo/ with cookie-free vote counter
Two marks (M and R) side by side, EN + DE, with the site-header and real
16 px favicon context for each. Votes go to ops/poll/pollsvc.py, a stdlib
Python service behind nginx at /api/poll/ (SQLite, systemd DynamicUser,
rate-limited). Devices are counted once via a salted hash of IP + user
agent; the privacy pages document it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MScAinbyMdeNc7H2BZdnnG
2026-08-26 12:57:23 +02:00

90 lines
3.3 KiB
Markdown

# website/ — furtka.org
Hugo source for [furtka.org](https://furtka.org). Intentionally minimal while
the project is pre-alpha: a single idea page in English and German, nothing more.
More pages will come back when there's something real to show.
## Local build
```sh
cd website
hugo server # http://localhost:1313
```
Requires Hugo **extended** ≥ 0.140.
## Deploy
Hosted on `forge-runner-01` (Proxmox VM, Ubuntu 24.04). Hugo runs on the VM;
nginx serves the built output from `/var/www/furtka.org`. TLS is terminated by
an upstream openresty reverse proxy — the VM itself only speaks plain HTTP.
### Auto-deploy on push-to-main (default)
`.forgejo/workflows/deploy-site.yml` fires on every push to `main` that touches
`website/**`. The self-hosted runner *is* forge-runner-01, so the whole deploy
collapses to a local rsync into `/srv/furtka-site/` + `hugo --minify` into
`/var/www/furtka.org/`. No SSH hop, no secrets. Runs in under a minute.
The in-CI script is `website/deploy-ci.sh`. Don't invoke it from your dev box —
it assumes it's already on the target host.
### Manual deploy (fallback)
For out-of-band pushes (feature branch, CI outage), deploy from your dev
machine:
```sh
./website/deploy.sh
```
This rsyncs `website/` to `/srv/furtka-site/` on the VM over SSH and runs
`hugo --minify` into `/var/www/furtka.org`. Same end state as the CI path,
just with an SSH hop.
### Poll counter
`/api/poll/` is a tiny stdlib Python service (`ops/poll/pollsvc.py`,
SQLite, systemd `DynamicUser`) behind nginx on `127.0.0.1:8090`. Install or
update it on the VM with `sudo ops/poll/setup-poll.sh`; the nginx location
and rate limit come from `ops/nginx/` via `setup-vm.sh`. Devices are told
apart by a salted hash of IP + user agent — no cookie — and a repeat vote
from the same device changes the choice instead of adding one.
### First-time VM setup
Only needed once, when provisioning a fresh forge-runner VM:
```sh
ssh forge-runner
sudo /srv/furtka-site/ops/nginx/setup-vm.sh # or copy the script over first
```
## Structure
```
hugo.toml Hugo config (multilingual: en default, de)
content/ Markdown pages
_index.md Home (EN)
_index.de.md Home (DE)
logo.md / .de.md Logo poll (/logo/, /de/logo/) — layout `poll`, votes via /api/poll/
layouts/ Custom inline theme — no external theme or framework
_default/ baseof, single, list
partials/ head, header, footer, gate SVG, lang switcher, mark-m / mark-r (poll)
poll/single.html Logo poll page; strings come from the content front matter
index.html Home-only layout with editorial hero
assets/css/main.css Stylesheet (fingerprinted + minified on build)
assets/js/poll.js Vote script for /logo/ — plain fetch, no cookies, no storage
static/favicon.svg Gate mark in crimson
deploy.sh Manual rsync + remote Hugo build (over SSH, for off-CI pushes)
deploy-ci.sh Local rsync + Hugo build — runs on forge-runner-01 from CI
```
## Design
Modern-minimal on paper-white light / near-black dark. System-UI sans
(no webfonts — zero external requests, matches the self-hosting ethos).
Deep crimson accent, `prefers-color-scheme` switch.
The gate SVG is the one brand mark — a small wicket-gate glyph repeated in the
header, footer, and favicon.