7.8 KiB
Handoff — Nächste Session
Du (Claude, nächste Session) oder ich (Jörg, später) kommen hier zurück. Dieses Dokument sagt: was ist der Zustand, was wartet, wo liegen die Fäden.
Zustand (Details in STATUS.md)
Die Nostr-Publish-Pipeline ist live. Alle 18 Posts sind publiziert als
kind:30023-Events auf 5 Relays, 91 Bilder auf 2 Blossom-Servern. Die
SvelteKit-SPA unter svelte.joerg-lohrer.de rendert alles ordentlich.
Das inhaltliche Kernziel des Gesamtprojekts ist damit erreicht.
Der Rest sind Feinschliff- und Cutover-Aufgaben.
Was als Nächstes ansteht
Option 1 — CI-Push-Auto-Trigger verifizieren (optional)
Status: Workflow-Manual-Trigger ist grün (Run #1 am 18.04.2026). Automatischer Auto-Trigger bei Content-Push noch nicht ausprobiert — kann jederzeit beiläufig mitgenommen werden:
- Minimaler Edit in einem Post (z. B. Typo) → commit → push
main - Forgejo synct automatisch zu GitHub → Workflow triggert → 1 Post als
updatepubliziert - Log-Artefakt in GitHub Actions prüfen
Kein Ziel mehr, nur Bestätigung. Pipeline ist funktional vollständig.
Option 2 — Cutover auf joerg-lohrer.de
Voraussetzung: Option 1 optional, aber nicht blockierend. Die Pipeline läuft ja schon, ob manuell oder via CI ist für den Cutover egal.
Schritte:
- In All-Inkl KAS die Domain
joerg-lohrer.deauf den SvelteKit-Webroot umhängen (aktuell:svelte.joerg-lohrer.de→/www/htdocs/v109928/joerglohrer28/oder welcher Ordner auch immer). - SvelteKit-SPA deployen, sofern sie nicht schon dort liegt.
- Live-Check:
curl -sI https://joerg-lohrer.de/→ sollte die neue SPA liefern, nicht mehr Hugo.
Hugo-Altbestand bleibt als Archiv im hugo-archive-Branch.
Option 3 — Startseite + Menü-Navigation + Impressum in der SPA
Unabhängig von Cutover, aber Voraussetzung für diesen: ohne Design wäre die Hauptdomain eine rohe Post-Liste.
- Startseite bekommt ein eigenes Design (nicht nur Post-Liste dump)
- Menü-Navigation in
app/src/routes/+layout.svelte(Home, Archiv, Impressum, Mastodon-Link) - Impressum als Static-Page (SvelteKit-Route
/impressum/), nicht als Nostr-Event — soll nicht als Blog-Beitrag in Listen erscheinen. Text ist bereits imcontent/-Ordner (Repo-Quelle); die einzige rechtlich relevante HTML-Datei, die auf dem Server liegt.
Option 4 — SPA respektiert kind:5-Deletion-Events
Status: aktuell filtert die SPA nicht nach NIP-09. Wenn ein Event per
kind:5-Referenz gelöscht wurde (z. B. 7f5d08b8… deletet 89609df5…
für d=1744905463975 am 18.04.), zeigen Relays es meist nicht mehr aus —
aber die SPA würde es trotzdem rendern, falls ein Relay es doch liefert.
Zu tun: im kind:30023-Loader (app/src/lib/nostr/...) einen
Cross-Check auf kind:5-Events einbauen. Events, deren Addressable-Pointer
(30023:pubkey:d-tag) in einem kind:5 referenziert ist, werden
gefiltert. Defensive Maßnahme für zukünftige Duplikate / Soft-Deletes.
Option 5 — Repo/Nostr-Konflikt-Management
Warum: aktuell ist die Pipeline eine einseitige Straße — Repo → Nostr. Wenn du via Client (Habla, Yakihonne, Amber) auf Nostr editierst, überschreibt der nächste Pipeline-Lauf deine Client-Edits mit dem (alten) Repo-State. Das ist ein echter Datenverlust-Risikofaktor.
Zu tun:
- Defensiv (
created_at-Check): Pipeline liest vor Publish das aktuelle Event vom Relay und vergleichtcreated_at. Wenn das Remote-Event neuer ist: Abbruch mit Warnung. - Reverse-Sync (
pull-from-nostr-Subcommand): liest Events, vergleicht mit Repo, zeigt Diffs. Manuelle Konfliktauflösung.
Keine Eile, solange du nicht parallel editierst. Erst relevant, wenn du dich an Habla & Co. gewöhnst.
Option 6 — NIP-09-Delete als Pipeline-Subcommand
Status: heute einmalig per nak event -k 5 … mit neu erzeugter Bunker-
URL erledigt (Duplikat 1744905463975). Das war ein Workaround um das
„already connected"-Problem unserer Pipeline-Signer-Wiederverwendung.
Zu tun: in publish/src/subcommands/ einen delete-Subcommand bauen,
der NIP-09 sauber erledigt und unsere stabile Signer-Identität nutzt.
deno task publish-delete --slug <slug>
# oder
deno task publish-delete --event-id <hex>
Jetzt nicht dringend — nur bauen, wenn der Fall öfter eintritt.
Option 7 — Pipeline weg von GitHub (self-hosted CI)
Wann: Wenn der Optiplex-Server steht und ein zentraler Ort für Dienste existiert.
Varianten:
- Cron / systemd-Timer auf dem Optiplex, der alle X Minuten
git pull && deno task publishmacht. Einfach, minimaler Setup. - Woodpecker-CI als Docker-Container neben Forgejo. Volle Push-getriggerte Pipeline ohne GitHub.
Der Pipeline-Code selbst (publish/src/**) ist CI-agnostisch — nur die
Trigger-Konfiguration ändert sich.
Schnell-Orientierung für die nächste Claude-Session
Lies in dieser Reihenfolge:
docs/STATUS.md(5 min)docs/HANDOFF.md(= dieses Dokument)- Für CI-Themen:
docs/github-ci-setup.md - Für Pipeline-Fragen:
docs/superpowers/specs/2026-04-15-publish-pipeline-design.md
Dev-Kommandos
# SPA-Tests
cd app && npm run test:unit
cd app && npm run test:e2e
cd app && npm run check
cd app && npm run dev
# SPA-Build + Deploy
cd app && npm run build && cd .. && ./scripts/deploy-svelte.sh
# Publish-Pipeline
cd publish && deno task check # pre-flight
cd publish && deno task publish --dry-run # diff-modus simulation
cd publish && deno task publish # diff-modus echt
cd publish && deno task publish --force-all # alle posts
cd publish && deno task publish --post <slug> # einen post
cd publish && deno task test # 59 tests
Bekannte Stolperfallen
- Amber-Bunker: bei neuer Bunker-URL müssen die zwei Permissions
(
get_public_key,sign_event) in Amber auf „Allow + Always" gesetzt werden, bevor Publish-Requests verarbeitet werden. Siehedocs/github-ci-setup.mdfür Details. CLIENT_SECRET_HEXin.env.localidentisch mit GitHub-Secret — sorgt dafür, dass sich beide Umgebungen bei Amber mit derselben App anmelden. Rotieren nur bei bewusstem Neu-Pairing in Amber.relay.damus.iobestätigt Events manchmal nicht mitOK. Bekanntes Damus-Verhalten, wird toleriert (MIN_RELAY_ACKS=2, andere 4 Relays sind zuverlässig).- Svelte 5 Runes:
$props()-Werte via$derived()in lokale Variablen. - Hugo-quotierte Dates:
date: "2023-02-26"ist ein YAML-String, nicht ein Date-Objekt.validatePostcoerced das automatisch; in neuen Posts am besten ohne Quotes schreiben.
Offene UNKNOWN-Einträge zur späteren Recherche
Im VR-Post (content/posts/2021-08-15-virtual-reality/index.md) sind
4 Bilder als license: UNKNOWN / authors: UNKNOWN markiert:
01-immersion-wikipedia.jpg(Wikipedia-Screenshot)02-mittelalterliche-kirche.jpg(Sketchfab — Lizenz ist CC BY-NC, Fotograf fehlt)03-avatare-erstellen.jpg(Ready Player Me)05-pupillendistanz.jpg(EyeMeasure iOS App)
Pipeline loggt Warnungen, publisht aber trotzdem. Recherche-Notizen in
docs/redaktion-bild-metadaten.md.
Session-Kontext
Hilfreich beim Wiedereinstieg mit Claude:
- Branch-Check:
git log --oneline -10 spa main - Live-Check SPA:
curl -sI https://svelte.joerg-lohrer.de/ - Event-Count:
nak req -k 30023 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.primal.net 2>/dev/null | jq -s 'length'→ 18 - Pipeline-Tests:
cd publish && deno task test→ 59 grün
Community-Wiki-Entwürfe
Liegen im Repo, noch nicht extern veröffentlicht:
docs/wiki-entwurf-nostr-bild-metadaten.md— DEdocs/wiki-draft-nostr-image-metadata.md— EN
Können als NIP-Proposal oder auf nostrbook.dev eingebracht werden, jetzt wo die Konvention in der Praxis validiert ist.