Merge branch 'main' into spa
This commit is contained in:
commit
7ea29941a6
|
|
@ -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**: `/<dtag>/` (z. B. `/dezentrale-oep-oer/`).
|
||||
- Legacy-Hugo-URLs `/YYYY/MM/DD/<dtag>.html/` werden per SvelteKit-Load
|
||||
auf die kurze Form 301-redirected (Backlink-Kompatibilität).
|
||||
- Tag-Route: `/tag/<name>/`.
|
||||
|
||||
### 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" <bild>`
|
||||
- Event bauen mit `nak event -k 30023 -d <slug> -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<NostrEvent>`. 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) <noreply@anthropic.com>`.
|
||||
- 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
|
||||
48
README.md
48
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)
|
||||
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 und Architektur-Dokumentation
|
||||
.claude/ Claude-Code-Sessions (als Transparenz-Spur)
|
||||
docs/ Specs, Pläne, Status, Handoff
|
||||
.claude/ Claude-Code-Sessions (transparenz) + Skills
|
||||
```
|
||||
|
||||
## Lizenz
|
||||
|
|
|
|||
|
|
@ -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/<ordner>/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/<ordner>/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" <bild>
|
||||
```
|
||||
|
||||
## 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<NostrEvent>` (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])}'`
|
||||
|
|
@ -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.
|
||||
Loading…
Reference in New Issue