Commit Graph

137 Commits

Author SHA1 Message Date
Jörg Lohrer f606748c3e test: failing node-test fuer renderMarkdown
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:00:13 +02:00
Jörg Lohrer 0b287f9ff6 docs: jsonld via svelte-tag statt {@html}
User-feedback: <script type="application/ld+json"> kann svelte direkt
rendern. Kein @html-Notausgang noetig, sauberere variante mit
auto-escape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:56:58 +02:00
Jörg Lohrer 7428930a76 docs: implementation-plan fuer prerender-snapshot
Frischer plan gegen die ueberarbeitete spec (fallback_url raus,
OG-default joerg-profil-2024.webp, prerender+runtime-fallback klar
als adapter-static-default). Sechs etappen, jede einzeln testbar
und rollback-bar:

1. renderMarkdown auf isomorphic-dompurify (node-faehig)
2. Snapshot-modul (deno) mit 9 testbaren cores + cli
3. Snapshot in CI
4. Detail-route auf prerender mit runtime-fallback
5. Runtime-fallback entfernen (snapshot ist quelle)
6. lftp mirror in drei phasen (optional, nicht-blockierend)

Alter plan bleibt im archive als geschichte.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:54:18 +02:00
Jörg Lohrer a278f65edf docs: prerender-snapshot-spec — drei klarstellungen
- fallback_url im cover_image rausgenommen (YAGNI; primary url
  reicht, blossom ist content-addressed). Beim ersten konkreten
  bedarf nachreichen.
- Site-default-OG-bild auf app/static/joerg-profil-2024.webp
  festgelegt (vorhandenes asset, nicht spekulativ).
- prerender + runtime-fallback klarer formuliert: das ist das
  default-verhalten von adapter-static mit fallback, kein
  workaround. ReplyList/ReplyComposer-hydration als
  verifikations-punkt im plan-schritt 4 vermerkt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:46:51 +02:00
Jörg Lohrer fdab93e829 docs: top-level-rollen geklaert + status-stempel
README/STATUS/HANDOFF/CLAUDE jeweils ein rollensatz oben:
- README = aussenseite
- STATUS = logbuch (stand + erledigt-chronologie)
- HANDOFF = konventions-handbuch (workflows + stolperfallen)
- CLAUDE.md = session-einstieg
HANDOFF erhaelt zusaetzlich eine Single-Source-of-Truth-sektion,
damit klar ist welche fakten wo gepflegt werden.

README-linkliste auf 3 specs eingedampft (SPA, pipeline, multilingual)
und auf das plan-archiv verlinkt statt einzelplaene. CLAUDE.md
verlinkt zusaetzlich die prerender-snapshot-spec mit kennzeichnung.
STATUS.md verzeichnis-baum spiegelt das archiv wider.

Wiki-entwuerfe + redaktions-doku + github-ci-setup-doku haben
explizite status-stempel (eingefroren / schnappschuss / aktuell-aber-zu-ersetzen),
damit man nicht mehr raten muss.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:30:44 +02:00
Jörg Lohrer 050a38d51a docs: plaene ins archiv verschoben
Alle 6 plaene unter docs/superpowers/plans/archive/. Davon 5 abgearbeitet
(SPA, publish-pipeline, 3x multilingual), 1 eingefroren (prerender-snapshot).
Checkboxen wurden waehrend der umsetzung nicht gepflegt — verbindlicher
stand ist STATUS.md und die jeweilige spec, das archive/README.md macht
die zuordnung sichtbar.

plans/ bleibt mit .gitkeep als verzeichnis bestehen, damit neue plaene
sofort wieder dort landen koennen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:30:31 +02:00
Jörg Lohrer 9017ed1926 docs: spec-header-konvention vereinheitlicht + cleanup-spec
Status-Header aller specs nach neuer konvention:
Entwurf | In Umsetzung | Umgesetzt (live seit YYYY-MM-DD) | Eingefroren | Verworfen.

Die zwei aeltesten specs (SPA, publish-pipeline) standen formal noch
auf "ausstehende User-Freigabe", obwohl seit 2026-04-18 live —
nun korrekt als umgesetzt markiert. Bild-metadaten-spec als
Phase 1 umgesetzt mit Phase-2-vermerk. Multilingual-spec angeglichen.
Prerender-snapshot-spec von "Stand:" auf "Status: Entwurf" mit
hinweis auf eingefrorenen plan im archiv.

Cleanup-spec selbst dokumentiert die konvention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 07:30:24 +02:00
Jörg Lohrer 11e406e5de docs: prerender-snapshot spec-klarstellungen + implementation-plan
spec:
- deploy upload-reihenfolge: drei-phasen-flow (assets → html → delete)
  mit präziser beschreibung statt flag-kombi-raten
- migrations-schritt 4 + 5 entkoppelt: 4 liefert snapshot primär mit
  runtime-fallback für nostr-first-posts, 5 entfernt fallback erst
  nach stabilem cutover
- exclude-glob im delete-pass für extern verwaltete files

plan (20 tasks, tdd):
- snapshot/ als deno-modul mit config, relays, dedup, plausibility,
  cover, extract, write — voll unit-getestet
- renderMarkdown auf isomorphic-dompurify
- sveltekit-route mit prerender=true, entries, og/twitter/json-ld/
  hreflang im head, snapshot-primary + runtime-fallback
- deploy-script auf lftp drei-phasen
- dokumentation in HANDOFF und CLAUDE.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:20:25 +02:00
Jörg Lohrer fd093dff5e docs: markdown-rendering aus snapshot in svelte-build verschoben
Der Snapshot liefert content_markdown, nicht content_html. Rendering
(marked + DOMPurify + highlight.js) passiert im SvelteKit-Prerender-
Schritt über das bereits existierende \$lib/render/markdown.ts —
keine Duplikation in Deno, kein gemeinsames Policy-Modul nötig.

Für Blaupausen-Nutzung ist rohes Markdown portabler: alternative
Renderer (Astro, Eleventy) bringen eigenen Markdown-Prozessor mit.

Konsequenz für Migration: Schritt 1 ist jetzt \"renderMarkdown
Node-kompatibel machen\" (isomorphic-dompurify) statt \"shared/
markdown-policy.ts ergänzen\".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:08:10 +02:00
Jörg Lohrer 48d05f8d2d docs: spec-review-eingearbeitet (HTML-render, Felder, Migration)
Nachschärfungen nach Review:
- content_html als primary im Snapshot-JSON (marked + DOMPurify +
  highlight.js, gemeinsame Policy in shared/markdown-policy.ts)
- content_markdown bleibt daneben (Debug + alternative Renderer)
- translations[] um title ergänzt (SPA-Switcher ohne Relay-Fetch)
- published_at vs. created_at semantisch klar getrennt (OG vs. Update)
- cover_image.fallback_url mit dokumentiertem Nutzungsszenario
- Fallback-Politik für fehlende summary/image/published_at
- --allow-shrink-Flag und kind:5-gestützte automatische Override
- Upload-Reihenfolge für Hash-benannte Bundles (Assets → HTML → Delete)
- /tag/<name>/-Verhalten in Nicht-Zielen erwähnt
- Edge-Case „Repo-Post + alle Relay-Events gelöscht" in Fehlertabelle
- Migrations-Weg um shared/markdown-policy.ts als Schritt 1 erweitert
- pro Migrations-Schritt explizite Rollback-Strategie

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:05:43 +02:00
Jörg Lohrer 708c86aa29 docs: spec für prerender-snapshot (SEO + social-media-cards)
Design-Dokument für die dreistufige Pipeline
publish → snapshot → build+deploy, die Post-Detailseiten mit echten
OG-Metadaten und prerendered Content versorgt, ohne Runtime-Relay-Fetch
und ohne Node-/Go-Server auf dem Shared-Hosting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:56:41 +02:00
Jörg Lohrer d12ed3c40e docs: status/handoff/readme/claude.md auf multilingual-stand
- README: neue plan-referenzen (3x multilingual), repo-struktur auf
  content/posts/<lang>/<slug>/, svelte-i18n + translations im app-tree
- STATUS: event-count 27 (26 de + 1 en), kurzfassung um mehrsprachigkeit,
  multilingual-abschnitt in „erledigt" (pipeline, spa, i18n + bugfixes)
- HANDOFF: option D entfernt (erledigt), neuer abschnitt „wie man eine
  übersetzung anlegt", frontmatter-template um a:-platzhalter,
  deploy-target-stolperfalle verschärft, vr-post-pfad aktualisiert
- Multilingual-spec: status von „noch nicht implementiert" auf „umgesetzt"
  + anmerkung zum post-switcher (📖 DE | EN statt text-hinweis)
- CLAUDE.md neu: knapper einstieg für agent-sessions mit commit-konvention,
  deploy-falle, zsh-globbing, forgejo-mirror-timing
- workflow-skill generalüberholt: post-cutover-stand, multilingual,
  publish-pipeline, activeLocale, 73 pipeline-tests

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:31:16 +02:00
Jörg Lohrer 9040e5ac02 feat(app): sprach-switcher direkt im post (📖 DE | EN)
statt text-hinweis "auch verfügbar in: ..." zeigt der post jetzt einen
kompakten switcher (📖 aktiver-code | anderer-code). klick auf den
anderen code setzt die ui-sprache global und navigiert zur sprach-
variante — alles konsistent.

language names raus (unused): displayLanguage + tests entfernt, da die
darstellung nun nur noch sprachcodes (DE/EN) zeigt. auch i18n-keys
lang.de/lang.en und post.also_available_in aufgeräumt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:09:33 +02:00
Jörg Lohrer 238b2a0938 feat(app): impressum-seitentitel lokalisiert (inhalt bleibt DE) 2026-04-21 14:15:04 +02:00
Jörg Lohrer 259d7949dd feat(app): post-route + komponenten lokalisiert (titel, datum, hinweise) 2026-04-21 14:13:59 +02:00
Jörg Lohrer 3411af610e feat(app): archiv-seite lokalisiert + nach locale gefiltert 2026-04-21 14:08:42 +02:00
Jörg Lohrer d7510953d2 feat(app): startseite lokalisiert + liste nach aktivem locale gefiltert 2026-04-21 14:07:17 +02:00
Jörg Lohrer d256670b56 feat(app): layout-header lokalisiert + sprach-switcher eingebunden 2026-04-21 14:00:26 +02:00
Jörg Lohrer 617b3dfccc feat(app): LanguageSwitcher-komponente mit de/en-buttons
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:33:40 +02:00
Jörg Lohrer 22997138f9 feat(app): i18n-init registriert messages und syncs mit activeLocale
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:33:19 +02:00
Jörg Lohrer 8f513495e3 feat(app): activeLocale-store mit persistence + initial-detection 2026-04-21 13:32:34 +02:00
Jörg Lohrer f799223836 chore(app): svelte-i18n + ui-messages-files (de/en)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:30:39 +02:00
Jörg Lohrer 5bab73def7 docs: plan 3/3 für multilinguale SPA (svelte-i18n + listen-filter)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:29:38 +02:00
Jörg Lohrer 0fca9cbfa2 fix(app): post-route lädt reaktiv via $effect statt onMount
bei navigation zwischen slugs innerhalb der gleichen [...slug]-route
bleibt die komponente montiert — onMount feuert dann nicht mehr, und
der neue post lud erst nach manuellem reload. $effect auf dtag löst
das und rendert die neue view sofort.

race-condition-guard: currentDtag wird pro effect-lauf festgefroren;
stale responses werden verworfen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:17:41 +02:00
Jörg Lohrer bf7b52ab9b feat(content): erste englische übersetzung (bible-selfies) + bidirektionaler a-tag
- neue sprach-variante content/posts/en/bible-selfies/ verweist auf dt. original
- dt. bibel-selfies verweist zurück auf bible-selfies
- plan 2/3: npm test → npm run test:unit (existing script name)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:53:59 +02:00
Jörg Lohrer 4a06213d03 feat(app): LanguageAvailability-komponente in PostView eingebunden 2026-04-21 12:49:59 +02:00
Jörg Lohrer 7f48644dfc feat(app): loadTranslations liefert sprach-varianten eines posts 2026-04-21 12:43:52 +02:00
Jörg Lohrer 8f4125fcc9 feat(app): displayLanguage code→anzeigename 2026-04-21 12:41:29 +02:00
Jörg Lohrer ef20e13172 feat(app): parseTranslationRefs extrahiert a-tags mit marker translation 2026-04-21 12:37:08 +02:00
Jörg Lohrer c28a64ed49 docs: plan 2/3 für multilinguale SPA (a-tag-resolving + sprachhinweis)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:32:13 +02:00
Jörg Lohrer b9eb2c0bab test: re-trigger action nach contentRoot-pfad-fix
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:18:51 +02:00
Jörg Lohrer ccbfc61a7c fix(publish): changedPostDirs gibt pfade mit original-contentRoot zurück 2026-04-21 10:18:20 +02:00
Jörg Lohrer 6055a8c1cc test: trigger action-smoketest nach contentRoot-fix
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:12:22 +02:00
Jörg Lohrer b89442bf5c fix(publish): changedPostDirs normalisiert ../-präfix im contentRoot 2026-04-21 10:10:01 +02:00
Jörg Lohrer 367af9df9f test: trigger github-action nach struktur-migration
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 09:59:14 +02:00
Jörg Lohrer 00c4efb69a chore: posts nach content/posts/de/ migriert, lang+a-tag-platzhalter ergänzt 2026-04-21 09:51:22 +02:00
Jörg Lohrer c93befa925 feat(publish): buildKind30023 übernimmt a-tags aus frontmatter 2026-04-21 09:22:12 +02:00
Jörg Lohrer 1b0872a93f feat(publish): validatePost prüft a-tag-format 2026-04-21 09:19:35 +02:00
Jörg Lohrer 4986eae592 feat(publish): Frontmatter unterstützt a-tag-liste 2026-04-21 09:16:26 +02:00
Jörg Lohrer 66ff33e34a docs: plan 1/3 für multilinguale posts + spec-korrektur (26 statt 8 posts)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 09:14:43 +02:00
Jörg Lohrer f977516552 test(publish): entferne toten index-mkdir im allPostDirs-fixture
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 09:14:16 +02:00
Jörg Lohrer 0c2e99dfeb feat(publish): allPostDirs traversiert sprach-ebene 2026-04-21 09:10:27 +02:00
Jörg Lohrer d3215fa760 feat(publish): filterPostDirs traversiert sprach-ebene 2026-04-21 09:06:43 +02:00
Jörg Lohrer 695f5e8e69 test: filterPostDirs für sprach-ebene (failing) 2026-04-21 09:05:53 +02:00
Jörg Lohrer 2b82994314 docs: design für multilinguale posts (content/posts/<lang>, l-/a-tags)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 08:48:29 +02:00
Jörg Lohrer 09fd7cb924 docs: status/handoff nach reimport aktualisiert
- Option A (repo/nostr-konflikt) + Option D (delete-subcommand) erledigt
- 26 statt 18 events, alltags-workflow explizit dokumentiert
- NIP-32 lang-tag als grundlage für spätere mehrsprachigkeit
- Slug-Hygiene-Stolperfalle ergänzt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 18:10:27 +02:00
Jörg Lohrer 7186c32067 feat: nostr-reimport von 8 client-posts + delete-subcommand + nip-32 lang-tag
8 neue Posts aus direkt-auf-Nostr-erstellten Events (Habla/Yakihonne) ins
Repo geholt, mit sauberen ASCII-slugs statt der kaputten d-tags (Umlaute,
Emojis, Doppelpunkte, Trailing-Dashes). Alte Events per NIP-09 geloescht.

Pipeline-Erweiterungen:
- neuer subcommand "delete" publisht NIP-09 kind:5 events via stabilem
  bunker-signer (nutzt CLIENT_SECRET_HEX-identitaet, keine re-pairings).
- frontmatter.lang + kind:30023 event tagt jetzt NIP-32 konform mit
  ["L","ISO-639-1"] + ["l","de","ISO-639-1"] (default: de).
- validate-post deno-task bekommt --allow-env (yaml-parser brauchts).

Vorbereitung fuer spaetere Mehrsprachigkeit: EN-Versionen koennen via
separate markdown-datei mit lang:en als eigenes event publiziert und
spaeter per a-tag-referenz zum DE-pendant verlinkt werden.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:50:37 +02:00
Jörg Lohrer 40785df346 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>
2026-04-18 16:27:53 +02:00
Jörg Lohrer 54eb0b62cb feat: cc0-badge im footer + impressum auf cc0 umstellen
Footer zeigt jetzt CC0-Badge (Heart+Zero inline SVG, monochrom via
currentColor) statt "© Jörg Lohrer". Impressum entsprechend von
CC BY-SA auf CC0 umgestellt, mit freundlichem Hinweis, dass
Namensnennung erwünscht, aber nicht rechtlich erforderlich ist.

"Nostr-basiert" im Footer jetzt Link zum GitHub-Repo (Making-of).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 16:19:21 +02:00
Jörg Lohrer 10e455a078 spa: startseite + archiv + impressum + menü + assets für cutover
Startseite (+page.svelte) komplett überarbeitet:
  - Hero mit lokalem Profilbild (WebP aus static/, schneller als
    kind:0-roundtrip), Begrüßung "Hi Willkommen auf meinem Blog 🤗",
    About/Website aus kind:0
  - Social-Icons-Leiste (Nostr/Mastodon/Bluesky/LinkedIn/ORCID/Mail)
    als inline-SVG, monochrom via currentColor, hover färbt blau
  - Nostr-Icon von satscoffee/nostr_icons (outline, CC0), die anderen
    stilisiert als vereinfachte Brand-Icons
  - Neueste 5 Posts + Archiv-Link

Archiv-Route (/archiv/): alle Posts, nach Jahr gruppiert.

Impressum (/impressum/): static-page, rendert content/impressum.md
(via vite ?raw-import), bleibt aus nostr-feeds draußen. Frontmatter-
parser toleriert trailing-spaces auf --- zeilen.

Menü im Layout: sticky header mit brand + 3 links (Home, Archiv,
Impressum), aktiv-state via akzent-farbe. Footer mit © + Impressum
+ "Nostr-basiert"-hinweis.

Assets: profilbild und favicons aus dem hugo-static (repo-root) nach
app/static/ übernommen, favicon-links in app.html ergänzt.

NIP-05: .well-known/nostr.json in app/static angelegt mit CORS-header
via .htaccess, damit "joerglohrer@joerg-lohrer.de" nach cutover
verifizierbar bleibt.

E2E-Tests angepasst an neue hero/navigation-struktur, 29/29 unit + 4/4
e2e grün.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 15:35:05 +02:00