diff --git a/CHANGELOG.md b/CHANGELOG.md
index b31ecb8..c07e08d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,12 @@ Alle Änderungen an Grotti. Format nach [Keep a Changelog](https://keepachangelo
## [Unreleased]
+## [2.2.1] – 2026-10-15
+
+### Geändert
+
+- Anleitungen mit relativen Bild- und Kapitelpfaden (`../web/static/doku/…`, `Anleitung-*.md`), damit Screenshots und Querverweise auch auf Git lesbar sind; die App schreibt sie beim Rendern auf `/static/…` bzw. `/doku/…` um.
+
## [2.2.0] – 2026-10-15
### Neu
diff --git a/docs/Anleitung-ACE.md b/docs/Anleitung-ACE.md
index e8754a0..a766168 100644
--- a/docs/Anleitung-ACE.md
+++ b/docs/Anleitung-ACE.md
@@ -2,7 +2,7 @@
Stand **15.10.2026**. Mehrfarb-Drucke brauchen vor dem Start eine Zuordnung Datei-Farbe → ACE-Platz und eine passende Spule am Drucker.
-
+
## Spule einlegen
@@ -12,7 +12,7 @@ Stand **15.10.2026**. Mehrfarb-Drucke brauchen vor dem Start eine Zuordnung Date
Es gibt **kein freies Spulen-Dropdown** beim Start: Grotti nimmt die Rolle(n), die am Ziel-Drucker liegen. Material-Mismatch oder zu wenig Rest → Warnung vor dem Start.
-Etiketten mit QR: [Material und mehr](Anleitung-Material).
+Etiketten mit QR: [Material und mehr](Anleitung-Material.md).
## ACE-Map beim Senden
@@ -35,5 +35,5 @@ Externe Spule / keine ACE-Slots: keine `.acm` nötig.
## Weiter
-- [Dateien senden](Anleitung-Dateien)
-- [Material](Anleitung-Material)
+- [Dateien senden](Anleitung-Dateien.md)
+- [Material](Anleitung-Material.md)
diff --git a/docs/Anleitung-Dateien.md b/docs/Anleitung-Dateien.md
index eb95f16..56df1f8 100644
--- a/docs/Anleitung-Dateien.md
+++ b/docs/Anleitung-Dateien.md
@@ -2,7 +2,7 @@
Stand **15.10.2026**. Seite `/dateien` — Bibliothek links, Senden rechts.
-
+
## Bibliothek
@@ -31,7 +31,7 @@ Unter Optionen u. a.:
- **Bettnetz / Auto-Level** beim MQTT-Start (Anycubic)
- Maschinen-Override, Projekt zuweisen
-- **ACE-Zuordnung** — siehe [ACE und Spulen](Anleitung-ACE)
+- **ACE-Zuordnung** — siehe [ACE und Spulen](Anleitung-ACE.md)
## Warum es dauert
@@ -39,11 +39,11 @@ Große Dateien brauchen oft **eine Minute**. In der Sidebar unter **Senden** sie
## Nach dem Start
-- Fortschritt auf der [Wand](Anleitung-Wand) und in der Sidebar **Läuft jetzt**
-- Bei „Wenn frei“: Eintrag unter [Warteschlange](Anleitung-Warteschlange)
+- Fortschritt auf der [Wand](Anleitung-Wand.md) und in der Sidebar **Läuft jetzt**
+- Bei „Wenn frei“: Eintrag unter [Warteschlange](Anleitung-Warteschlange.md)
- Später unter **Protokoll** mit **Nochmal** (inkl. gespeicherter ACE-Map)
## Weiter
-- [ACE und Spulen](Anleitung-ACE)
-- [Warteschlange](Anleitung-Warteschlange)
+- [ACE und Spulen](Anleitung-ACE.md)
+- [Warteschlange](Anleitung-Warteschlange.md)
diff --git a/docs/Anleitung-Einrichtung.md b/docs/Anleitung-Einrichtung.md
index 4cf106c..6a2e9ea 100644
--- a/docs/Anleitung-Einrichtung.md
+++ b/docs/Anleitung-Einrichtung.md
@@ -34,7 +34,7 @@ copy config.example.json config.json
| `energy`, `telegram`, `alerts` | Kosten im Protokoll und Telegram — später auch unter Einstellungen. |
| `secret_key` | Für Login-Sessions. Beim ersten Start wird ein Wert erzeugt, wenn leer. |
-Drucker beim ersten Start über `drucker.json` (Seed). Danach pflegt man sie unter [Einstellungen](Anleitung-Einstellungen).
+Drucker beim ersten Start über `drucker.json` (Seed). Danach pflegt man sie unter [Einstellungen](Anleitung-Einstellungen.md).
```json
[{ "name": "Kobra 3 da26", "host": "10.10.1.60" }]
@@ -50,7 +50,7 @@ Die Familie (Kobra 3 oder S1) liest Grotti aus dem Namen.
Dann öffnen. Beim ersten Start legst du den Admin-Benutzer an. Nach Code-Änderungen an Python oft neu starten.
-
+
## Sicherheit
@@ -61,6 +61,6 @@ Dann öffnen. Beim ersten Start legst du den Admin-Benu
## Weiter
-- [Oberfläche](Anleitung-Oberflaeche) — Navigation und Sidebar
-- [Dateien senden](Anleitung-Dateien) — erster Druck
+- [Oberfläche](Anleitung-Oberflaeche.md) — Navigation und Sidebar
+- [Dateien senden](Anleitung-Dateien.md) — erster Druck
- Ausführlich im `README.md` im Projektordner
diff --git a/docs/Anleitung-Einstellungen.md b/docs/Anleitung-Einstellungen.md
index 3ff2214..fcbdc13 100644
--- a/docs/Anleitung-Einstellungen.md
+++ b/docs/Anleitung-Einstellungen.md
@@ -2,11 +2,11 @@
Stand **15.10.2026**. Seite `/einstellungen` — Drucker, Automatik, Anzeige, Telegram, Energie.
-
+
## Dieser Browser
-- **Desktop** oder **Regal (Touch)** — nur lokal im Browser, siehe [Oberfläche](Anleitung-Oberflaeche).
+- **Desktop** oder **Regal (Touch)** — nur lokal im Browser, siehe [Oberfläche](Anleitung-Oberflaeche.md).
## Automatik
@@ -40,5 +40,5 @@ Watt und Strompreis für die Kosten im **Protokoll**. Optional Trockner/Ausschus
## Weiter
-- [Einrichtung](Anleitung-Einrichtung) (Config-Datei)
-- [Störungen](Anleitung-Stoerungen)
+- [Einrichtung](Anleitung-Einrichtung.md) (Config-Datei)
+- [Störungen](Anleitung-Stoerungen.md)
diff --git a/docs/Anleitung-Material.md b/docs/Anleitung-Material.md
index 41c8cdb..d410acf 100644
--- a/docs/Anleitung-Material.md
+++ b/docs/Anleitung-Material.md
@@ -2,7 +2,7 @@
Stand **15.10.2026**. Spulen, Etiketten, Projekte, Protokoll, Kameras, Aktivität und Ideen.
-
+
## Material
@@ -38,5 +38,5 @@ Zeitstrahl: Starts, Schritte, Fertig, Fehler, Abbrüche, offline. Filter nach Dr
## Weiter
-- [ACE und Spulen](Anleitung-ACE)
-- [Einstellungen](Anleitung-Einstellungen)
+- [ACE und Spulen](Anleitung-ACE.md)
+- [Einstellungen](Anleitung-Einstellungen.md)
diff --git a/docs/Anleitung-Oberflaeche.md b/docs/Anleitung-Oberflaeche.md
index df3830e..b0f147d 100644
--- a/docs/Anleitung-Oberflaeche.md
+++ b/docs/Anleitung-Oberflaeche.md
@@ -8,7 +8,7 @@ Links (Desktop): **Drucker**, **Dateien**, **Kameras**, **Aktivität**, **Wartes
Unter ca. 760 px: untere Leiste mit den wichtigsten Seiten. Das Seitenmenü lässt sich zur Icon-Rail einklappen.
-
+
## Live-Leiste
@@ -33,5 +33,5 @@ Shortcut in der URL: `?shelf=1` bzw. `?shelf=0`. Nur dieser Browser (`localStora
## Weiter
-- [Druckerwand](Anleitung-Wand)
-- [Dateien senden](Anleitung-Dateien)
+- [Druckerwand](Anleitung-Wand.md)
+- [Dateien senden](Anleitung-Dateien.md)
diff --git a/docs/Anleitung-Stoerungen.md b/docs/Anleitung-Stoerungen.md
index 5a647ba..62e30cd 100644
--- a/docs/Anleitung-Stoerungen.md
+++ b/docs/Anleitung-Stoerungen.md
@@ -31,7 +31,7 @@ Was tun: Abbruch über Grotti (nicht nur am Display), auf der Wand den Task-Hinw
## ACE / „cannot parse“
-ACE-Zuordnung unter Dateien → Optionen prüfen. Spulen am richtigen Platz. Siehe [ACE und Spulen](Anleitung-ACE).
+ACE-Zuordnung unter Dateien → Optionen prüfen. Spulen am richtigen Platz. Siehe [ACE und Spulen](Anleitung-ACE.md).
## Offline
@@ -52,5 +52,5 @@ Oft noch Verarbeitung auf dem Drucker. In der Sidebar unter **Senden** den Forts
## Weiter
-- [Druckerwand](Anleitung-Wand)
-- [Warteschlange](Anleitung-Warteschlange)
+- [Druckerwand](Anleitung-Wand.md)
+- [Warteschlange](Anleitung-Warteschlange.md)
diff --git a/docs/Anleitung-Wand.md b/docs/Anleitung-Wand.md
index d824b5d..a771f72 100644
--- a/docs/Anleitung-Wand.md
+++ b/docs/Anleitung-Wand.md
@@ -2,7 +2,7 @@
Stand **15.10.2026**. Startseite `/` — eine Karte je Drucker. Klick öffnet das Cockpit.
-
+
## Karte
@@ -30,7 +30,7 @@ Während eines Abräum-Ablaufs blendet Grotti „Platte geräumt“ aus — der
URL mit Hash: `/#` (z. B. nach Klick auf die Karte).
-
+
Inhalt:
@@ -45,10 +45,10 @@ Inhalt:
- Gesperrte Drucker (Einstellungen) starten keine neuen „wenn frei“-Jobs.
- Live-Daten kommen mit wenigen Sekunden Verzögerung.
-- Ein Task-Hinweis auf der Karte zeigt, wenn auf dem Drucker noch ein alter Auftrag hängt — siehe [Störungen](Anleitung-Stoerungen).
+- Ein Task-Hinweis auf der Karte zeigt, wenn auf dem Drucker noch ein alter Auftrag hängt — siehe [Störungen](Anleitung-Stoerungen.md).
## Weiter
-- [Dateien senden](Anleitung-Dateien)
-- [Warteschlange und Ablauf](Anleitung-Warteschlange)
-- [Störungen](Anleitung-Stoerungen)
+- [Dateien senden](Anleitung-Dateien.md)
+- [Warteschlange und Ablauf](Anleitung-Warteschlange.md)
+- [Störungen](Anleitung-Stoerungen.md)
diff --git a/docs/Anleitung-Warteschlange.md b/docs/Anleitung-Warteschlange.md
index c033826..c9153ba 100644
--- a/docs/Anleitung-Warteschlange.md
+++ b/docs/Anleitung-Warteschlange.md
@@ -2,7 +2,7 @@
Stand **15.10.2026**. Aufträge „wenn frei“, Priorität, und der Kobra-3-Ablauf (drucken → abkühlen → schieben → tasten).
-
+
## Seite Warteschlange
@@ -48,5 +48,5 @@ Aktueller Schritt: auf der Druckerkarte und in der Sidebar. Abbrechen an beiden
## Weiter
-- [Druckerwand](Anleitung-Wand)
-- [Störungen](Anleitung-Stoerungen)
+- [Druckerwand](Anleitung-Wand.md)
+- [Störungen](Anleitung-Stoerungen.md)
diff --git a/grotti/version.py b/grotti/version.py
index 60ec20d..8f4b1b9 100644
--- a/grotti/version.py
+++ b/grotti/version.py
@@ -1,3 +1,3 @@
"""Version von Grotti (SemVer). Bei jeder Änderung CHANGELOG.md mitführen."""
-__version__ = "2.2.0"
+__version__ = "2.2.1"
diff --git a/web/app.py b/web/app.py
index 2b18696..aa2064b 100644
--- a/web/app.py
+++ b/web/app.py
@@ -519,7 +519,15 @@ def create_app(cfg):
return labels.get(name, name.replace("Anleitung-", "").replace("-", " "))
def render_markdown(path):
+ """Markdown für die App: Git-relative Bild-/Kapitelpfade → App-URLs."""
text = path.read_text(encoding="utf-8")
+ # docs/… → web/static/… im Repo; unter /doku als /static/…
+ text = text.replace("../web/static/", "/static/")
+ text = re.sub(
+ r"\]\((Anleitung-[A-Za-z0-9_-]+)(?:\.md)?\)",
+ r"](/doku/\1)",
+ text,
+ )
html = markdown.markdown(text, extensions=["tables", "fenced_code", "sane_lists"])
return Markup(html)