- Go 54.9%
- CSS 27.9%
- HTML 13.8%
- Shell 3.4%
|
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
The arrow reads more naturally than the em-dash for "feedback going to Posta." Updates the actor doc name, the HTML page title, and the archive page header. Tests use their own fixture names and don't need to track this. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| app-icon | ||
| deploy | ||
| internal | ||
| static | ||
| templates | ||
| .gitignore | ||
| .woodpecker.yaml | ||
| go.mod | ||
| go.sum | ||
| intro.md | ||
| main.go | ||
| mark-night.png | ||
| README.md | ||
| SPEC.md | ||
posta/web
The marketing/documentation site for posta, served by a single Go binary.
Layout
web/
├── main.go HTTP server + spec-md cache
├── templates/
│ ├── layout.html shared header/footer/nav
│ ├── index.html / — landing
│ ├── spec.html /spec — server-rendered SPEC.md
│ └── design.html /design — design system reference
├── static/
│ └── style.css all visual decisions
└── go.mod
Templates and static files are embedded with embed.FS, so the binary is
self-contained.
Run
go run . --listen :9495 --spec ../spec/SPEC.md
Flags:
--listenTCP listen address (default:9495).--specpath toSPEC.md. Read on every request, re-rendered when mtime changes. Default../spec/SPEC.md(assumes theposta/specrepo is a sibling).--feedback-urlcanonical URL of the/feedbackroom (e.g.https://posta.no/feedback). Empty disables the room entirely; everything else still works.--feedback-keyspath to the room'skeys.json(required with--feedback-url). Generate withposta-web genkeys --out <path>.--feedback-dbpath to the room's SQLite database (required with--feedback-url). Created on first start.--feedback-owner-urlURL to pre-seed as a subscriber on first start (optional). Lets the operator's own client see the very first wrapped broadcast end-to-end.
/feedback room
When --feedback-url is set, posta-web mounts a Posta participant at that
URL's path. GET returns the actor doc (kind: "room"); POST receives
signed envelopes per SPEC §7. The room becomes stateful: SQLite database
plus the keys file must live on a persistent volume.
Bootstrap order on a fresh deployment:
mkdir -p /var/lib/posta-web && chown posta:posta /var/lib/posta-web
chmod 0700 /var/lib/posta-web
posta-web genkeys --out /var/lib/posta-web/feedback-keys.json
# Then start the service with:
# --feedback-url=https://posta.no/feedback
# --feedback-keys=/var/lib/posta-web/feedback-keys.json
# --feedback-db=/var/lib/posta-web/feedback.db
# --feedback-owner-url=https://arne.posta.no
Subsequent restarts re-open the existing files. Pending schema migrations and outbound-row cleanup run automatically on every startup.
How /spec works
- The handler asks
specCache.render()for the current HTML + TOC. - The cache stats
SPEC.md. If mtime hasn't advanced, return the cached HTML. Otherwise re-read, re-parse with goldmark, walk the AST to collect h2 + h3 headings into a TOC, and cache. - The template inlines the rendered HTML and the TOC list.
This means edit SPEC.md and refresh — no rebuild, no JS rendering, no
external dependencies at runtime.
Code highlighting
Goldmark's chroma integration emits <span class="ch-…"> tokens. Visual
mapping lives in static/style.css under the .ch-chroma rules — the
classes are mapped to the project's cream/forest palette directly, so the
spec's code blocks share the same look as the home page's quickstart.
Design system
/design documents the palette, type scale, components, and CSS tokens used
across both this site and any future surfaces. Treat it as the canonical
reference when adding pages.