Compare commits
2 Commits
10e455a078
...
40785df346
| Author | SHA1 | Date |
|---|---|---|
|
|
40785df346 | |
|
|
54eb0b62cb |
87
README.md
87
README.md
|
|
@ -1,46 +1,97 @@
|
|||
# joerg-lohrer.de
|
||||
|
||||
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.
|
||||
Persönliche Webseite. Nach einer Transition von einer Hugo-basierten,
|
||||
statischen Seite läuft `joerg-lohrer.de` jetzt als 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).
|
||||
- **`https://joerg-lohrer.de/`** — SvelteKit-SPA, Cutover am 2026-04-18 erfolgt.
|
||||
- **`https://staging.joerg-lohrer.de/`** — Staging (gleicher Build, ein Schritt vor Prod).
|
||||
- **`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).
|
||||
|
||||
## 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
|
||||
|
||||
- 📍 **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)
|
||||
- 📐 **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)
|
||||
- 🛠 **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)
|
||||
|
||||
## Branches
|
||||
|
||||
- **`main`** — kanonisch (Content, Specs, Pläne, Deploy-Scripts, Skill).
|
||||
- **`spa`** — aktueller Arbeitszweig mit allen SvelteKit-Commits. Wird beim
|
||||
Cutover nach `main` gemerged.
|
||||
- **`main`** — kanonisch. Seit Cutover (2026-04-18) Produktions-Quelle.
|
||||
- **`spa`** — historischer SvelteKit-Arbeitszweig, inzwischen gemerged.
|
||||
- **`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
|
||||
|
||||
```
|
||||
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
|
||||
content/posts/ Markdown-Posts (Quelle für Nostr-Events, 18 Stück)
|
||||
content/impressum.md Statisches Impressum (wird von SPA geladen)
|
||||
app/ SvelteKit-SPA (Laufzeit-Renderer)
|
||||
publish/ Deno-Publish-Pipeline (Blossom + Nostr)
|
||||
preview/spa-mini/ Vanilla-HTML-Mini-Spike (historische Referenz)
|
||||
scripts/deploy-svelte.sh FTPS-Deploy, Targets: svelte/staging/prod
|
||||
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
|
||||
|
||||
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).
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<script lang="ts">
|
||||
// CC-Zero-Badge: kombination aus CC-Heart + Zero-Logo, monochrom via
|
||||
// currentColor. Icons aus dem offiziellen CC-Press-Kit
|
||||
// (creativecommons.org/mission/branding/). Inline hier, weil statische
|
||||
// svg-imports mit ?raw in vite problematisch sind.
|
||||
</script>
|
||||
|
||||
<span class="cc-badge" aria-hidden="true">
|
||||
<!-- CC-Heart (vereinfachtes herz aus dem offiziellen logo) -->
|
||||
<svg viewBox="0 0 46296 40689" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M23204.91 7530.98c2944.63,-3188.84 6384.04,-4639.01 10366.38,-4077.21 4110.34,579.88 7609.97,3518.41 8854.17,7479.01 957.39,3047.58 559.96,6460.83 -722.09,9573.35 -1993.98,4840.97 -7886.31,11722.09 -18555.24,16532.85 -10668.92,-4810.76 -16561.25,-11691.88 -18555.24,-16532.85 -1282.05,-3112.52 -1679.47,-6525.77 -722.09,-9573.35 1244.19,-3960.6 4743.83,-6899.13 8854.17,-7479.01 3982.46,-561.82 7421.94,888.46 10366.64,4077.48 5.4,5.84 56.52,61.37 56.53,61.36 0.04,0.04 51.9,-56.36 56.79,-61.63zm-56.79 -4522.44c-6431.69,-5048.01 -16512.25,-3730.83 -21147.65,3855.94 -1539.08,2519.03 -2117.14,5447.75 -1981.3,8355.45 235.64,5043.59 2412.75,9452.27 5610.61,13256.78 4306.02,5122.9 10531.26,9148.59 17382.21,12152.72 9.53,4.18 88.63,38.56 136.13,59.69 41.66,-17.53 114.6,-50.41 137.01,-60.3 6815.65,-3004.07 13075.56,-7030.12 17381.33,-12152.12 3198.08,-3804.33 5374.97,-8213.2 5610.61,-13256.78 135.85,-2907.7 -442.2,-5836.43 -1981.3,-8355.45 -4635.4,-7586.77 -14715.95,-8903.95 -21147.65,-3855.94z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M22983.64 21630.19l-2928.01 -1451.38c-1017.73,1483.99 -1758.21,2488.33 -3897.08,1902.25 -1678.91,-460.05 -2175.85,-2300.18 -2239.67,-3843.76 -87.17,-2108.39 649.94,-4543.46 3168.15,-4413.24 1609.13,83.19 2294.75,1032.23 2661.15,1885.36l3196.99 -1638.9c-1574.75,-3004.31 -5265.13,-4026.05 -8393.32,-3188.81 -3328.66,890.9 -5014.61,3952.95 -4955.5,7255.23 60.43,3375.58 1680.8,6291.51 5161.55,7052.54 1697.16,371.06 3545.13,284.81 5116.74,-503.18 1216.27,-609.83 2567.56,-1786.86 3109,-3056.12zm13802.46 0l-2928.01 -1451.38c-1017.73,1483.99 -1758.21,2488.33 -3897.08,1902.25 -1678.91,-460.05 -2175.86,-2300.18 -2239.67,-3843.76 -87.18,-2108.39 649.94,-4543.46 3168.15,-4413.24 1609.13,83.19 2294.74,1032.23 2661.15,1885.36l3196.99 -1638.9c-1574.75,-3004.31 -5265.14,-4026.05 -8393.32,-3188.81 -3328.66,890.9 -5014.61,3952.95 -4955.5,7255.23 60.42,3375.58 1680.8,6291.51 5161.55,7052.54 1697.16,371.06 3545.13,284.81 5116.74,-503.18 1216.27,-609.83 2567.56,-1786.86 3109,-3056.12z"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<!-- CC-Zero (kreis + 0 aus dem cc-0-logo) -->
|
||||
<svg viewBox="-0.5 0.5 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M31.5,14.08c-10.565,0-13.222,9.969-13.222,18.42c0,8.452,2.656,18.42,13.222,18.42c10.564,0,13.221-9.968,13.221-18.42C44.721,24.049,42.064,14.08,31.5,14.08z M31.5,21.026c0.429,0,0.82,0.066,1.188,0.157c0.761,0.656,1.133,1.561,0.403,2.823l-7.036,12.93c-0.216-1.636-0.247-3.24-0.247-4.437C25.808,28.777,26.066,21.026,31.5,21.026z M36.766,26.987c0.373,1.984,0.426,4.056,0.426,5.513c0,3.723-0.258,11.475-5.69,11.475c-0.428,0-0.822-0.045-1.188-0.136c-0.07-0.021-0.134-0.043-0.202-0.067c-0.112-0.032-0.23-0.068-0.336-0.11c-1.21-0.515-1.972-1.446-0.874-3.093L36.766,26.987z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M31.433,0.5c-8.877,0-16.359,3.09-22.454,9.3c-3.087,3.087-5.443,6.607-7.082,10.532C0.297,24.219-0.5,28.271-0.5,32.5c0,4.268,0.797,8.32,2.397,12.168c1.6,3.85,3.921,7.312,6.969,10.396c3.085,3.049,6.549,5.399,10.398,7.037c3.886,1.602,7.939,2.398,12.169,2.398c4.229,0,8.34-0.826,12.303-2.465c3.962-1.639,7.496-3.994,10.621-7.081c3.011-2.933,5.289-6.297,6.812-10.106C62.73,41,63.5,36.883,63.5,32.5c0-4.343-0.77-8.454-2.33-12.303c-1.562-3.885-3.848-7.32-6.857-10.33C48.025,3.619,40.385,0.5,31.433,0.5z M31.567,6.259c7.238,0,13.412,2.566,18.554,7.709c2.477,2.477,4.375,5.31,5.67,8.471c1.296,3.162,1.949,6.518,1.949,10.061c0,7.354-2.516,13.454-7.506,18.33c-2.592,2.516-5.502,4.447-8.74,5.781c-3.2,1.334-6.498,1.994-9.927,1.994c-3.468,0-6.788-0.653-9.949-1.948c-3.163-1.334-6.001-3.238-8.516-5.716c-2.515-2.514-4.455-5.353-5.826-8.516c-1.333-3.199-2.017-6.498-2.017-9.927c0-3.467,0.684-6.787,2.017-9.949c1.371-3.2,3.312-6.074,5.826-8.628C18.092,8.818,24.252,6.259,31.567,6.259z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<style>
|
||||
.cc-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.15em;
|
||||
color: var(--accent);
|
||||
vertical-align: -0.2em;
|
||||
}
|
||||
.cc-badge svg {
|
||||
width: 1.1em;
|
||||
height: 1.1em;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/state';
|
||||
import { bootstrapReadRelays } from '$lib/stores/readRelays';
|
||||
import CcZeroBadge from '$lib/components/CcZeroBadge.svelte';
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
|
|
@ -37,11 +38,28 @@
|
|||
|
||||
<footer class="site-footer">
|
||||
<div class="footer-inner">
|
||||
<span class="footer-copy">© Jörg Lohrer</span>
|
||||
<span class="footer-license">
|
||||
<a
|
||||
href="https://creativecommons.org/publicdomain/zero/1.0/deed.de"
|
||||
target="_blank"
|
||||
rel="license noopener"
|
||||
aria-label="CC0 1.0 Universal Public Domain Dedication"
|
||||
title="CC0 1.0 Universal"
|
||||
>
|
||||
<CcZeroBadge />
|
||||
<span class="cc-label">CC0</span>
|
||||
</a>
|
||||
Jörg Lohrer
|
||||
</span>
|
||||
<span class="footer-sep">·</span>
|
||||
<a href="/impressum/">Impressum</a>
|
||||
<span class="footer-sep">·</span>
|
||||
<span class="footer-meta">Nostr-basiert</span>
|
||||
<a
|
||||
href="https://github.com/joerglohrer/joerglohrerde"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
title="Quellcode, Making-of und Nostr-Publish-Pipeline"
|
||||
>Nostr-basiert – Making-of im Repo</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
|
@ -129,7 +147,17 @@
|
|||
.footer-sep {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.footer-meta {
|
||||
opacity: 0.7;
|
||||
.footer-license a {
|
||||
color: var(--accent);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.footer-license a:hover .cc-label {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.cc-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Die Inhalte unserer Seiten wurden mit größter Sorgfalt erstellt. Für die Rich
|
|||
Mein Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte ich keinen Einfluss habe. Deshalb kann ich für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werde ich derartige Links umgehend entfernen.
|
||||
|
||||
### Urheberrecht
|
||||
Die durch den Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen jedoch nicht der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind sowohl für den privaten, als auch für den kommerziellen Gebrauch unter Namensnennung und der Creative Commons Lizenz [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/deed.de) gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Solltest Du trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten ich um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werde ich derartige Inhalte umgehend entfernen.
|
||||
Die durch den Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Soweit nicht anders angegeben, stelle ich eigene Inhalte und Werke unter der Creative-Commons-Lizenz [CC0 1.0 Universal (Public Domain Dedication)](https://creativecommons.org/publicdomain/zero/1.0/deed.de) zur Verfügung — sie dürfen ohne Rückfrage für jeden Zweck, auch kommerziell, kopiert, bearbeitet, verbreitet und weiterverwendet werden. Eine Namensnennung ist rechtlich nicht erforderlich, aber ich freue mich natürlich, wenn Du mich als Quelle nennst. Wo eine abweichende Lizenz gilt, ist sie beim jeweiligen Inhalt vermerkt. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Solltest Du trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitte ich um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werde ich derartige Inhalte umgehend entfernen.
|
||||
|
||||
### Datenschutz
|
||||
Die Nutzung meiner Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf meiner Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder eMail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Deine ausdrückliche Zustimmung nicht an Dritte weitergegeben. Ich weise darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit ausdrücklich widersprochen. Die Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-Mails, vor.
|
||||
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`)
|
||||
|
||||
**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.
|
||||
**Cutover am 2026-04-18 abgeschlossen.** `joerg-lohrer.de` läuft als
|
||||
SvelteKit-SPA, rendert 18 Nostr-Langform-Posts live aus 5 Relays, Bilder
|
||||
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).
|
||||
Automatischer Auto-Trigger bei Content-Push noch nicht ausprobiert —
|
||||
kann jederzeit beiläufig mitgenommen werden:
|
||||
**Liste der verwaisten Nostr-Events** (d-tag → event-id-Prefix):
|
||||
|
||||
1. Minimaler Edit in einem Post (z. B. Typo) → commit → push `main`
|
||||
2. Forgejo synct automatisch zu GitHub → Workflow triggert → 1 Post als
|
||||
`update` publiziert
|
||||
3. Log-Artefakt in GitHub Actions prüfen
|
||||
| d-tag | event-id | Probleme |
|
||||
|---|---|---|
|
||||
| `richter-oder-rcher-banksy-als-moderner-prophet-vor-dem-high-court` | `bb2c2cea…` | Umlaut-Abdecker (`Rächer` → `rcher`) |
|
||||
| `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
|
||||
läuft ja schon, ob manuell oder via CI ist für den Cutover egal.
|
||||
1. **Content exportieren.** Pro Event: `nak req -i <event-id> <relay>` →
|
||||
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:**
|
||||
1. In All-Inkl KAS die Domain `joerg-lohrer.de` auf den SvelteKit-Webroot
|
||||
umhängen (aktuell: `svelte.joerg-lohrer.de` → `/www/htdocs/v109928/joerglohrer28/`
|
||||
oder welcher Ordner auch immer).
|
||||
2. SvelteKit-SPA deployen, sofern sie nicht schon dort liegt.
|
||||
3. Live-Check: `curl -sI https://joerg-lohrer.de/` → sollte die neue SPA
|
||||
liefern, nicht mehr Hugo.
|
||||
**Edge Cases:**
|
||||
- Das leere-d-tag-Event (`d75857dc…`): wenn es noch sinnvoller Content
|
||||
ist, als neuer Post re-importieren. Sonst einfach löschen.
|
||||
- Bilder in alten Events zeigen auf externe Server (nicht Blossom). Beim
|
||||
Re-Publish lädt die Pipeline sie herunter und hasht sie neu. Wenn die
|
||||
Quelle tot ist, muss das Bild manuell beschafft oder der Post mit
|
||||
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 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
|
||||
### Option B — SPA respektiert NIP-09-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 —
|
||||
`kind:5`-Referenz gelöscht wurde, 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
|
||||
**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
|
||||
### Option C — Postfach `webmaster@joerg-lohrer.de`
|
||||
|
||||
**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.
|
||||
User-Task: im All-Inkl KAS als Weiterleitung anlegen. Der Link im
|
||||
Footer und in den Social-Icons zeigt bereits darauf.
|
||||
|
||||
**Zu tun:**
|
||||
- **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
|
||||
### Option D — 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
|
||||
|
|
@ -100,9 +100,10 @@ deno task publish-delete --slug <slug>
|
|||
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
|
||||
existiert.
|
||||
|
|
@ -116,6 +117,17 @@ existiert.
|
|||
Der Pipeline-Code selbst (`publish/src/**`) ist CI-agnostisch — nur die
|
||||
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
|
||||
|
||||
Lies in dieser Reihenfolge:
|
||||
|
|
@ -134,7 +146,8 @@ cd app && npm run check
|
|||
cd app && npm run dev
|
||||
|
||||
# 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
|
||||
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 --force-all # alle posts
|
||||
cd publish && deno task publish --post <slug> # einen post
|
||||
cd publish && deno task test # 59 tests
|
||||
cd publish && deno task test # tests
|
||||
```
|
||||
|
||||
## 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
|
||||
ein Date-Objekt. `validatePost` coerced das automatisch; in neuen Posts
|
||||
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
|
||||
|
||||
|
|
@ -177,10 +193,14 @@ Pipeline loggt Warnungen, publisht aber trotzdem. Recherche-Notizen in
|
|||
## 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
|
||||
- Branch-Check: `git log --oneline -10 main`
|
||||
- Live-Check: `curl -sI https://joerg-lohrer.de/`
|
||||
- Event-Count Repo vs. Relays:
|
||||
```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
|
||||
|
||||
|
|
|
|||
158
docs/STATUS.md
158
docs/STATUS.md
|
|
@ -1,63 +1,63 @@
|
|||
# Projekt-Status: joerg-lohrer.de → Nostr-basierte SPA
|
||||
|
||||
**Stand:** 2026-04-18
|
||||
**Stand:** 2026-04-18 (Cutover abgeschlossen)
|
||||
|
||||
## 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.
|
||||
`joerg-lohrer.de` läuft als SvelteKit-SPA, die Blog-Posts live aus
|
||||
signierten Nostr-Events (NIP-23, `kind:30023`) auf 5 Public-Relays rendert.
|
||||
Bilder liegen content-addressed auf 2 Blossom-Servern. Die Hugo-basierte
|
||||
Altseite ist als `hugo-archive`-Branch eingefroren.
|
||||
|
||||
## Vier parallele Webseiten
|
||||
**Das inhaltliche Kernziel des Gesamtprojekts ist erreicht.**
|
||||
|
||||
## Live-URLs
|
||||
|
||||
| URL | Status | Rolle |
|
||||
|---|---|---|
|
||||
| `https://joerg-lohrer.de/` | live, unverändert | **Hugo-Altbestand** (bleibt bis Cutover) |
|
||||
| `https://spa.joerg-lohrer.de/` | live | **Vanilla-HTML-Mini-Spike** (Proof of Concept) |
|
||||
| `https://svelte.joerg-lohrer.de/` | live | **SvelteKit-SPA** (35-Task-Plan komplett) |
|
||||
| `https://staging.joerg-lohrer.de/` | live, leer | **Staging** (Webroot `joerglohrer26/` für Pipeline-Entwicklung; FTP-Creds in `.env.local`) |
|
||||
|
||||
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.
|
||||
| `https://joerg-lohrer.de/` | live | **Produktion**, SvelteKit-SPA (Cutover 2026-04-18) |
|
||||
| `https://staging.joerg-lohrer.de/` | live | **Staging**, letzter Pre-Prod-Build |
|
||||
| `https://svelte.joerg-lohrer.de/` | live | **Entwicklung**, Deploy-Target der Pipeline |
|
||||
| `https://spa.joerg-lohrer.de/` | live | **Historisch**, Vanilla-HTML-Mini-Spike |
|
||||
|
||||
## Was auf Nostr liegt
|
||||
|
||||
- **Autoren-Pubkey:** `npub1f7jar3qnu269uyx5p0e4v24hqxjnxysxudvujza2ur5ehltvdeqsly2fx9`
|
||||
(hex: `4fa5d1c413e2b45e10d40bf3562ab701a5331206e359c90baae0e99bfd6c6e41`)
|
||||
- **Publizierte Events:** **18 Langform-Posts** (`kind:30023`) — alle Altposts
|
||||
via Publish-Pipeline migriert (Commit `0c6fdd1`, Log in
|
||||
`docs/publish-logs/2026-04-18-force-all-migration.json`).
|
||||
- **NIP-05:** `joerglohrer@joerg-lohrer.de` (via `/.well-known/nostr.json`)
|
||||
- **Publizierte Events:** **18 Langform-Posts** (`kind:30023`) aus dem Repo,
|
||||
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.primal.net`, `relay.tchncs.de`, `relay.edufeed.org`
|
||||
- **Blossom-Server** (`kind:10063`): `blossom.edufeed.org`, `blossom.primal.net`
|
||||
|
||||
**91 Bilder** auf beiden Blossom-Servern. Alle Events enthalten hash-basierte
|
||||
Blossom-URLs. SPA rendert alle Posts einheitlich — kein Legacy-Pfad, keine
|
||||
rsync-Artefakte.
|
||||
- **91 Bilder** auf beiden Blossom-Servern, alle Events enthalten
|
||||
hash-basierte Blossom-URLs.
|
||||
|
||||
## Repo-Struktur
|
||||
|
||||
```
|
||||
joerglohrerde/
|
||||
├── content/posts/ # 18 Markdown-Posts, alle mit structured images: im Frontmatter
|
||||
├── app/ # SvelteKit-SPA (Ziel-Implementation)
|
||||
├── preview/spa-mini/ # Vanilla-HTML-Mini-Spike (Referenz)
|
||||
├── publish/ # NOCH NICHT ANGELEGT — Publish-Pipeline (Task 1 aus Plan)
|
||||
├── content/posts/ # 18 Markdown-Posts, alle mit strukturierten images:
|
||||
├── content/impressum.md # Statisches Impressum (wird von SPA geladen)
|
||||
├── app/ # SvelteKit-SPA (Laufzeit-Renderer)
|
||||
├── publish/ # Deno-Publish-Pipeline (Blossom + Nostr)
|
||||
├── preview/spa-mini/ # Vanilla-HTML-Mini-Spike (historisch)
|
||||
├── scripts/
|
||||
│ └── deploy-svelte.sh # FTPS-Deploy nach svelte.joerg-lohrer.de
|
||||
│ └── deploy-svelte.sh # FTPS-Deploy, Targets: svelte/staging/prod
|
||||
├── docs/
|
||||
│ ├── STATUS.md # Dieses Dokument
|
||||
│ ├── HANDOFF.md # Wie man hier weitermacht
|
||||
│ ├── redaktion-bild-metadaten.md # Checkliste, Bild-Durchgang (abgearbeitet)
|
||||
│ ├── wiki-entwurf-nostr-bild-metadaten.md # Wiki-Konvention deutsch
|
||||
│ ├── wiki-draft-nostr-image-metadata.md # Wiki-Konvention englisch
|
||||
│ ├── redaktion-bild-metadaten.md
|
||||
│ ├── wiki-entwurf-nostr-bild-metadaten.md
|
||||
│ ├── wiki-draft-nostr-image-metadata.md
|
||||
│ ├── github-ci-setup.md
|
||||
│ └── superpowers/
|
||||
│ ├── specs/ # SPA + Publish-Pipeline + Bild-Metadaten-Konvention
|
||||
│ └── plans/
|
||||
│ ├── 2026-04-15-spa-sveltekit.md # erledigt
|
||||
│ └── 2026-04-16-publish-pipeline.md # ⬅ als nächstes
|
||||
│ ├── 2026-04-15-spa-sveltekit.md # erledigt
|
||||
│ └── 2026-04-16-publish-pipeline.md # erledigt
|
||||
├── .github/workflows/ # publish.yml (Forgejo→GitHub Push-Mirror-Trigger)
|
||||
├── .claude/
|
||||
│ ├── skills/ # Repo-spezifischer Claude-Skill
|
||||
│ └── settings.local.json # Claude-Session-State (gitignored)
|
||||
|
|
@ -66,80 +66,78 @@ joerglohrerde/
|
|||
|
||||
## Branch-Layout (Git)
|
||||
|
||||
- **`main`** — kanonischer Zweig.
|
||||
- **`spa`** — aktueller Arbeits-Branch, vor `main`. SvelteKit-SPA live,
|
||||
Content-Migration (Bild-Metadaten) abgeschlossen, Publish-Pipeline geplant.
|
||||
- **`main`** — kanonischer Zweig, Produktions-Quelle seit Cutover.
|
||||
- **`spa`** — historischer SvelteKit-Arbeitszweig, gemerged.
|
||||
- **`hugo-archive`** — Orphan-Branch mit Hugo-Zustand, eingefroren.
|
||||
|
||||
## Setup-Zustand
|
||||
|
||||
Einmalig manuell erledigt:
|
||||
- ✅ Amber-Bunker-URL in `.env.local` als `BUNKER_URL`
|
||||
- ✅ FTP-Creds für alle Subdomains (SPA, SVELTE, STAGING) in `.env.local`
|
||||
- ✅ `AUTHOR_PUBKEY_HEX` und `BOOTSTRAP_RELAY=wss://relay.primal.net` in `.env.local`
|
||||
Einmalig manuell erledigt (gitignored in `.env.local`):
|
||||
- ✅ Amber-Bunker-URL als `BUNKER_URL`
|
||||
- ✅ FTP-Creds für alle Targets (SVELTE/STAGING/PROD)
|
||||
- ✅ `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:10063`-Event publiziert (Blossom-Server)
|
||||
- ✅ 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
|
||||
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
|
||||
## Erledigt (chronologisch seit 2026-04-15)
|
||||
|
||||
- ✅ Content-Migration: alle 18 Posts haben strukturierte `images:`-Liste
|
||||
im Frontmatter (91 Bilder, mit Alt-Text, Lizenz, Autor:innen, ggf. Caption
|
||||
und Modifications). Commit `c023b59`.
|
||||
- ✅ Erlebnispädagogik-Post: tote Amazon-Hotlinks entfernt.
|
||||
im Frontmatter (91 Bilder, mit Alt-Text, Lizenz, Autor:innen, ggf.
|
||||
Caption und Modifications).
|
||||
- ✅ Spec, Plan und Bild-Metadaten-Konvention geschrieben.
|
||||
- ✅ Community-Wiki-Entwürfe (DE + EN) für Nostr-Bildattribution.
|
||||
- ✅ **Publish-Pipeline komplett implementiert**, 22 Tasks aus dem Plan:
|
||||
- 18 Code-Tasks (Phase 1–6), 59 Unit-Tests grün
|
||||
- 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`).
|
||||
- ✅ **Publish-Pipeline komplett implementiert** (24 Tasks, 59 Tests grün).
|
||||
- ✅ **Alle 18 Altposts publiziert** als `kind:30023`-Events.
|
||||
- ✅ **91 Bilder** auf beiden Blossom-Servern.
|
||||
- ✅ SPA rendert alle Posts mit Bildern von Blossom (visuell verifiziert).
|
||||
- ✅ **GitHub-Actions-Workflow** angelegt (`.github/workflows/publish.yml`).
|
||||
- ✅ Forgejo → GitHub Push-Mirror eingerichtet, GitHub-Secrets gesetzt.
|
||||
- ✅ **`spa` → `main` gemergt**, GitHub-Actions-Workflow manuell verifiziert
|
||||
(Run #1: signer ok, outbox ok, blossom-liste ok, mode=diff posts=0).
|
||||
**Alle 24 Tasks des Publish-Pipeline-Plans abgeschlossen.**
|
||||
- ✅ **Staging-Deploy-Infrastruktur:** `scripts/deploy-svelte.sh` mit
|
||||
drei Targets (`svelte`/`staging`/`prod`), dynamisches `og:url` und
|
||||
`canonical` via `__SITE_URL__`-Platzhalter. Staging-Subdomain
|
||||
`staging.joerg-lohrer.de` bedient jetzt `joerglohrer26/` (Cutover-Ziel).
|
||||
- ✅ **Duplikat-Event `1744905463975` via NIP-09 gelöscht** (Delete-Event
|
||||
`7f5d08b8…`, auf alle 5 Relays). Nach Migration nicht mehr auffindbar.
|
||||
- ✅ **GitHub-Actions-Workflow** + Forgejo→GitHub Push-Mirror + Secrets.
|
||||
- ✅ **Duplikat-Event via NIP-09 gelöscht** (`bibel-selfies` Unix-Timestamp-dup).
|
||||
- ✅ **Staging-Deploy-Infrastruktur** mit `__SITE_URL__`-Templating.
|
||||
- ✅ **Homepage** mit Hero, Profilbild, Social-Icons (Nostr/Mastodon/
|
||||
Bluesky/LinkedIn/ORCID/Mail), Latest-Posts.
|
||||
- ✅ **Archiv-Seite**, **Impressum-Seite**, Menü-Navigation im Layout.
|
||||
- ✅ **CC0-Footer-Badge** (Heart+Zero inline SVG, monochrom).
|
||||
- ✅ **Impressum auf CC0 umgestellt** (mit freundlichem Namensnennungs-Hinweis).
|
||||
- ✅ **Cutover 2026-04-18** — `joerg-lohrer.de` von Hugo (`joerglohrer24/`)
|
||||
auf SvelteKit-SPA (`joerglohrer26/`) umgehängt.
|
||||
|
||||
## Live-Verifikation
|
||||
|
||||
```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 -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-publish-pipeline-design.md` (Publish, Blossom-only)
|
||||
- `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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue