3.4 KiB
desfoto.de — Agent Guidelines
What this repository is
The complete source of https://desfoto.de, the photography and video brand of
Denny Schulz (Neumünster). It is a hand-written static site: no framework, no CMS,
no runtime dependencies. src/ holds Python builders and the editorial content,
scripts/build-site.py renders everything into the committed site/ directory,
and nginx serves site/ from a container behind the shared VPS Traefik instance.
dennyschulz.de is a separate site and must never be modified or linked from here.
Commands
python3 scripts/fetch-assets.py— download pool images, Google Fonts subsets and licences intoassets-src/(idempotent;assets-src/is not committed).python3 scripts/build-site.py— rebuild all ofsite/. Printsbuild okand a link/alt check; exits non-zero on any broken internal reference..ocauto/qa— authoritative deterministic QA: builds twice to prove the output is reproducible, runsnginx -tanddocker compose config, thenpython3 -m unittest discover -s tests.- Local runtime:
docker compose -f compose.yml up -d→ http://127.0.0.1:18430 - UI smoke:
/home/king/bin/oc-ui-smoke http://127.0.0.1:18430/ - Release:
/home/king/bin/oc-release /home/king/projects/desfoto "<msg>" <files...>
Editing rules
- Content lives in
src/content.pyandsrc/pages.py; never hand-editsite/.site/is generated output that happens to be committed for deployment. - Never invent facts. Prices, testimonials, client names, awards and biography dates
are intentionally absent; do not add them without verified information. Legal data
in
src/content.py:LEGALmirrors the operator's own Impressum (§ 5 DDG). - Keep the design language: paper/ink/rust/teal tokens from
src/theme.py, rounded cards, hairline dividers, Fraunces for display and Manrope for text. - Images come from the operator's own pool through
src/images.json. Only add an entry if the operator holds the rights; always give a meaningful Germanalt. - Two-space indentation,
from __future__ import annotations, type hints on public functions, no new third-party Python packages (Pillow is the only dependency).
Privacy contract
The /datenschutz/ page makes concrete promises. Any change that would break one of
them is a defect, not a style question:
- no cookies, no
localStorage, no analytics, no tracking; access_log offinnginx.conf— never enable request logging;error_log /dev/null crit;innginx.conf— never write an error-log file either;- fonts, scripts, styles and images are served from this origin only;
- YouTube is embedded exclusively via the click-to-load facade
(
youtube-nocookie.com) — no iframe before the click, no preconnect; - the contact form never posts anywhere; it composes a local
mailto:draft (the non-JS fallback is amailto:form action, which also stays on the device).
tests/test_site.py enforces these promises; extend it when you add a new flow.
Deployment
.ocauto/deploy <sha> ships the committed build to /home/denny/stacks/desfoto on
prod-main, snapshots the previous release into /home/denny/stacks/desfoto-releases/
and removes the obsolete desfoto.de → dennyschulz.de labels from /srv/stack.
.ocauto/verify <sha> proves the live site matches the release. Details, including
rollback, are in docs/deployment.md. Traefik is shared infrastructure: route through
labels, never restart or recreate the proxy.