docs: cutover dokumentiert, option A (repo/nostr-konflikt) priorisiert
- README: aktueller Live-Stand (SPA auf joerg-lohrer.de), CC0-Lizenz - STATUS: Cutover 2026-04-18 erfasst, Staging/Prod beide auf joerglohrer26/ - HANDOFF: Option A als priorisierter nächster Schritt — 9 verwaiste Nostr-Events mit problematischen d-tags (Emojis, Doppelpunkte, Umlaute, leerer d-tag) brauchen Markdown-Reimport + saubere Slugs + NIP-09-Cleanup Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
54eb0b62cb
commit
40785df346
87
README.md
87
README.md
|
|
@ -1,46 +1,97 @@
|
||||||
# joerg-lohrer.de
|
# joerg-lohrer.de
|
||||||
|
|
||||||
Persönliche Webseite. In Transition von einer Hugo-basierten, statischen Seite
|
Persönliche Webseite. Nach einer Transition von einer Hugo-basierten,
|
||||||
hin zu einer SvelteKit-SPA, die Blog-Posts live aus signierten Nostr-Events
|
statischen Seite läuft `joerg-lohrer.de` jetzt als SvelteKit-SPA, die
|
||||||
(NIP-23, `kind:30023`) rendert.
|
Blog-Posts live aus signierten Nostr-Events (NIP-23, `kind:30023`) rendert.
|
||||||
|
|
||||||
## Aktueller Stand
|
## Aktueller Stand
|
||||||
|
|
||||||
- **`https://joerg-lohrer.de/`** — Hugo-Seite, läuft noch.
|
- **`https://joerg-lohrer.de/`** — SvelteKit-SPA, Cutover am 2026-04-18 erfolgt.
|
||||||
- **`https://spa.joerg-lohrer.de/`** — Vanilla-HTML-Mini-Spike (Proof of Concept).
|
- **`https://staging.joerg-lohrer.de/`** — Staging (gleicher Build, ein Schritt vor Prod).
|
||||||
- **`https://svelte.joerg-lohrer.de/`** — produktive SvelteKit-SPA (Ziel).
|
- **`https://svelte.joerg-lohrer.de/`** — Entwicklungs-Deploy-Target der Pipeline.
|
||||||
|
- **`https://spa.joerg-lohrer.de/`** — Vanilla-HTML-Mini-Spike (Proof of Concept, historisch).
|
||||||
|
|
||||||
Detailliert in [`docs/STATUS.md`](docs/STATUS.md).
|
Detailliert in [`docs/STATUS.md`](docs/STATUS.md).
|
||||||
|
|
||||||
|
## Wie die Seite funktioniert
|
||||||
|
|
||||||
|
1. **Inhalte** liegen als Markdown in `content/posts/<slug>/index.md` mit
|
||||||
|
strukturierten Bild-Metadaten im Frontmatter (Alt-Text, Lizenz, Autor:innen).
|
||||||
|
2. **Publish-Pipeline** (`publish/`, Deno) lädt Bilder auf Blossom-Server
|
||||||
|
(content-addressed) und publiziert signierte `kind:30023`-Events via
|
||||||
|
NIP-46-Bunker (Amber) auf 5 Relays.
|
||||||
|
3. **SvelteKit-SPA** (`app/`) lädt diese Events zur Laufzeit und rendert
|
||||||
|
Post-Liste + Detailseiten. Keine Server-Komponente, Static-Hosting reicht.
|
||||||
|
4. **CI**: GitHub Actions triggert die Publish-Pipeline bei Push auf `main`
|
||||||
|
(via Forgejo→GitHub Push-Mirror).
|
||||||
|
|
||||||
|
Identität und Assets:
|
||||||
|
- **Pubkey:** `npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9`
|
||||||
|
- **NIP-05:** `joerglohrer@joerg-lohrer.de` (statisches `.well-known/nostr.json`)
|
||||||
|
- **Blossom-Server:** `blossom.edufeed.org`, `blossom.primal.net`
|
||||||
|
- **Relays:** `relay.damus.io`, `nos.lol`, `relay.primal.net`, `relay.tchncs.de`, `relay.edufeed.org`
|
||||||
|
|
||||||
## Navigation
|
## Navigation
|
||||||
|
|
||||||
- 📍 **Stand und Live-URLs:** [`docs/STATUS.md`](docs/STATUS.md)
|
- 📍 **Stand und Live-URLs:** [`docs/STATUS.md`](docs/STATUS.md)
|
||||||
- 🔜 **Wie es weitergeht:** [`docs/HANDOFF.md`](docs/HANDOFF.md)
|
- 🔜 **Wie es weitergeht:** [`docs/HANDOFF.md`](docs/HANDOFF.md)
|
||||||
- 📐 **SPA-Spec:** [`docs/superpowers/specs/2026-04-15-nostr-page-design.md`](docs/superpowers/specs/2026-04-15-nostr-page-design.md)
|
- 📐 **SPA-Spec:** [`docs/superpowers/specs/2026-04-15-nostr-page-design.md`](docs/superpowers/specs/2026-04-15-nostr-page-design.md)
|
||||||
- 📐 **Publish-Pipeline-Spec:** [`docs/superpowers/specs/2026-04-15-publish-pipeline-design.md`](docs/superpowers/specs/2026-04-15-publish-pipeline-design.md)
|
- 📐 **Publish-Pipeline-Spec:** [`docs/superpowers/specs/2026-04-15-publish-pipeline-design.md`](docs/superpowers/specs/2026-04-15-publish-pipeline-design.md)
|
||||||
|
- 📐 **Bild-Metadaten-Konvention:** [`docs/superpowers/specs/2026-04-16-image-metadata-convention.md`](docs/superpowers/specs/2026-04-16-image-metadata-convention.md)
|
||||||
- 🛠 **SvelteKit-SPA-Plan:** [`docs/superpowers/plans/2026-04-15-spa-sveltekit.md`](docs/superpowers/plans/2026-04-15-spa-sveltekit.md) (35 Tasks, abgeschlossen)
|
- 🛠 **SvelteKit-SPA-Plan:** [`docs/superpowers/plans/2026-04-15-spa-sveltekit.md`](docs/superpowers/plans/2026-04-15-spa-sveltekit.md) (35 Tasks, abgeschlossen)
|
||||||
|
- 🛠 **Publish-Pipeline-Plan:** [`docs/superpowers/plans/2026-04-16-publish-pipeline.md`](docs/superpowers/plans/2026-04-16-publish-pipeline.md) (24 Tasks, abgeschlossen)
|
||||||
- 🤖 **Claude-Workflow-Skill:** [`.claude/skills/joerglohrerde-workflow.md`](.claude/skills/joerglohrerde-workflow.md)
|
- 🤖 **Claude-Workflow-Skill:** [`.claude/skills/joerglohrerde-workflow.md`](.claude/skills/joerglohrerde-workflow.md)
|
||||||
|
|
||||||
## Branches
|
## Branches
|
||||||
|
|
||||||
- **`main`** — kanonisch (Content, Specs, Pläne, Deploy-Scripts, Skill).
|
- **`main`** — kanonisch. Seit Cutover (2026-04-18) Produktions-Quelle.
|
||||||
- **`spa`** — aktueller Arbeitszweig mit allen SvelteKit-Commits. Wird beim
|
- **`spa`** — historischer SvelteKit-Arbeitszweig, inzwischen gemerged.
|
||||||
Cutover nach `main` gemerged.
|
|
||||||
- **`hugo-archive`** — eingefrorener Hugo-Zustand als Orphan-Branch.
|
- **`hugo-archive`** — eingefrorener Hugo-Zustand als Orphan-Branch.
|
||||||
Rollback über `git checkout hugo-archive && hugo build`.
|
Rollback-Option über `git checkout hugo-archive && hugo build`.
|
||||||
|
|
||||||
## Repo-Struktur
|
## Repo-Struktur
|
||||||
|
|
||||||
```
|
```
|
||||||
content/posts/ Markdown-Posts (Quelle für Nostr-Events)
|
content/posts/ Markdown-Posts (Quelle für Nostr-Events, 18 Stück)
|
||||||
app/ SvelteKit-SPA (Ziel-Implementation)
|
content/impressum.md Statisches Impressum (wird von SPA geladen)
|
||||||
preview/spa-mini/ Vanilla-HTML-Mini-Spike (Referenz)
|
app/ SvelteKit-SPA (Laufzeit-Renderer)
|
||||||
scripts/deploy-svelte.sh FTPS-Deploy nach svelte.joerg-lohrer.de
|
publish/ Deno-Publish-Pipeline (Blossom + Nostr)
|
||||||
static/ Site-Assets (Favicons, Profilbild)
|
preview/spa-mini/ Vanilla-HTML-Mini-Spike (historische Referenz)
|
||||||
docs/ Specs, Pläne, Status, Handoff
|
scripts/deploy-svelte.sh FTPS-Deploy, Targets: svelte/staging/prod
|
||||||
.claude/ Claude-Code-Sessions (transparenz) + Skills
|
static/ Site-Assets (Favicons, Profilbild, .well-known/)
|
||||||
|
docs/ Specs, Pläne, Status, Handoff, Wiki-Entwürfe
|
||||||
|
.github/workflows/ GitHub-Actions CI (Publish-Pipeline-Trigger)
|
||||||
|
.claude/ Claude-Code-Sessions (Transparenz) + Skills
|
||||||
|
```
|
||||||
|
|
||||||
|
## Entwicklung
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# SPA lokal
|
||||||
|
cd app && npm run dev
|
||||||
|
|
||||||
|
# SPA testen
|
||||||
|
cd app && npm run test:unit
|
||||||
|
cd app && npm run test:e2e
|
||||||
|
cd app && npm run check
|
||||||
|
|
||||||
|
# Publish-Pipeline
|
||||||
|
cd publish && deno task check # pre-flight
|
||||||
|
cd publish && deno task publish --dry-run # Simulation
|
||||||
|
cd publish && deno task publish # diff-modus echt
|
||||||
|
cd publish && deno task publish --post <slug> # ein Post
|
||||||
|
cd publish && deno task test # Tests
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
DEPLOY_TARGET=staging ./scripts/deploy-svelte.sh
|
||||||
|
DEPLOY_TARGET=prod ./scripts/deploy-svelte.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Lizenz
|
## Lizenz
|
||||||
|
|
||||||
Siehe [LICENSE](LICENSE).
|
Inhalte: [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/deed.de)
|
||||||
|
(Namensnennung erwünscht, aber rechtlich nicht erforderlich), sofern nicht
|
||||||
|
anders vermerkt. Drittinhalte sind beim jeweiligen Bild mit Autor:innen und
|
||||||
|
Lizenz gekennzeichnet.
|
||||||
|
|
||||||
|
Code: siehe [LICENSE](LICENSE).
|
||||||
|
|
|
||||||
156
docs/HANDOFF.md
156
docs/HANDOFF.md
|
|
@ -5,87 +5,87 @@ Dieses Dokument sagt: was ist der Zustand, was wartet, wo liegen die Fäden.
|
||||||
|
|
||||||
## Zustand (Details in `STATUS.md`)
|
## Zustand (Details in `STATUS.md`)
|
||||||
|
|
||||||
**Die Nostr-Publish-Pipeline ist live.** Alle 18 Posts sind publiziert als
|
**Cutover am 2026-04-18 abgeschlossen.** `joerg-lohrer.de` läuft als
|
||||||
`kind:30023`-Events auf 5 Relays, 91 Bilder auf 2 Blossom-Servern. Die
|
SvelteKit-SPA, rendert 18 Nostr-Langform-Posts live aus 5 Relays, Bilder
|
||||||
SvelteKit-SPA unter `svelte.joerg-lohrer.de` rendert alles ordentlich.
|
auf 2 Blossom-Servern. Hugo-Altbestand liegt als `hugo-archive`-Branch
|
||||||
|
eingefroren.
|
||||||
|
|
||||||
**Das inhaltliche Kernziel des Gesamtprojekts ist damit erreicht.**
|
Der Rest sind Feinschliff-Aufgaben.
|
||||||
|
|
||||||
Der Rest sind Feinschliff- und Cutover-Aufgaben.
|
## Was als Nächstes ansteht (priorisiert)
|
||||||
|
|
||||||
## Was als Nächstes ansteht
|
### Option A — Repo/Nostr-Konflikt-Management (priorisiert)
|
||||||
|
|
||||||
### Option 1 — CI-Push-Auto-Trigger verifizieren (optional)
|
**Warum jetzt:** Es gibt **9 Langform-Events auf Nostr, die keine
|
||||||
|
Markdown-Entsprechung im Repo haben** — alle via Client (Habla / Yakihonne)
|
||||||
|
direkt auf Nostr erstellt, zum Teil mit problematischen d-tags (Emojis,
|
||||||
|
Doppelpunkte, Umlaute, Trailing-Dashes, oder leer).
|
||||||
|
|
||||||
**Status:** Workflow-Manual-Trigger ist grün (Run #1 am 18.04.2026).
|
**Liste der verwaisten Nostr-Events** (d-tag → event-id-Prefix):
|
||||||
Automatischer Auto-Trigger bei Content-Push noch nicht ausprobiert —
|
|
||||||
kann jederzeit beiläufig mitgenommen werden:
|
|
||||||
|
|
||||||
1. Minimaler Edit in einem Post (z. B. Typo) → commit → push `main`
|
| d-tag | event-id | Probleme |
|
||||||
2. Forgejo synct automatisch zu GitHub → Workflow triggert → 1 Post als
|
|---|---|---|
|
||||||
`update` publiziert
|
| `richter-oder-rcher-banksy-als-moderner-prophet-vor-dem-high-court` | `bb2c2cea…` | Umlaut-Abdecker (`Rächer` → `rcher`) |
|
||||||
3. Log-Artefakt in GitHub Actions prüfen
|
| `die-kraft-der-gemeinschaft-wahre-strke-liegt-nicht-in-strukturen-sondern-in-prozessen` | `27d7fbee…` | Umlaut-Abdecker (`Stärke` → `strke`) |
|
||||||
|
| `nostr-und-open-educational-practices-oep-` | `0baa3615…` | Trailing-Dash, unschön |
|
||||||
|
| `religionsbezogene-bildung-mit-rollenkarten:-ki-bilder-als-impulsgeber` | `3ac719ca…` | `:` ungültig für URL-Slug |
|
||||||
|
| `📢-empowering-learners-for-the-age-of-ai-–-der-neue-review-draft-des-ai-literacy-frameworks-für-schule-ist-da!` | `3c005996…` | Emoji + `!` + Umlaute + extrem lang |
|
||||||
|
| `🟠-prompts-für-die-religionsbezogene-bildung-posten-und-diskutieren-auf-nostr` | `f726fcd5…` | Emoji + Umlaute |
|
||||||
|
| `ki-mitmachen` | `a1368d2e…` | sauber, aber fehlt im Repo |
|
||||||
|
| `bibel-selfies` | `00cbe5f3…` | Langform-Version; Duplikat mit Unix-Timestamp wurde bereits gelöscht |
|
||||||
|
| `""` (leer!) | `d75857dc…` | leerer d-tag — SPA-kritisch, Event hat keinen Slug |
|
||||||
|
|
||||||
Kein Ziel mehr, nur Bestätigung. Pipeline ist funktional vollständig.
|
**Zielbild:** Repo ist die Quelle der Wahrheit. Jeder Post existiert als
|
||||||
|
Markdown mit sauberem Slug. d-tags sind URL-freundlich (ASCII, keine
|
||||||
|
Sonderzeichen außer `-`).
|
||||||
|
|
||||||
### Option 2 — Cutover auf `joerg-lohrer.de`
|
**Empfohlener Flow (Reihenfolge nicht tauschen!):**
|
||||||
|
|
||||||
**Voraussetzung:** Option 1 optional, aber nicht blockierend. Die Pipeline
|
1. **Content exportieren.** Pro Event: `nak req -i <event-id> <relay>` →
|
||||||
läuft ja schon, ob manuell oder via CI ist für den Cutover egal.
|
JSON mit Content + Tags. Manuell in neue Markdown-Datei umwandeln
|
||||||
|
(`content/posts/<YYYY-MM-DD>-<saubererslug>/index.md`). Titel,
|
||||||
|
published_at, ggf. summary und bestehende image-Tags übernehmen.
|
||||||
|
Bilder nach `images/` kopieren (falls noch erreichbar), sonst
|
||||||
|
Blossom-URLs im Markdown belassen und beim Publish neu hashen.
|
||||||
|
2. **Slugs bereinigen.** Neue, saubere, ASCII-only d-tags wählen. Doku
|
||||||
|
in `docs/redaktion-bild-metadaten.md` oder einem neuen
|
||||||
|
`docs/nostr-reimport-mapping.md` festhalten (alter d-tag → neuer slug).
|
||||||
|
3. **Neu publizieren.** `deno task publish --post <slug>` pro Datei.
|
||||||
|
Pipeline hasht Bilder zu Blossom, signiert mit stabiler Identität.
|
||||||
|
4. **Alte Events löschen** via NIP-09 (`kind:5`). Heute noch manuell per
|
||||||
|
`nak event -k 5 -t e=<old-event-id>`, siehe Option D. Oder: erst
|
||||||
|
Option D bauen, dann diesen Schritt per Pipeline-Subcommand.
|
||||||
|
5. **Verifikation.** Post-Count pro Relay checken, SPA-Post-Liste
|
||||||
|
visuell prüfen.
|
||||||
|
|
||||||
**Schritte:**
|
**Edge Cases:**
|
||||||
1. In All-Inkl KAS die Domain `joerg-lohrer.de` auf den SvelteKit-Webroot
|
- Das leere-d-tag-Event (`d75857dc…`): wenn es noch sinnvoller Content
|
||||||
umhängen (aktuell: `svelte.joerg-lohrer.de` → `/www/htdocs/v109928/joerglohrer28/`
|
ist, als neuer Post re-importieren. Sonst einfach löschen.
|
||||||
oder welcher Ordner auch immer).
|
- Bilder in alten Events zeigen auf externe Server (nicht Blossom). Beim
|
||||||
2. SvelteKit-SPA deployen, sofern sie nicht schon dort liegt.
|
Re-Publish lädt die Pipeline sie herunter und hasht sie neu. Wenn die
|
||||||
3. Live-Check: `curl -sI https://joerg-lohrer.de/` → sollte die neue SPA
|
Quelle tot ist, muss das Bild manuell beschafft oder der Post mit
|
||||||
liefern, nicht mehr Hugo.
|
Platzhalter markiert werden.
|
||||||
|
- `relay.damus.io` liefert mehr Events als andere Relays — bei
|
||||||
|
Nicht-Auffindbarkeit auf anderen Relays trotzdem löschen, damus.io
|
||||||
|
respektiert den NIP-09.
|
||||||
|
|
||||||
Hugo-Altbestand bleibt als Archiv im `hugo-archive`-Branch.
|
### Option B — SPA respektiert NIP-09-Deletion-Events
|
||||||
|
|
||||||
### 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 im `content/`-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
|
**Status:** aktuell filtert die SPA nicht nach NIP-09. Wenn ein Event per
|
||||||
`kind:5`-Referenz gelöscht wurde (z. B. `7f5d08b8…` deletet `89609df5…`
|
`kind:5`-Referenz gelöscht wurde, zeigen Relays es meist nicht mehr aus —
|
||||||
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.
|
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
|
**Zu tun:** im `kind:30023`-Loader (`app/src/lib/nostr/…`) einen
|
||||||
Cross-Check auf `kind:5`-Events einbauen. Events, deren Addressable-Pointer
|
Cross-Check auf `kind:5`-Events einbauen. Events, deren Addressable-Pointer
|
||||||
(`30023:pubkey:d-tag`) in einem `kind:5` referenziert ist, werden
|
(`30023:pubkey:d-tag`) in einem `kind:5` referenziert ist, werden
|
||||||
gefiltert. Defensive Maßnahme für zukünftige Duplikate / Soft-Deletes.
|
gefiltert. Defensive Maßnahme für zukünftige Duplikate / Soft-Deletes.
|
||||||
|
|
||||||
### Option 5 — Repo/Nostr-Konflikt-Management
|
### Option C — Postfach `webmaster@joerg-lohrer.de`
|
||||||
|
|
||||||
**Warum:** aktuell ist die Pipeline eine einseitige Straße — Repo → Nostr.
|
User-Task: im All-Inkl KAS als Weiterleitung anlegen. Der Link im
|
||||||
Wenn du via Client (Habla, Yakihonne, Amber) auf Nostr editierst,
|
Footer und in den Social-Icons zeigt bereits darauf.
|
||||||
überschreibt der nächste Pipeline-Lauf deine Client-Edits mit dem (alten)
|
|
||||||
Repo-State. Das ist ein echter Datenverlust-Risikofaktor.
|
|
||||||
|
|
||||||
**Zu tun:**
|
### Option D — NIP-09-Delete als Pipeline-Subcommand
|
||||||
- **Defensiv (`created_at`-Check):** Pipeline liest vor Publish das
|
|
||||||
aktuelle Event vom Relay und vergleicht `created_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-
|
**Status:** heute einmalig per `nak event -k 5 …` mit neu erzeugter Bunker-
|
||||||
URL erledigt (Duplikat `1744905463975`). Das war ein Workaround um das
|
URL erledigt (Duplikat `1744905463975`). Das war ein Workaround um das
|
||||||
|
|
@ -100,9 +100,10 @@ deno task publish-delete --slug <slug>
|
||||||
deno task publish-delete --event-id <hex>
|
deno task publish-delete --event-id <hex>
|
||||||
```
|
```
|
||||||
|
|
||||||
Jetzt nicht dringend — nur bauen, wenn der Fall öfter eintritt.
|
**Sinnvollerweise mit Option A kombinieren** — in der Re-Import-Kampagne
|
||||||
|
werden 9 NIP-09 hintereinander gebraucht.
|
||||||
|
|
||||||
### Option 7 — Pipeline weg von GitHub (self-hosted CI)
|
### Option E — Pipeline weg von GitHub (self-hosted CI)
|
||||||
|
|
||||||
**Wann:** Wenn der Optiplex-Server steht und ein zentraler Ort für Dienste
|
**Wann:** Wenn der Optiplex-Server steht und ein zentraler Ort für Dienste
|
||||||
existiert.
|
existiert.
|
||||||
|
|
@ -116,6 +117,17 @@ existiert.
|
||||||
Der Pipeline-Code selbst (`publish/src/**`) ist CI-agnostisch — nur die
|
Der Pipeline-Code selbst (`publish/src/**`) ist CI-agnostisch — nur die
|
||||||
Trigger-Konfiguration ändert sich.
|
Trigger-Konfiguration ändert sich.
|
||||||
|
|
||||||
|
### Option F — Design-Refinements
|
||||||
|
|
||||||
|
**Wann:** irgendwann, wenn Lust drauf ist.
|
||||||
|
|
||||||
|
- Parallax-Effekte, Animations
|
||||||
|
- Dark-Mode-Feinschliff (aktuell `prefers-color-scheme`, könnte Toggle bekommen)
|
||||||
|
- Typografie-Experimente (Variable Fonts?)
|
||||||
|
- Bildergalerie-Komponente für Posts mit vielen Bildern
|
||||||
|
|
||||||
|
Alles nicht-blockierend, die SPA funktioniert solide.
|
||||||
|
|
||||||
## Schnell-Orientierung für die nächste Claude-Session
|
## Schnell-Orientierung für die nächste Claude-Session
|
||||||
|
|
||||||
Lies in dieser Reihenfolge:
|
Lies in dieser Reihenfolge:
|
||||||
|
|
@ -134,7 +146,8 @@ cd app && npm run check
|
||||||
cd app && npm run dev
|
cd app && npm run dev
|
||||||
|
|
||||||
# SPA-Build + Deploy
|
# SPA-Build + Deploy
|
||||||
cd app && npm run build && cd .. && ./scripts/deploy-svelte.sh
|
DEPLOY_TARGET=staging ./scripts/deploy-svelte.sh
|
||||||
|
DEPLOY_TARGET=prod ./scripts/deploy-svelte.sh
|
||||||
|
|
||||||
# Publish-Pipeline
|
# Publish-Pipeline
|
||||||
cd publish && deno task check # pre-flight
|
cd publish && deno task check # pre-flight
|
||||||
|
|
@ -142,7 +155,7 @@ cd publish && deno task publish --dry-run # diff-modus simulation
|
||||||
cd publish && deno task publish # diff-modus echt
|
cd publish && deno task publish # diff-modus echt
|
||||||
cd publish && deno task publish --force-all # alle posts
|
cd publish && deno task publish --force-all # alle posts
|
||||||
cd publish && deno task publish --post <slug> # einen post
|
cd publish && deno task publish --post <slug> # einen post
|
||||||
cd publish && deno task test # 59 tests
|
cd publish && deno task test # tests
|
||||||
```
|
```
|
||||||
|
|
||||||
## Bekannte Stolperfallen
|
## Bekannte Stolperfallen
|
||||||
|
|
@ -161,6 +174,9 @@ cd publish && deno task test # 59 tests
|
||||||
- **Hugo-quotierte Dates:** `date: "2023-02-26"` ist ein YAML-String, nicht
|
- **Hugo-quotierte Dates:** `date: "2023-02-26"` ist ein YAML-String, nicht
|
||||||
ein Date-Objekt. `validatePost` coerced das automatisch; in neuen Posts
|
ein Date-Objekt. `validatePost` coerced das automatisch; in neuen Posts
|
||||||
am besten ohne Quotes schreiben.
|
am besten ohne Quotes schreiben.
|
||||||
|
- **Deploy-Targets:** `svelte` → Entwicklung, `staging` → Pre-Prod,
|
||||||
|
`prod` → `joerglohrer26/` (Produktion seit Cutover). Script parst
|
||||||
|
`.env.local` per awk (wegen Sonderzeichen in FTP-Passwörtern).
|
||||||
|
|
||||||
## Offene UNKNOWN-Einträge zur späteren Recherche
|
## Offene UNKNOWN-Einträge zur späteren Recherche
|
||||||
|
|
||||||
|
|
@ -177,10 +193,14 @@ Pipeline loggt Warnungen, publisht aber trotzdem. Recherche-Notizen in
|
||||||
## Session-Kontext
|
## Session-Kontext
|
||||||
|
|
||||||
Hilfreich beim Wiedereinstieg mit Claude:
|
Hilfreich beim Wiedereinstieg mit Claude:
|
||||||
- Branch-Check: `git log --oneline -10 spa main`
|
- Branch-Check: `git log --oneline -10 main`
|
||||||
- Live-Check SPA: `curl -sI https://svelte.joerg-lohrer.de/`
|
- Live-Check: `curl -sI https://joerg-lohrer.de/`
|
||||||
- Event-Count: `nak req -k 30023 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.primal.net 2>/dev/null | jq -s 'length'` → 18
|
- Event-Count Repo vs. Relays:
|
||||||
- Pipeline-Tests: `cd publish && deno task test` → 59 grün
|
```sh
|
||||||
|
ls content/posts/ | wc -l
|
||||||
|
nak req -k 30023 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.edufeed.org 2>/dev/null | jq -s 'length'
|
||||||
|
```
|
||||||
|
- Pipeline-Tests: `cd publish && deno task test`
|
||||||
|
|
||||||
## Community-Wiki-Entwürfe
|
## Community-Wiki-Entwürfe
|
||||||
|
|
||||||
|
|
|
||||||
158
docs/STATUS.md
158
docs/STATUS.md
|
|
@ -1,63 +1,63 @@
|
||||||
# Projekt-Status: joerg-lohrer.de → Nostr-basierte SPA
|
# Projekt-Status: joerg-lohrer.de → Nostr-basierte SPA
|
||||||
|
|
||||||
**Stand:** 2026-04-18
|
**Stand:** 2026-04-18 (Cutover abgeschlossen)
|
||||||
|
|
||||||
## Kurzfassung
|
## Kurzfassung
|
||||||
|
|
||||||
Jörg Lohrers persönliche Webseite wird von einem Hugo-basierten statischen
|
`joerg-lohrer.de` läuft als SvelteKit-SPA, die Blog-Posts live aus
|
||||||
Site-Generator zu einer dezentralen Nostr-basierten SPA überführt. Posts
|
signierten Nostr-Events (NIP-23, `kind:30023`) auf 5 Public-Relays rendert.
|
||||||
existieren als signierte Events (NIP-23, `kind:30023`) auf Public-Relays und
|
Bilder liegen content-addressed auf 2 Blossom-Servern. Die Hugo-basierte
|
||||||
werden zur Laufzeit im Browser gerendert.
|
Altseite ist als `hugo-archive`-Branch eingefroren.
|
||||||
|
|
||||||
## Vier parallele Webseiten
|
**Das inhaltliche Kernziel des Gesamtprojekts ist erreicht.**
|
||||||
|
|
||||||
|
## Live-URLs
|
||||||
|
|
||||||
| URL | Status | Rolle |
|
| URL | Status | Rolle |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `https://joerg-lohrer.de/` | live, unverändert | **Hugo-Altbestand** (bleibt bis Cutover) |
|
| `https://joerg-lohrer.de/` | live | **Produktion**, SvelteKit-SPA (Cutover 2026-04-18) |
|
||||||
| `https://spa.joerg-lohrer.de/` | live | **Vanilla-HTML-Mini-Spike** (Proof of Concept) |
|
| `https://staging.joerg-lohrer.de/` | live | **Staging**, letzter Pre-Prod-Build |
|
||||||
| `https://svelte.joerg-lohrer.de/` | live | **SvelteKit-SPA** (35-Task-Plan komplett) |
|
| `https://svelte.joerg-lohrer.de/` | live | **Entwicklung**, Deploy-Target der Pipeline |
|
||||||
| `https://staging.joerg-lohrer.de/` | live, leer | **Staging** (Webroot `joerglohrer26/` für Pipeline-Entwicklung; FTP-Creds in `.env.local`) |
|
| `https://spa.joerg-lohrer.de/` | live | **Historisch**, Vanilla-HTML-Mini-Spike |
|
||||||
|
|
||||||
Die SvelteKit-SPA unter `svelte.joerg-lohrer.de` ist die Ziel-Implementierung.
|
|
||||||
`spa.joerg-lohrer.de` bleibt als schlanke Referenz erhalten. Hugo läuft weiter,
|
|
||||||
bis die Publish-Pipeline steht und der Cutover auf die Hauptdomain erfolgt.
|
|
||||||
|
|
||||||
## Was auf Nostr liegt
|
## Was auf Nostr liegt
|
||||||
|
|
||||||
- **Autoren-Pubkey:** `npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9`
|
- **Autoren-Pubkey:** `npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9`
|
||||||
(hex: `4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41`)
|
(hex: `4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41`)
|
||||||
- **Publizierte Events:** **18 Langform-Posts** (`kind:30023`) — alle Altposts
|
- **NIP-05:** `joerglohrer@joerg-lohrer.de` (via `/.well-known/nostr.json`)
|
||||||
via Publish-Pipeline migriert (Commit `0c6fdd1`, Log in
|
- **Publizierte Events:** **18 Langform-Posts** (`kind:30023`) aus dem Repo,
|
||||||
`docs/publish-logs/2026-04-18-force-all-migration.json`).
|
plus **9 nicht-Repo-Events** (via Client wie Habla/Yakihonne erstellt,
|
||||||
|
siehe HANDOFF → Option 5 für Konflikt-Management-Plan).
|
||||||
- **Relay-Liste** (`kind:10002`): `relay.damus.io`, `nos.lol`,
|
- **Relay-Liste** (`kind:10002`): `relay.damus.io`, `nos.lol`,
|
||||||
`relay.primal.net`, `relay.tchncs.de`, `relay.edufeed.org`
|
`relay.primal.net`, `relay.tchncs.de`, `relay.edufeed.org`
|
||||||
- **Blossom-Server** (`kind:10063`): `blossom.edufeed.org`, `blossom.primal.net`
|
- **Blossom-Server** (`kind:10063`): `blossom.edufeed.org`, `blossom.primal.net`
|
||||||
|
- **91 Bilder** auf beiden Blossom-Servern, alle Events enthalten
|
||||||
**91 Bilder** auf beiden Blossom-Servern. Alle Events enthalten hash-basierte
|
hash-basierte Blossom-URLs.
|
||||||
Blossom-URLs. SPA rendert alle Posts einheitlich — kein Legacy-Pfad, keine
|
|
||||||
rsync-Artefakte.
|
|
||||||
|
|
||||||
## Repo-Struktur
|
## Repo-Struktur
|
||||||
|
|
||||||
```
|
```
|
||||||
joerglohrerde/
|
joerglohrerde/
|
||||||
├── content/posts/ # 18 Markdown-Posts, alle mit structured images: im Frontmatter
|
├── content/posts/ # 18 Markdown-Posts, alle mit strukturierten images:
|
||||||
├── app/ # SvelteKit-SPA (Ziel-Implementation)
|
├── content/impressum.md # Statisches Impressum (wird von SPA geladen)
|
||||||
├── preview/spa-mini/ # Vanilla-HTML-Mini-Spike (Referenz)
|
├── app/ # SvelteKit-SPA (Laufzeit-Renderer)
|
||||||
├── publish/ # NOCH NICHT ANGELEGT — Publish-Pipeline (Task 1 aus Plan)
|
├── publish/ # Deno-Publish-Pipeline (Blossom + Nostr)
|
||||||
|
├── preview/spa-mini/ # Vanilla-HTML-Mini-Spike (historisch)
|
||||||
├── scripts/
|
├── scripts/
|
||||||
│ └── deploy-svelte.sh # FTPS-Deploy nach svelte.joerg-lohrer.de
|
│ └── deploy-svelte.sh # FTPS-Deploy, Targets: svelte/staging/prod
|
||||||
├── docs/
|
├── docs/
|
||||||
│ ├── STATUS.md # Dieses Dokument
|
│ ├── STATUS.md # Dieses Dokument
|
||||||
│ ├── HANDOFF.md # Wie man hier weitermacht
|
│ ├── HANDOFF.md # Wie man hier weitermacht
|
||||||
│ ├── redaktion-bild-metadaten.md # Checkliste, Bild-Durchgang (abgearbeitet)
|
│ ├── redaktion-bild-metadaten.md
|
||||||
│ ├── wiki-entwurf-nostr-bild-metadaten.md # Wiki-Konvention deutsch
|
│ ├── wiki-entwurf-nostr-bild-metadaten.md
|
||||||
│ ├── wiki-draft-nostr-image-metadata.md # Wiki-Konvention englisch
|
│ ├── wiki-draft-nostr-image-metadata.md
|
||||||
|
│ ├── github-ci-setup.md
|
||||||
│ └── superpowers/
|
│ └── superpowers/
|
||||||
│ ├── specs/ # SPA + Publish-Pipeline + Bild-Metadaten-Konvention
|
│ ├── specs/ # SPA + Publish-Pipeline + Bild-Metadaten-Konvention
|
||||||
│ └── plans/
|
│ └── plans/
|
||||||
│ ├── 2026-04-15-spa-sveltekit.md # erledigt
|
│ ├── 2026-04-15-spa-sveltekit.md # erledigt
|
||||||
│ └── 2026-04-16-publish-pipeline.md # ⬅ als nächstes
|
│ └── 2026-04-16-publish-pipeline.md # erledigt
|
||||||
|
├── .github/workflows/ # publish.yml (Forgejo→GitHub Push-Mirror-Trigger)
|
||||||
├── .claude/
|
├── .claude/
|
||||||
│ ├── skills/ # Repo-spezifischer Claude-Skill
|
│ ├── skills/ # Repo-spezifischer Claude-Skill
|
||||||
│ └── settings.local.json # Claude-Session-State (gitignored)
|
│ └── settings.local.json # Claude-Session-State (gitignored)
|
||||||
|
|
@ -66,80 +66,78 @@ joerglohrerde/
|
||||||
|
|
||||||
## Branch-Layout (Git)
|
## Branch-Layout (Git)
|
||||||
|
|
||||||
- **`main`** — kanonischer Zweig.
|
- **`main`** — kanonischer Zweig, Produktions-Quelle seit Cutover.
|
||||||
- **`spa`** — aktueller Arbeits-Branch, vor `main`. SvelteKit-SPA live,
|
- **`spa`** — historischer SvelteKit-Arbeitszweig, gemerged.
|
||||||
Content-Migration (Bild-Metadaten) abgeschlossen, Publish-Pipeline geplant.
|
|
||||||
- **`hugo-archive`** — Orphan-Branch mit Hugo-Zustand, eingefroren.
|
- **`hugo-archive`** — Orphan-Branch mit Hugo-Zustand, eingefroren.
|
||||||
|
|
||||||
## Setup-Zustand
|
## Setup-Zustand
|
||||||
|
|
||||||
Einmalig manuell erledigt:
|
Einmalig manuell erledigt (gitignored in `.env.local`):
|
||||||
- ✅ Amber-Bunker-URL in `.env.local` als `BUNKER_URL`
|
- ✅ Amber-Bunker-URL als `BUNKER_URL`
|
||||||
- ✅ FTP-Creds für alle Subdomains (SPA, SVELTE, STAGING) in `.env.local`
|
- ✅ FTP-Creds für alle Targets (SVELTE/STAGING/PROD)
|
||||||
- ✅ `AUTHOR_PUBKEY_HEX` und `BOOTSTRAP_RELAY=wss://relay.primal.net` in `.env.local`
|
- ✅ `AUTHOR_PUBKEY_HEX` und `BOOTSTRAP_RELAY=wss://relay.primal.net`
|
||||||
|
- ✅ `CLIENT_SECRET_HEX` (identisch mit GitHub-Secret für stabile App-ID in Amber)
|
||||||
- ✅ `kind:10002`-Event publiziert (Relay-Liste)
|
- ✅ `kind:10002`-Event publiziert (Relay-Liste)
|
||||||
- ✅ `kind:10063`-Event publiziert (Blossom-Server)
|
- ✅ `kind:10063`-Event publiziert (Blossom-Server)
|
||||||
- ✅ Subdomains mit TLS + HSTS
|
- ✅ Subdomains mit TLS + HSTS
|
||||||
- ✅ Staging-Subdomain `staging.joerg-lohrer.de` → Webroot `joerglohrer26/`
|
- ✅ Staging → Webroot `joerglohrer26/`
|
||||||
|
- ✅ Prod → Webroot `joerglohrer26/` (Cutover 2026-04-18)
|
||||||
|
- ✅ NIP-05-JSON mit CORS-Header via `.htaccess`
|
||||||
|
|
||||||
Alles in `.env.local` — gitignored, nicht committet.
|
## Offene Punkte (Details in HANDOFF.md)
|
||||||
|
|
||||||
## Offene Punkte
|
Nach Priorität:
|
||||||
|
1. **Repo/Nostr-Konflikt-Management** — 9 verwaiste Nostr-Events haben
|
||||||
|
keine Markdown-Entsprechung. Geplanter Flow: Markdown nachziehen →
|
||||||
|
d-tags bereinigen → neu publizieren → alte löschen (NIP-09).
|
||||||
|
2. **Postfach `webmaster@joerg-lohrer.de`** als Weiterleitung in KAS anlegen.
|
||||||
|
3. **SPA respektiert NIP-09-Deletion-Events** (defensiver kind:5-Filter).
|
||||||
|
4. **NIP-09-Delete als Pipeline-Subcommand** (heute noch `nak event -k 5`).
|
||||||
|
5. **Self-hosted CI** (Woodpecker / Cron auf Optiplex), weg von GitHub.
|
||||||
|
6. **5 UNKNOWN-Einträge** im VR-Post zur späteren Recherche.
|
||||||
|
|
||||||
- **End-to-End-Test CI mit echtem Content-Push** (Workflow-Manual-Trigger
|
## Erledigt (chronologisch seit 2026-04-15)
|
||||||
ist grün; automatischer Auto-Trigger via Push-Mirror noch nicht real
|
|
||||||
ausprobiert).
|
|
||||||
- **Menü-Navigation** in der SPA (Home / Archiv / Impressum / Kontakt)
|
|
||||||
- **Impressum-Seite** (braucht rechtlichen Text)
|
|
||||||
- **Cutover auf `joerg-lohrer.de`** (Pipeline läuft, Voraussetzung erfüllt;
|
|
||||||
Hauptdomain kann auf SvelteKit-SPA umgestellt werden)
|
|
||||||
- **5 UNKNOWN-Einträge** im `virtual-reality`-Post zur späteren Recherche
|
|
||||||
(Wikipedia-Screenshot, Sketchfab-Fotograf, Ready-Player-Me, EyeMeasure-App)
|
|
||||||
- **CI-Migration** (später): weg von GitHub-Actions zu Woodpecker oder
|
|
||||||
Cron auf Optiplex — siehe `docs/github-ci-setup.md`.
|
|
||||||
|
|
||||||
## Erledigt seit 2026-04-15
|
|
||||||
|
|
||||||
- ✅ Content-Migration: alle 18 Posts haben strukturierte `images:`-Liste
|
- ✅ Content-Migration: alle 18 Posts haben strukturierte `images:`-Liste
|
||||||
im Frontmatter (91 Bilder, mit Alt-Text, Lizenz, Autor:innen, ggf. Caption
|
im Frontmatter (91 Bilder, mit Alt-Text, Lizenz, Autor:innen, ggf.
|
||||||
und Modifications). Commit `c023b59`.
|
Caption und Modifications).
|
||||||
- ✅ Erlebnispädagogik-Post: tote Amazon-Hotlinks entfernt.
|
|
||||||
- ✅ Spec, Plan und Bild-Metadaten-Konvention geschrieben.
|
- ✅ Spec, Plan und Bild-Metadaten-Konvention geschrieben.
|
||||||
- ✅ Community-Wiki-Entwürfe (DE + EN) für Nostr-Bildattribution.
|
- ✅ Community-Wiki-Entwürfe (DE + EN) für Nostr-Bildattribution.
|
||||||
- ✅ **Publish-Pipeline komplett implementiert**, 22 Tasks aus dem Plan:
|
- ✅ **Publish-Pipeline komplett implementiert** (24 Tasks, 59 Tests grün).
|
||||||
- 18 Code-Tasks (Phase 1–6), 59 Unit-Tests grün
|
- ✅ **Alle 18 Altposts publiziert** als `kind:30023`-Events.
|
||||||
- Stabile NIP-46-Anbindung via `CLIENT_SECRET_HEX` für wiederverwendbare
|
|
||||||
App-Identität in Amber
|
|
||||||
- `validatePost` akzeptiert auch string-dates (für Hugo-Kompatibilität)
|
|
||||||
- ✅ **Alle 18 Altposts publiziert** als `kind:30023`-Events (Commit `0c6fdd1`,
|
|
||||||
Log in `docs/publish-logs/2026-04-18-force-all-migration.json`).
|
|
||||||
- ✅ **91 Bilder** auf beiden Blossom-Servern.
|
- ✅ **91 Bilder** auf beiden Blossom-Servern.
|
||||||
- ✅ SPA rendert alle Posts mit Bildern von Blossom (visuell verifiziert).
|
- ✅ **GitHub-Actions-Workflow** + Forgejo→GitHub Push-Mirror + Secrets.
|
||||||
- ✅ **GitHub-Actions-Workflow** angelegt (`.github/workflows/publish.yml`).
|
- ✅ **Duplikat-Event via NIP-09 gelöscht** (`bibel-selfies` Unix-Timestamp-dup).
|
||||||
- ✅ Forgejo → GitHub Push-Mirror eingerichtet, GitHub-Secrets gesetzt.
|
- ✅ **Staging-Deploy-Infrastruktur** mit `__SITE_URL__`-Templating.
|
||||||
- ✅ **`spa` → `main` gemergt**, GitHub-Actions-Workflow manuell verifiziert
|
- ✅ **Homepage** mit Hero, Profilbild, Social-Icons (Nostr/Mastodon/
|
||||||
(Run #1: signer ok, outbox ok, blossom-liste ok, mode=diff posts=0).
|
Bluesky/LinkedIn/ORCID/Mail), Latest-Posts.
|
||||||
**Alle 24 Tasks des Publish-Pipeline-Plans abgeschlossen.**
|
- ✅ **Archiv-Seite**, **Impressum-Seite**, Menü-Navigation im Layout.
|
||||||
- ✅ **Staging-Deploy-Infrastruktur:** `scripts/deploy-svelte.sh` mit
|
- ✅ **CC0-Footer-Badge** (Heart+Zero inline SVG, monochrom).
|
||||||
drei Targets (`svelte`/`staging`/`prod`), dynamisches `og:url` und
|
- ✅ **Impressum auf CC0 umgestellt** (mit freundlichem Namensnennungs-Hinweis).
|
||||||
`canonical` via `__SITE_URL__`-Platzhalter. Staging-Subdomain
|
- ✅ **Cutover 2026-04-18** — `joerg-lohrer.de` von Hugo (`joerglohrer24/`)
|
||||||
`staging.joerg-lohrer.de` bedient jetzt `joerglohrer26/` (Cutover-Ziel).
|
auf SvelteKit-SPA (`joerglohrer26/`) umgehängt.
|
||||||
- ✅ **Duplikat-Event `1744905463975` via NIP-09 gelöscht** (Delete-Event
|
|
||||||
`7f5d08b8…`, auf alle 5 Relays). Nach Migration nicht mehr auffindbar.
|
|
||||||
|
|
||||||
## Live-Verifikation
|
## Live-Verifikation
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -sI https://svelte.joerg-lohrer.de/ | head -3
|
curl -sI https://joerg-lohrer.de/ | head -3
|
||||||
curl -sI https://staging.joerg-lohrer.de/ | head -3
|
curl -sI https://staging.joerg-lohrer.de/ | head -3
|
||||||
|
curl -s https://joerg-lohrer.de/.well-known/nostr.json | jq .
|
||||||
```
|
```
|
||||||
|
|
||||||
## Kontakt zur Implementierung
|
## Pipeline-Quick-Check
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Event-Count pro Relay
|
||||||
|
for r in wss://relay.damus.io wss://nos.lol wss://relay.primal.net wss://relay.tchncs.de wss://relay.edufeed.org; do
|
||||||
|
echo -n "$r: "; nak req -k 30023 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 $r 2>/dev/null | wc -l
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
## Design-Referenzen
|
||||||
|
|
||||||
Alle Design-Entscheidungen in:
|
|
||||||
- `docs/superpowers/specs/2026-04-15-nostr-page-design.md` (SPA)
|
- `docs/superpowers/specs/2026-04-15-nostr-page-design.md` (SPA)
|
||||||
- `docs/superpowers/specs/2026-04-15-publish-pipeline-design.md` (Publish, Blossom-only)
|
- `docs/superpowers/specs/2026-04-15-publish-pipeline-design.md` (Publish, Blossom-only)
|
||||||
- `docs/superpowers/specs/2026-04-16-image-metadata-convention.md` (Bild-Metadaten-YAML)
|
- `docs/superpowers/specs/2026-04-16-image-metadata-convention.md` (Bild-Metadaten-YAML)
|
||||||
- `docs/superpowers/plans/2026-04-16-publish-pipeline.md` (24 Tasks, als nächstes)
|
|
||||||
|
|
||||||
Für die nächste Session: **`docs/HANDOFF.md`** lesen.
|
Für die nächste Session: **`docs/HANDOFF.md`** lesen.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue