Files
desfoto/AGENTS.md

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 into assets-src/ (idempotent; assets-src/ is not committed).
  • python3 scripts/build-site.py — rebuild all of site/. Prints build ok and 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, runs nginx -t and docker compose config, then python3 -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.py and src/pages.py; never hand-edit site/. 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:LEGAL mirrors 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 German alt.
  • 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 off in nginx.conf — never enable request logging;
  • error_log /dev/null crit; in nginx.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 a mailto: 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.