Commit Graph

47 Commits

Author SHA1 Message Date
Jörg Lohrer f470732c2c spa(task 13): reactions-loader mit aggregation
loadReactions(dtag) sammelt kind:7-Events mit #a-Filter auf den
Post, gruppiert nach content (emoji oder +/-), zählt und sortiert
nach Häufigkeit. Leerer content wird als + interpretiert (NIP-25-
Konvention für Like-Default).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:21:44 +02:00
Jörg Lohrer bab2895848 spa(task 12): replies-loader für kind:1 mit a-tag-filter
Fügt `loadReplies(dtag)` an loaders.ts an. Filter `#a` auf das
addressable-Event-Format "30023:<pubkey>:<dtag>" findet alle kind:1
Replies auf den Post. Sortiert aufsteigend (älteste zuerst).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:19:21 +02:00
Jörg Lohrer 09f2ce8b49 spa: loader für postlist, post, profile 2026-04-15 16:40:21 +02:00
Jörg Lohrer 078423a1b2 spa: read-relays-store mit bootstrap aus kind:10002 2026-04-15 16:37:41 +02:00
Jörg Lohrer 0bf9bf3bf2 spa: outbox-relay-loader für kind:10002 mit fallback 2026-04-15 16:33:27 +02:00
Jörg Lohrer 6f9f53c561 spa: relaypool-singleton via applesauce-relay 2026-04-15 16:10:06 +02:00
Jörg Lohrer ec9d361a13 spa(task 7 polish): scoped marked-instance, ssr-guard, erweiterte xss-tests
- Eigene `new Marked({...})`-Instanz statt globaler `marked.use()`-Mutation
  — schützt andere Module vor Konfigurationsleckage, schärft Spec §3
  ("lokale Ersetzbarkeit").
- SSR-Guard: `renderMarkdown` wirft in Non-DOM-Umgebungen eine
  Fehlermeldung statt stumm unsicher durchzulaufen. SPA hat `ssr=false`,
  Vitest läuft in jsdom — Guard ist Early-Fail für versehentliche
  Node-Aufrufe.
- `ADD_ATTR: ['target', 'rel']` entfernt — war ein No-Op, weil Marked
  diese Attribute nicht einfügt. Link-Attribut-Hardening kommt später,
  wenn externe Links tatsächlich `target="_blank"` bekommen sollen.
- Code-Block-Test prüft zusätzlich `class="hljs"` (Regression-Anker
  für Custom-Renderer).
- Erweiterte XSS-Matrix: onerror, onclick, iframe, data:text/html,
  vbscript:, svg+script — relevant für spätere Reply-Darstellung.

14/14 Tests grün.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 16:06:51 +02:00
Jörg Lohrer 2bcb2451b4 spa: markdown-renderer mit sanitize (tdd) 2026-04-15 16:03:04 +02:00
Jörg Lohrer 8af049a9ff spa: deploy-script und htaccess für svelte.joerg-lohrer.de
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:59:46 +02:00
Jörg Lohrer 1fb77669e6 spa(task 5 polish): jsdoc auf naddr-helpers, coverage-lücken geschlossen
- JSDoc zu NaddrArgs, buildNaddr, buildHablaLink (Stil konsistent mit config.ts).
- Neue Tests: ohne relays (Default-`?? []`-Pfad), unterschiedliche Inputs
  erzeugen unterschiedliche Links (Guard gegen konstanten Rückgabewert).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:21:36 +02:00
Jörg Lohrer c539c4fee3 spa: naddr/habla-link-helper (tdd) 2026-04-15 15:18:41 +02:00
Jörg Lohrer 36dd76a88f spa(task 4 polish): decodeURIComponent crash-safe, edge-case-tests
- decodeURIComponent in try/catch (malformed URI encoding crasht
  den SPA-Boot-Path nicht mehr, returned stattdessen null).
- JSDoc präzisiert: erwartet nur Pfad ohne Query/Fragment.
- Neue Tests: malformed %E0 → null, leerer dtag → null,
  round-trip Legacy → canonical.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:17:38 +02:00
Jörg Lohrer 47decd9b70 spa: url-parser für legacy-hugo-urls (tdd) 2026-04-15 15:14:35 +02:00
Jörg Lohrer bf3d82d266 spa(task 3 polish): config-konstanten immutable, klarere timeout-doku
- FALLBACK_READ_RELAYS als `as const` tuple (kein mutables Array).
- BOOTSTRAP_RELAY als erster Eintrag referenziert statt dupliziert.
- Präzisere JSDoc zu HABLA_BASE (klarmacht, dass /a/ baked-in ist).
- Timeout-Kommentare trennen soft (per-Relay) vs. hard (Page-Budget).

Code-Quality-Nitpicks aus Task 3 Review adressiert. npm run check grün.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:12:30 +02:00
Jörg Lohrer b5fbfb0e85 spa: nostr-konfigurations-modul mit pubkey, bootstrap-relay, fallbacks 2026-04-15 15:10:17 +02:00
Jörg Lohrer bc02a80e10 spa(task 2): runtime- und dev-dependencies installiert
Runtime: applesauce-core/relay/loaders/signers, nostr-tools, marked,
dompurify, highlight.js, rxjs.

Dev: vitest, @playwright/test, @testing-library/svelte, jsdom,
@types/dompurify.

vite.config.ts um vitest-Konfiguration erweitert (jsdom, globals,
tests/unit/**). package.json um test:unit, test:e2e, deploy:svelte
npm-Scripts ergänzt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:09:10 +02:00
Jörg Lohrer 5b9773ccd3 spa(task 1): sveltekit-skeleton mit adapter-static initialisiert
- sv create minimal template, TypeScript, ohne addons
- adapter-static statt adapter-auto (fallback: index.html)
- ssr=false, prerender=false, trailingSlash=always im layout.ts
- build produziert statisches build/ (getestet)
- .gitignore um package-lock.json und *.log ergänzt

Svelte 5 mit Runes, SvelteKit 2.57, TypeScript 6, Vite 8.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:03:15 +02:00
Jörg Lohrer 64640a5eed Merge branch 'main' into spa 2026-04-15 14:57:27 +02:00
Jörg Lohrer 937e356f4c plan: sveltekit-spa implementierung (35 tasks, 6 phasen)
Deckt die vollständige SPA-Spec ab: Setup + adapter-static, Daten-
ebene (Relay-Pool, Loader, Profil, Markdown, Signer), Routing mit
Legacy-URL-Normalisierung, Tag-Filter, Reactions, NIP-07-Kommentare.
TDD für pure Transformationen (URL-Parser, naddr, Markdown), E2E mit
Playwright für Happy-Paths.

Deploy-Ziel: svelte.joerg-lohrer.de. spa.joerg-lohrer.de bleibt als
Vanilla-Mini-Spike-MVP erhalten (Referenz-Verhalten).

Publish-Pipeline hat eigene Spec und bekommt separaten Plan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:57:26 +02:00
Jörg Lohrer 3bcc4a7170 Merge branch 'main' into spa 2026-04-15 14:46:34 +02:00
Jörg Lohrer 841b183b3c spec(spa): kurze form /<dtag>/ als kanonische url
Revidiert das URL-Schema: die lange Hugo-Form /YYYY/MM/DD/<dtag>.html/
wird als Legacy behandelt, die kurze Form /<dtag>/ als kanonisch.

Gründe: schöner zu teilen, skaliert über die 18 Altposts hinaus,
Datumskomponente fügt keinen Informationswert (Datum steht im Event
als published_at).

Legacy-URLs werden clientseitig via history.replaceState ohne Reload
auf die kurze Form normalisiert — Backlinks bleiben funktional,
Bookmarks konvergieren zur kurzen Form. Keine .htaccess-Redirects.

Im Mini-Spike bereits umgesetzt und live auf spa.joerg-lohrer.de.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:46:33 +02:00
Jörg Lohrer 1147980f2a spike(spa-mini): legacy-hugo-urls auf kurze form normalisieren
/YYYY/MM/DD/<dtag>.html/ wird erkannt, via history.replaceState auf
die kanonische Form /<dtag>/ umgeschrieben, dann der Post geladen.
Externe Backlinks auf alte Hugo-URLs landen damit ohne Reload-Flash
auf der neuen kurzen Adresse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:44:25 +02:00
Jörg Lohrer fc6e0fecdb spike(spa-mini): profilkachel auf der startseite
Lädt kind:0-Metadata-Event des Autors parallel zur Beitragsliste und
zeigt Avatar, Anzeigename, About-Text, NIP-05 und Website oben auf
der Übersichtsseite. Einzelpost-Seiten bleiben fokussiert, ohne
Profil-Header.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:37:32 +02:00
Jörg Lohrer 2e18e68907 Merge branch 'main' into spa 2026-04-15 14:31:21 +02:00
Jörg Lohrer db86b7dd23 spec(spa): daten-transparenz statt stilles dedup
Die produktive SPA soll Events wahrheitsgetreu darstellen und nicht
defensiv korrigieren. Daten-Anomalien (doppelte t-Tags etc.) bleiben
sichtbar, damit der Autor sie wahrnimmt. Bereinigung gehört in
separate Audit-Werkzeuge, nicht in die SPA-Renderlogik.

Der Mini-SPA-Spike dedup'te pragmatisch — explizit als Abweichung
vom Zielverhalten vermerkt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:31:20 +02:00
Jörg Lohrer 865e429c5a spike(spa-mini): tag-dedup + cover-bild-größe begrenzen
- tagsAll() dedupliziert Werte (Schutz gegen Clients, die doppelte
  t-Tags ins Event schreiben; real beobachtet bei einem existierenden
  Post mit zweimal "relilab").
- Cover-Bild in der Einzelansicht auf max 480px Breite + zentriert,
  damit es nicht die gesamte Viewportbreite füllt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:29:57 +02:00
Jörg Lohrer f070ea33c0 spike(spa-mini): url-routing, post-liste mit thumbnails, streaming-load
Liest dtag aus URL-Pfad (SPA-Navigation via History-API) und zeigt
Liste auf /, Einzelpost auf /<dtag>/. Interne Links ohne Reload,
Browser-Back funktioniert.

Streaming-Load via pool.subscribeMany: Events werden angezeigt,
sobald das erste Relay antwortet, statt auf alle 5 zu warten.
Deutlich bessere Reaktionszeit.

Liste mit Cover-Thumbnail links, Titel+Summary+Datum rechts.
Responsive: unter 480px stapelt sich Bild über Text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:21:34 +02:00
Jörg Lohrer 1ae6445c84 spike(spa-mini): responsive layout + erläuterungstext nach oben
- Erklärung zur Implementierungstechnik als Intro-Box direkt unter dem
  Tech-Spike-Banner (statt versteckt im Footer).
- Footer reduziert auf einen Link zum Quellcode.
- Mobile-Anpassungen: kleinerer Title auf < 640px, weniger Padding,
  Tags wrappen sauber, lange URLs/Code/Tabellen brechen ohne Overflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:03:10 +02:00
Jörg Lohrer 0679a335f4 spike(spa-mini): vanilla-html viewer für einen einzelnen nostr-post
Tech-Spike unter preview/spa-mini/ — eine index.html, lädt
nostr-tools/marked/DOMPurify von esm.sh, holt das kind:30023-Event
mit dtag dezentrale-oep-oer von 5 public-relays, rendert clientseitig.
Beweist, dass die SPA-Architektur in der Praxis funktioniert, ohne
SvelteKit-Build-Pipeline.

Inhalt:
- index.html mit Loader, Renderer, Fehler-Handling
- .htaccess mit SPA-Fallback (relevant sobald gehostet)
- README mit Anleitung lokal/Deploy

.gitignore um .env*, logs/ ergänzt (für späteren Pipeline-Bedarf).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 13:53:16 +02:00
Jörg Lohrer 4251fee668 spec(spa): erläuterung warum webspace für sveltekit ausreicht
Häufige Sorge ("kann mein einfaches Webspace-Paket SvelteKit hosten?")
explizit beantwortet: SvelteKit mit adapter-static produziert reine
statische Dateien, exakt analog zu Hugos public/. Webspace, FTP und
.htaccess reichen vollständig — keine Node-Runtime, keine Datenbank,
kein vServer nötig.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 13:46:45 +02:00
Jörg Lohrer febb3147fb spec(publish): pipeline für nostr-events via deno + amber + rsync
Publish-Pipeline für den Weg Markdown → signiertes kind:30023 → Relays,
plus Bilder-Upload (Legacy: rsync zu All-Inkl für die 18 Altposts;
Blossom: BUD-01-Upload für neue Posts).

Kernpunkte:
- Deno-Runtime, gemeinsame Library und CLI für lokal + GitHub Action
- NIP-46 Bunker (Amber-Stufe, später Optiplex-Stufe ohne Code-Change)
- Relay- und Blossom-Server-Listen via kind:10002 / kind:10063
  (manuell einmalig publiziert, identisch mit SPA-Nutzung)
- Git-Diff als Change-Detection, --force-all für Migration/Reimport
- State-los im Repo, keine Lock-Files, keine Commits zurück
- Pre-Flight `deno task check` validiert alle Voraussetzungen

Beziehung zur SPA-Spec: gemeinsame Event-Verträge (kind:30023, 10002,
10063) sind in dieser Spec normativ; SPA-Spec verweist darauf.
Publish läuft einmalig für die 18 Altposts (SPA-Migrationsschritt C)
vor dem SPA-Cutover (Schritt D).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:07:33 +02:00
Jörg Lohrer 6a4db658c6 spec(spa): relay-liste aus kind:10002 statt hartcodiert
Die Relay-Liste wird zur Laufzeit aus dem NIP-65-Outbox-Event geholt
(via Bootstrap-Relay), mit hartcodierter Fallback-Liste als Sicherheit.
Damit teilen SPA und Publish-Pipeline eine gemeinsame Quelle der
Wahrheit für Relay-Konfiguration — Änderungen erfordern nur ein neues
Event, keinen Code-Deploy.

Publish-Spec wird das normative Schema für kind:10002 und kind:10063
definieren; SPA-Spec verweist darauf.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:02:20 +02:00
Jörg Lohrer d17410fb18 normalize: slugs lowercase und url-kompatibel
Vereinheitlicht die slug-Frontmatter-Werte auf lowercase-Form, passend
zu den tatsächlich von Hugo erzeugten URLs (die lagen ohnehin schon
lowercase auf All-Inkl). Damit sind die slugs identisch mit den
späteren Nostr-d-Tags, keine Runtime-Normalisierung nötig.

7 Posts angepasst:
- Pflanzenschild-QR-Code → pflanzenschild-qr-code
- WordPress-Werkstatt → wordpress-werkstatt
- OB-virtualcam → ob-virtualcam
- Dampfnudeln → dampfnudeln
- BottomUp-MarkDown → bottomup-markdown
- 'KIBedenken - Bewusstsein' → kibedenken-bewusstsein
- 'Gemeinsam die Bildungszukunft gestalten: Dezentrale OEP und OER…' → dezentrale-oep-oer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 10:38:38 +02:00
Jörg Lohrer 8dc6e061ff main: hugo-artefakte entfernt, bereit für nostr-spa-entwicklung
Entfernt: themes/, public/, resources/, layouts/, assets/, archetypes/,
hugo.toml, .hugo_build.lock, .gitmodules. Kompletter Hugo-Stand ist
im Orphan-Branch 'hugo-archive' eingefroren.

Behalten auf main: content/ (markdown-quelle für publish-skript),
docs/ (specs), static/ (favicons, profilbild), .claude/, LICENSE.

README überarbeitet mit Branch-Übersicht.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:51:05 +02:00
Jörg Lohrer 3a5c4d1e00 archive: final hugo build mit neuem post dezentrale-oep-oer
Letzter Commit vor Transition zu nostr-spa. Beinhaltet:
- neuer Post 2025-03-04-dezentrale-oep-oer (content + Hugo-Build)
- aktualisierte public/*.html nach Mastodon-Comment-Entfernung
- .claude/ als Transparenz-Spur der Sessions
- .DS_Store aus Index entfernt (bleibt ignoriert)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:49:26 +02:00
Jörg Lohrer 4918175f8b spec: nostr-page auf basis von events — design
SvelteKit-SPA, die Blog-Posts live aus signierten kind:30023-Events
von Public-Relays rendert. Ablösung der Hugo-Seite auf All-Inkl ohne
eigene Infrastruktur in Phase 1; Stubs, eigener Relay und Blossom als
Evolutionspfad.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:25:11 +02:00
Jörg Lohrer 78c6b0be51 comment integration ohne styling 2025-02-12 19:43:36 +01:00
Jörg Lohrer d755fd82c2 fix ERROR deprecated: .Site.Social was deprecated in Hugo v0.124.0 and will be removed in Hugo 0.143.0. Implement taxonomy 'social' or use .Site.Params.Social instead. with hogo.toml 2025-02-01 07:52:15 +01:00
Jörg Lohrer 1b069f98d4 yaml cover images ergänzt 2025-02-01 07:44:21 +01:00
Jörg Lohrer e9dc55e9fd + gitignore DS_Store 2025-02-01 06:52:16 +01:00
Jörg Lohrer 15ddf4e777 neu 2025-02-01 06:42:08 +01:00
Jörg Lohrer af72263ca9 umbau 2025-01-28 18:18:59 +01:00
Jörg Lohrer 4e9300b1e0 update 2 2024-12-03 17:02:00 +01:00
Jörg Lohrer 094c0a6203 icons 2024-11-06 17:57:18 +01:00
joerglohrer 3f04f53d7c README.md aktualisiert 2024-11-06 16:01:59 +01:00
joerglohrer 2f2706e4e4 README.md aktualisiert 2024-11-06 16:00:13 +01:00
Jörg Lohrer 5f7696d6ae Initial commit 2024-11-06 15:55:54 +01:00