From 0a3bf026ff45a131e829325538932020d2c5b1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lohrer?= Date: Wed, 15 Apr 2026 18:34:15 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20handoff-pakette=20f=C3=BCr=20pause=20+?= =?UTF-8?q?=20sp=C3=A4tere=20fortsetzung?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docs/STATUS.md: was ist getan, was läuft live, wo liegen die Fäden - docs/HANDOFF.md: nächste Optionen (Publish-Pipeline, Menü, Cutover), Dev-Kommandos, bekannte Stolperfallen - .claude/skills/joerglohrerde-workflow.md: repo-spezifischer Skill zum Session-Start — Konventionen, API-Eigenheiten, wiederkehrende Kommandos, wie mit Jörg arbeiten - README.md als Navigation zu allen Dokumenten Damit kann die nächste Session ohne Kontextverlust fortgeführt werden. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/joerglohrerde-workflow.md | 180 +++++++++++++++++++++++ README.md | 52 ++++--- docs/HANDOFF.md | 140 ++++++++++++++++++ docs/STATUS.md | 105 +++++++++++++ 4 files changed, 457 insertions(+), 20 deletions(-) create mode 100644 .claude/skills/joerglohrerde-workflow.md create mode 100644 docs/HANDOFF.md create mode 100644 docs/STATUS.md diff --git a/.claude/skills/joerglohrerde-workflow.md b/.claude/skills/joerglohrerde-workflow.md new file mode 100644 index 0000000..56daa4c --- /dev/null +++ b/.claude/skills/joerglohrerde-workflow.md @@ -0,0 +1,180 @@ +--- +name: joerglohrerde-workflow +description: Repo-spezifischer Skill für joerglohrerde. Nutze ihn bei jedem Session-Start, um den aktuellen Zustand zu erfassen, Konventionen zu verstehen und wiederkehrende Workflows (Deploy, Publish, Tests) effizient auszuführen. +--- + +# joerglohrerde — Session-Skill + +Dieses Repo ist die persönliche Webseite von Jörg Lohrer — in Transition +von Hugo zu einer dezentralen Nostr-basierten SvelteKit-SPA. + +## Beim Session-Start IMMER zuerst + +1. **Lies `docs/STATUS.md`** — aktueller Projektstand, live-URLs, Branches. +2. **Lies `docs/HANDOFF.md`** — was wartet, nächste Schritte, Stolperfallen. +3. Bei konkreten Aufgaben: entsprechende Spec unter `docs/superpowers/specs/` + oder Plan unter `docs/superpowers/plans/`. +4. Branch-Zustand prüfen: `git log --oneline -10 spa main hugo-archive`. + +Dann erst Rückfragen oder Vorschläge formulieren. + +## Drei Live-Webseiten + +| URL | Inhalt | Wann anfassen | +|---|---|---| +| `joerg-lohrer.de` | Hugo-Seite (alt) | nur im finalen Cutover | +| `spa.joerg-lohrer.de` | Vanilla-Mini-Spike | als Referenz, aber nicht weiterentwickeln | +| `svelte.joerg-lohrer.de` | SvelteKit-SPA | **Haupt-Arbeitsziel** | + +## Git-Branches + +- `main` — kanonisch (Content, Specs, Pläne, Deploy-Scripts) +- `spa` — aktueller Arbeitszweig mit allen SvelteKit-Commits +- `hugo-archive` — Orphan, eingefrorener Hugo-Zustand + +Specs und Pläne gehören auf `main`; SvelteKit-Code auf `spa`. Typischer +Workflow: committe Spec-Updates auf `main`, merge `main` → `spa` um +sie überall zu haben. + +## Sprache und Ton + +- Antworten und Commit-Messages auf **Deutsch** (Kundensprache). +- Code-Kommentare auch auf Deutsch (wenn überhaupt). +- Identifier, Variablen, Funktionen auf **Englisch**. +- Kurz und konkret — Jörg ist technisch versiert, erwartet keine + Grundlagen-Erklärungen. + +## Kernkonventionen + +### Kanonisches URL-Schema + +- Post-URL ist **kurz**: `//` (z. B. `/dezentrale-oep-oer/`). +- Legacy-Hugo-URLs `/YYYY/MM/DD/.html/` werden per SvelteKit-Load + auf die kurze Form 301-redirected (Backlink-Kompatibilität). +- Tag-Route: `/tag//`. + +### Slug-Regel + +Alle Slugs sind lowercase (Frontmatter `slug:`). Commit `d17410f` hat das +normalisiert. Keine Runtime-Transformation, beim Publishen 1:1 übernehmen. + +### Nostr-Konstanten + +- Pubkey (hex): `4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41` +- npub: `npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9` +- Bootstrap-Relay: `wss://relay.damus.io` +- Vollständige Relay-Liste: aus `kind:10002` des Autors (on-the-fly). +- Blossom-Server: aus `kind:10063` des Autors. + +Zentralisiert in `app/src/lib/nostr/config.ts`. + +### Signing + +- **Im Browser (Kommentare):** NIP-07 via Extension (Alby, nos2x). +- **Aus der Kommandozeile (Publish):** NIP-46 via Amber-Bunker. Bunker-URL + in `.env.local` als `BUNKER_URL`. +- Privater Schlüssel **nie** im Repo, nie in CI-Secrets, nie in einer + Pipeline-Umgebung direkt. + +## Wiederkehrende Kommandos + +### SPA-Entwicklung + +```sh +cd app +npm run dev # Dev-Server localhost:5173 +npm run check # Type-Check (sollte 0 errors sein) +npm run test:unit # Vitest — aktuell 29 Tests +npm run test:e2e # Playwright — aktuell 3 Tests +npm run build # Prod-Build nach app/build/ +``` + +### Deploy nach `svelte.joerg-lohrer.de` + +```sh +cd app && npm run build && cd .. +./scripts/deploy-svelte.sh +``` + +Das Script: +- liest `SVELTE_FTP_*` aus `.env.local` +- uploaded `app/build/*` per FTPS (TLS 1.2-Cap wegen All-Inkl-Bug) +- checkt `HTTP/2 200` am Ende + +### Manuelles Publishen eines Posts (bis Publish-Pipeline fertig ist) + +Siehe `docs/HANDOFF.md` Abschnitt „Manuelles Publishen". Kurz: +- Body aus Markdown-Frontmatter extrahieren (awk-Pattern dort) +- Bilder zu Blossom: `nak blossom upload --server https://blossom.edufeed.org --sec "$BUNKER_URL" ` +- Event bauen mit `nak event -k 30023 -d -t title=... ...` +- Push zu allen Relays + +### Nostr-Status checken + +```sh +# Alle publizierten kind:30023-Events des Autors +nak req -k 30023 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.damus.io 2>/dev/null | jq -c '{d: (.tags[] | select(.[0]=="d") | .[1]), title: (.tags[] | select(.[0]=="title") | .[1])}' + +# kind:10002 (Relay-Liste) +nak req -k 10002 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.damus.io + +# kind:10063 (Blossom-Liste) +nak req -k 10063 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.damus.io +``` + +## Tech-Stack-Eigenheiten, die man kennen muss + +1. **Svelte 5 Runes:** `$props()`-Werte müssen via `$derived()` in lokale + Variablen abgeleitet werden — sonst `state_referenced_locally`-Warning. + +2. **applesauce-relay v5.x API:** RxJS-basiert. `pool.request(relays, filter)` + liefert `Observable`. Die Loader in `app/src/lib/nostr/loaders.ts` + nutzen `toArray() + lastValueFrom + timeout + catchError`-Pattern. + **Nicht** das Tupel-Pattern `msg[0] === 'EVENT'` — das gehört in + alte nostr-tools-Beispiele, nicht hierher. + +3. **DOMPurify braucht DOM:** im `renderMarkdown`-Helper gibt es einen + Early-Fail-Guard für Node-Aufrufe (SSR ist ohnehin aus). + +4. **All-Inkl-FTPS-Bug:** Data-Connection bricht bei TLS 1.3 ab. + `--tls-max 1.2` im curl-Call. Sobald SSH auf All-Inkl verfügbar ist + (Premium-Tarif angefragt), wird das Deploy-Script auf rsync umgestellt. + +5. **Amber-Bunker-Session:** bei neuer Bunker-URL müssen globale + Permissions in Amber zurückgesetzt werden. Sonst hängt `nak event` + auf die Signatur-Response. + +## Was nicht in Scope ist (laut Plan/Specs) + +- Impressum-Inhalt (rechtliche Texte) +- Meta-Stubs pro Post (kommt via Publish-Pipeline Phase 3) +- Menü-Navigation (einfach nachrüstbar, aber nicht priorisiert) +- Eigener Relay (ideologischer Evolutionspfad, nicht Phase 1) +- Eigener Blossom-Server (dito) + +## Wie mit Jörg arbeiten + +- **Kurze Antworten**, konkrete Optionen, nicht lang umherreden. +- Bei mehreren Wegen: 2–3 Varianten mit Empfehlung nennen, nicht alles + aufzählen. +- Commit-Nachrichten: imperativ, auf Deutsch, mit Kontext im Body. + Co-Author: `Co-Authored-By: Claude Opus 4.6 (1M context) `. +- Vor dem Dispatchen von Subagents: kritische API-Details der Libraries + manuell verifizieren (Plan-Annahmen können alte Versionsstände + widerspiegeln). Beispiel: applesauce-relay API war nicht so wie im Plan + beschrieben — Subagent mit aktueller API briefen statt blind vertrauen. +- Nach jedem Feature-Commit: Build + Deploy, damit Jörg live sehen kann. + Das ist in diesem Workflow wichtig, weil UI-Feedback oft Layout-Fragen + aufwirft, die kein Test entdeckt. + +## Credentials / Secrets + +Alle in `.env.local` (gitignored). Variablen: +- `BUNKER_URL` — Amber-NIP-46-Pairing für Signaturen +- `SPA_FTP_HOST/USER/PASS/REMOTE_PATH` — FTPS nach spa.joerg-lohrer.de +- `SVELTE_FTP_HOST/USER/PASS/REMOTE_PATH` — FTPS nach svelte.joerg-lohrer.de + +Falls neue Bunker-URL nötig (Amber-Session kaputt): +- In Amber neue Bunker-URL generieren +- In `.env.local` ersetzen +- In Amber globale Permissions für die App löschen, sonst hängt der Request diff --git a/README.md b/README.md index a563ef9..dda87cb 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,44 @@ # joerg-lohrer.de -Persönliche Webseite. Befindet sich in der Transition von einer Hugo-basierten, -statischen Seite hin zu einer SvelteKit-SPA, die Blog-Posts live aus signierten -Nostr-Events (NIP-23, `kind:30023`) rendert. +Persönliche Webseite. In Transition von einer Hugo-basierten, statischen Seite +hin zu einer SvelteKit-SPA, die Blog-Posts live aus signierten Nostr-Events +(NIP-23, `kind:30023`) rendert. + +## Aktueller Stand + +- **`https://joerg-lohrer.de/`** — Hugo-Seite, läuft noch. +- **`https://spa.joerg-lohrer.de/`** — Vanilla-HTML-Mini-Spike (Proof of Concept). +- **`https://svelte.joerg-lohrer.de/`** — produktive SvelteKit-SPA (Ziel). + +Detailliert in [`docs/STATUS.md`](docs/STATUS.md). + +## Navigation + +- 📍 **Stand und Live-URLs:** [`docs/STATUS.md`](docs/STATUS.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) +- 📐 **Publish-Pipeline-Spec:** [`docs/superpowers/specs/2026-04-15-publish-pipeline-design.md`](docs/superpowers/specs/2026-04-15-publish-pipeline-design.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) +- 🤖 **Claude-Workflow-Skill:** [`.claude/skills/joerglohrerde-workflow.md`](.claude/skills/joerglohrerde-workflow.md) ## Branches -- **`main`** — aktuelle Arbeit. Enthält Markdown-Content (`content/posts/`), - Specs (`docs/`), Assets (`static/`) und wird im Lauf der Migration um die - SvelteKit-SPA und das Publish-Skript erweitert. -- **`spa`** — Feature-Branch für die SvelteKit-SPA-Entwicklung. Wird bei +- **`main`** — kanonisch (Content, Specs, Pläne, Deploy-Scripts, Skill). +- **`spa`** — aktueller Arbeitszweig mit allen SvelteKit-Commits. Wird beim Cutover nach `main` gemerged. -- **`hugo-archive`** — eingefrorener Zustand der alten Hugo-Seite als - Orphan-Branch (ein Commit ohne Historie). Nicht mehr weiterentwickelt. - Wiederherstellbar über `git checkout hugo-archive && hugo build`. +- **`hugo-archive`** — eingefrorener Hugo-Zustand als Orphan-Branch. + Rollback über `git checkout hugo-archive && hugo build`. -## Spec - -Architektur und Design-Entscheidungen: -[`docs/superpowers/specs/2026-04-15-nostr-page-design.md`](docs/superpowers/specs/2026-04-15-nostr-page-design.md) - -## Struktur auf `main` +## Repo-Struktur ``` -content/posts/ Markdown-Posts (Quelle für Nostr-Events) -static/ Site-Assets (Favicons, Profilbild) -docs/ Specs und Architektur-Dokumentation -.claude/ Claude-Code-Sessions (als Transparenz-Spur) +content/posts/ Markdown-Posts (Quelle für Nostr-Events) +app/ SvelteKit-SPA (Ziel-Implementation) +preview/spa-mini/ Vanilla-HTML-Mini-Spike (Referenz) +scripts/deploy-svelte.sh FTPS-Deploy nach svelte.joerg-lohrer.de +static/ Site-Assets (Favicons, Profilbild) +docs/ Specs, Pläne, Status, Handoff +.claude/ Claude-Code-Sessions (transparenz) + Skills ``` ## Lizenz diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md new file mode 100644 index 0000000..06fadf1 --- /dev/null +++ b/docs/HANDOFF.md @@ -0,0 +1,140 @@ +# 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 (siehe `STATUS.md` für Details) + +Die SvelteKit-SPA unter `svelte.joerg-lohrer.de` ist **fertig und live**. +35 geplante Tasks + einige Erweiterungen abgeschlossen. Branch `spa` hat +alle Commits. Ein Git-Merge nach `main` und Deploy auf die Hauptdomain ist +**noch nicht** erfolgt — das kommt erst nach dem Cutover-Plan. + +## Was als Nächstes ansteht + +Drei Optionen, ordered by natürlichkeit der Fortsetzung: + +### Option 1 — Publish-Pipeline bauen + +**Warum:** aktuell muss Jörg jeden neuen Post manuell mit `nak event` signieren +und publishen (siehe `preview/spa-mini/README.md`, Referenzbefehl in den +Brainstorm-Notizen). Eine Publish-Pipeline automatisiert: + +1. Markdown-Post in `content/posts/` bearbeiten / neu anlegen +2. Git-Commit + push auf `main` +3. GitHub Action signiert Event via NIP-46 (Amber-Bunker), pushed zu allen + Relays aus `kind:10002`, lädt Bilder zu Blossom, lädt Altbild-Assets + ggf. zu All-Inkl via SSH/rsync. + +**Was existiert:** Spec vollständig unter +`docs/superpowers/specs/2026-04-15-publish-pipeline-design.md`. Plan +**noch nicht geschrieben.** + +**Nächster Konkreter Schritt:** +``` +superpowers:writing-plans +``` +mit dem Publish-Spec als Input. + +**Vorarbeiten:** +- SSH-Zugang zu All-Inkl klären (Premium-Tarif angefragt, Status prüfen) +- Deno ≥ 2.x installiert? +- GitHub Actions-Repo-Secrets vorbereiten (`BUNKER_URL`, `ALLINKL_DEPLOY_ROOT`, + `SSH_DEPLOY_KEY`, `AUTHOR_PUBKEY_HEX`) + +### Option 2 — Menü-Navigation + Impressum auf der SPA + +**Warum:** kleine UX-Ergänzung, die das SPA-Erlebnis runder macht. + +- Header-Navigation in `app/src/routes/+layout.svelte` ergänzen (Home, Archiv, + Impressum, evtl. Mastodon-Link) +- `/impressum/`-Route anlegen mit rechtlichem Text +- ggf. Archives-Route als eigene Liste mit Gruppierung nach Jahr + +**Aufwand:** ~30-60 min je nach Layout-Wunsch. Kein Spec-Update nötig, +ist in SPA-Spec §2 bereits als Ziel erwähnt. + +### Option 3 — Cutover auf Hauptdomain + +**Warum:** `joerg-lohrer.de` liefert aktuell noch Hugo aus. Sobald genug +Altposts als Events publiziert sind und die Publish-Pipeline läuft, kann die +SvelteKit-SPA auf die Hauptdomain umziehen. Das ist aber **kein Task jetzt** +— muss auf Publish-Pipeline warten, sonst brechen Backlinks zu Posts, die +noch nicht als Events existieren. + +**Reihenfolge:** Option 1 → Publish-Pipeline + einmaliger Massen-Import der +übrigen 17 Altposts → dann Option 3. + +## Schnell-Orientierung für die nächste Claude-Session + +Lies in dieser Reihenfolge: +1. `docs/STATUS.md` (5 min) +2. `docs/HANDOFF.md` (= dieses Dokument) +3. Die relevante Spec, je nachdem was drankommt: + - Publish-Pipeline: `docs/superpowers/specs/2026-04-15-publish-pipeline-design.md` + - SPA-Anpassungen: `docs/superpowers/specs/2026-04-15-nostr-page-design.md` + +Nutze den Skill unter `.claude/skills/joerglohrerde-workflow.md` für +wiederkehrende Kommandos. + +## Dev-Kommandos + +```sh +# Unit-Tests (Vitest) +cd app && npm run test:unit + +# E2E-Tests (Playwright) +cd app && npm run test:e2e + +# Type-Check +cd app && npm run check + +# Dev-Server (Port 5173) +cd app && npm run dev + +# Production-Build + Deploy +cd app && npm run build && cd .. && ./scripts/deploy-svelte.sh +``` + +## Manuelles Publishen (bis Publish-Pipeline fertig ist) + +Einen Post aus `content/posts//index.md` als kind:30023-Event +publizieren: + +```sh +# Body ohne Frontmatter extrahieren +awk 'BEGIN{in_fm=0; past_fm=0} NR==1 && /^---$/ {in_fm=1; next} in_fm && /^---$/ {in_fm=0; past_fm=1; next} past_fm {print}' content/posts//index.md > /tmp/body.md + +# Bunker-URL aus .env.local +BUNKER_URL=$(grep -E '^BUNKER_URL=' .env.local | sed 's/^BUNKER_URL=//') + +# Event bauen, signieren, zu Relays pushen +# (Tags: d, title, summary, image, published_at, t×n) +# Siehe "dezentrale-oep-oer"-Beispiel in der Brainstorm-Historie +``` + +Für Bilder: Upload zu Blossom mit `nak blossom upload`: +```sh +nak blossom upload --server https://blossom.edufeed.org --sec "$BUNKER_URL" +``` + +## Bekannte Stolperfallen + +- **Amber-Bunker:** bei neuer Bunker-URL müssen globale Permissions in Amber + zurückgesetzt werden, sonst hängt `nak` auf den Signatur-Request. +- **All-Inkl FTPS:** bricht mit TLS 1.3 die Data-Connection ab. Script + nutzt `--tls-max 1.2`. Bei SSH-Umstellung: rsync fixen, TLS-Flag raus. +- **Svelte 5 Runes:** `$props()`-Werte müssen via `$derived()` in lokale + Variablen, sonst `state_referenced_locally`-Warning. +- **applesauce-relay API:** ist RxJS-basiert. `pool.request(relays, filter)` + returned `Observable` (nicht die Tupel-`subscribe({next: msg + if msg[0]==='EVENT'})`-Form). +- **Slug-Normalisierung:** alle Frontmatter-Slugs sind lowercase (Commit + `d17410f`). Beim Publishen 1:1 übernehmen, keine Runtime-Transformation. + +## Session-Kontext + +Hilfreich beim Wiedereinstieg mit Claude: +- Branch-Check: `git log --oneline -10 spa main hugo-archive` +- Live-Check: `curl -sI https://svelte.joerg-lohrer.de/` +- Publish-Status: `nak req -k 30023 -a 4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41 wss://relay.damus.io 2>/dev/null | jq -c '{d: (.tags[] | select(.[0]=="d") | .[1]), title: (.tags[] | select(.[0]=="title") | .[1])}'` diff --git a/docs/STATUS.md b/docs/STATUS.md new file mode 100644 index 0000000..fcf349b --- /dev/null +++ b/docs/STATUS.md @@ -0,0 +1,105 @@ +# Projekt-Status: joerg-lohrer.de → Nostr-basierte SPA + +**Stand:** 2026-04-15 + +## Kurzfassung + +Jörg Lohrers persönliche Webseite wird von einem Hugo-basierten statischen +Site-Generator zu einer dezentralen Nostr-basierten SPA überführt. Posts +existieren als signierte Events (NIP-23, `kind:30023`) auf Public-Relays und +werden zur Laufzeit im Browser gerendert. + +## Drei parallele Webseiten + +| URL | Status | Rolle | +|---|---|---| +| `https://joerg-lohrer.de/` | live, unverändert | **Hugo-Altbestand** (wird noch nicht ersetzt) | +| `https://spa.joerg-lohrer.de/` | live | **Vanilla-HTML-Mini-Spike** (Proof of Concept, ~250 Zeilen HTML+JS) | +| `https://svelte.joerg-lohrer.de/` | live | **SvelteKit-SPA** (35-Task-Plan komplett) | + +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 + +- **Autoren-Pubkey:** `npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9` + (hex: `4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41`) +- **Publizierte Events:** ~10 Langform-Posts (`kind:30023`), darunter + `dezentrale-oep-oer`, `offenheit-das-wesentliche`, `gleichnis-vom-saemann`, + `bibelfussball`, `dampfnudeln` u. a. +- **Relay-Liste** (`kind:10002`): `relay.damus.io`, `nos.lol`, + `relay.primal.net`, `relay.tchncs.de`, `relay.edufeed.org` +- **Blossom-Server** (`kind:10063`): `blossom.edufeed.org`, `blossom.primal.net` + +Bilder des ersten „experimentell publizierten" Posts (`dezentrale-oep-oer`) +liegen auf Blossom. Weitere 17 Altposts haben ihre Bilder noch unter dem +ursprünglichen Hugo-Permalink auf All-Inkl. + +## Repo-Struktur + +``` +joerglohrerde/ +├── content/posts/ # Markdown-Quelle (18 Posts, wird vom Publish-Skript gelesen) +├── app/ # SvelteKit-SPA (Ziel-Implementation) +├── preview/spa-mini/ # Vanilla-HTML-Mini-Spike (Referenz) +├── scripts/ +│ └── deploy-svelte.sh # FTPS-Deploy nach svelte.joerg-lohrer.de +├── docs/ +│ ├── STATUS.md # Dieses Dokument +│ ├── HANDOFF.md # Wie man hier weitermacht +│ └── superpowers/ +│ ├── specs/ # SPA-Spec + Publish-Pipeline-Spec +│ └── plans/ # SPA-Implementation-Plan (35 Tasks, abgeschlossen) +├── .claude/ +│ ├── skills/ # Repo-spezifischer Claude-Skill +│ └── settings.local.json # Claude-Session-State (nicht committen? aktuell schon) +└── .env.local # Gitignored: FTP-Creds + Bunker-URL +``` + +## Branch-Layout (Git) + +- **`main`** — kanonischer Zweig. Enthält Content, Specs, Pläne, Deploy-Scripts, + `.claude/`-Skill. Schlanker als früher (kein Hugo-Artefakt mehr). +- **`spa`** — aktueller Arbeits-Branch. SvelteKit-SPA in `app/` komplett + implementiert und live. **Aktuell vor `main` mit allen `spa:`-Commits.** +- **`hugo-archive`** — Orphan-Branch mit dem letzten funktionierenden + Hugo-Zustand, eingefroren. Rollback über `git checkout hugo-archive && hugo build`. + +## Setup-Zustand + +Einmalig manuell erledigt: +- ✅ Amber-Bunker-URL in `.env.local` als `BUNKER_URL` +- ✅ SPA-FTP-Creds (`spa.joerg-lohrer.de`) in `.env.local` als `SPA_FTP_*` +- ✅ SvelteKit-FTP-Creds (`svelte.joerg-lohrer.de`) in `.env.local` als `SVELTE_FTP_*` +- ✅ `kind:10002`-Event publiziert +- ✅ `kind:10063`-Event publiziert +- ✅ Subdomains mit TLS + HSTS (`max-age=300`) + +Alles in `.env.local` — gitignored, nicht committet. + +## Offene Punkte / Nicht-in-Scope + +- **Publish-Pipeline** (Spec vorhanden unter `docs/superpowers/specs/2026-04-15-publish-pipeline-design.md`, Plan noch nicht geschrieben) +- **Menü-Navigation** in der SPA (Home / Archiv / Impressum / Kontakt) +- **Impressum-Seite** (braucht rechtlichen Text) +- **Meta-Stubs für Social-Previews und SEO** (wird Teil der Publish-Pipeline) +- **SSH-Zugang zu All-Inkl** (laut Notiz von Jörg: Premium-Tarif im Kommen → rsync statt FTPS möglich) +- **Cutover auf `joerg-lohrer.de`** (Hauptdomain bekommt dann die SvelteKit-SPA) + +## Live-Verifikation + +Jederzeit: +```sh +curl -sI https://svelte.joerg-lohrer.de/ | head -3 +curl -sI https://spa.joerg-lohrer.de/ | head -3 +``` + +## Kontakt zur Implementierung + +Alle Design-Entscheidungen in: +- `docs/superpowers/specs/2026-04-15-nostr-page-design.md` (SPA) +- `docs/superpowers/specs/2026-04-15-publish-pipeline-design.md` (Publish) +- `docs/superpowers/plans/2026-04-15-spa-sveltekit.md` (35-Task-Plan, abgeschlossen) + +Für die nächste Session: `docs/HANDOFF.md` lesen.