Commit Graph

166 Commits

Author SHA1 Message Date
Jörg Lohrer 10bdf603a9 fix(spa): %sveltekit.head% nicht im app.html-kommentar erwaehnen
User-feedback: kommentar-inhalt aus app.html erschien sichtbar im
body der detail-seiten. Ursache: SvelteKit ersetzt jeden vorkommen
von %sveltekit.head%, auch innerhalb von HTML-kommentaren. Mein
beschreibender kommentar erwaehnte das wort als beispiel — wurde
dann zur build-zeit durch tatsaechliche head-tags ersetzt, was den
kommentar-block aufbrach (eingefuegte tags enthalten >, das schliesst
den kommentar) und den rest des kommentar-textes in den body
wandern liess.

Fix: kommentar umformuliert, sodass der platzhalter-name nicht mehr
woertlich vorkommt ("via SvelteKit-head-injection" statt "via
%sveltekit.head%").

Live-verifiziert auf banksy-high-court-prophet — body startet jetzt
sauber mit <header>.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:02:18 +02:00
Jörg Lohrer f6824019c8 feat(deploy): snapshot vor svelte-build im deploy-skript
Damit DEPLOY_TARGET=svelte/staging/prod immer mit aktuellem
snapshot/output baut. Ohne diesen step wuerde ein veralteter
snapshot ins HTML wandern, frische posts oder uebersetzungen
saessen erst beim naechsten deploy drin.

Schlaegt der snapshot fehl (relays down, env fehlt), bricht das
skript ab — bewusst hard-fail, damit kein verfaelschter build
hochgeladen wird.

Live-verifiziert auf https://svelte.joerg-lohrer.de/bibel-selfies/:
- HTTP 200, og-tags + hreflang + json-ld korrekt
- __SITE_URL__-substitution greift sauber
- <title>, og:title, json-ld stimmen mit snapshot ueberein

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:55:53 +02:00
Jörg Lohrer 3e31caacef fix(spa): prerender-build laeuft + meta/json-ld korrekt
Drei build-blocker beim ersten prerender-versuch identifiziert und gefixt:

1. svelte.config.js: handleHttpError + handleMissingId fuer den
   prerender-crawler. Der crawler folgt zur build-zeit allen hrefs/srcs
   im HTML — sieht dabei
   - __SITE_URL__-platzhalter in canonical/hreflang (werden im deploy
     per sed ersetzt, sind keine echten routes)
   - relative bild-paths in alten posts (z.B. h01-json-import.png)
   - anchor-links auf headings ohne id-attribute (#ACF-JSON-Export)
   Alle drei sind keine echten 404s — handlers ignorieren sie.

2. +page.svelte: <script type="application/ld+json">{jsonLd}</script>
   in <svelte:head> rendert {jsonLd} als literalen string, weil svelte
   den script-tag-inhalt nicht als expression evaluiert. Zurueck zu
   {@html ...} mit </script>-escape-hardening, damit titel oder
   beschreibungen mit </script> den output nicht aufbrechen koennen.

3. app.html behaelt seine homepage-defaults fuer og:title/og:url/
   og:description/canonical — der prerender-crawler rendert nur
   detail-routen (/<slug>/), die homepage bleibt SPA-only und braucht
   die defaults im app.html-template, weil dort kein svelte:head greift.
   Detail-routen ueberschreiben per <svelte:head>; last-wins greift bei
   LinkedIn/Mastodon/Browser. Facebook/Twitter (first-wins) haetten
   einen homepage-prerender-schritt noetig — folge-aufgabe.

Plus snapshot/deno.lock committed — deno empfiehlt lockfile-commit fuer
reproduzierbare CI-builds, analog package-lock.json.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:50:27 +02:00
Jörg Lohrer 2ad27adf1f feat(spa): snapshot-pfad mit reactions/replies/langs/tags
Snapshot-pfad bekommt feature-paritaet mit dem runtime-fallback:
- Sprach-switcher (inline, gleiche optik wie LanguageAvailability,
  ohne neue i18n-keys — verwendet snapshot.translations direkt)
- Tag-liste mit links auf /tag/<name>/
- Reactions, ExternalClientLinks, ReplyComposer, ReplyList
  (alle dtag-basiert, brauchen keine NostrEvent-konstruktion)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:46:12 +02:00
Jörg Lohrer 4e4a5efa42 docs: plan-korrektur — svelte:head muss top-level stehen
Bei der umsetzung von task 4.2 stellte sich heraus, dass svelte
<svelte:head> nicht in einem {#if}-block stehen darf. Plan-code
korrigiert von

  {#if snapshot}<svelte:head>...</svelte:head>{/if}

zu

  <svelte:head>{#if snapshot}...{/if}</svelte:head>

Semantisch identisch (head-content erscheint nur wenn snapshot da ist),
aber svelte-konform.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:42:07 +02:00
Jörg Lohrer 63e59bffb9 feat(spa): post-detail rendert prerendered aus snapshot
Snapshot-pfad: page+head komplett aus json, mit og/twitter/jsonld/hreflang.
Runtime-fallback: falls data.snapshot null, loadPost+PostView wie bisher.
Reactions/replies kommen im naechsten task.

svelte:head auf top-level verschoben (svelte-constraint: keine meta-tags
innerhalb von {#if}-bloecken erlaubt).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:41:11 +02:00
Jörg Lohrer b5772b8aa2 feat(spa): detail-route auf prerender + ssr=true
Lokaler override des global ssr=false. entries() liest aus
snapshot/output/index.json, load() pro-slug aus posts/<slug>.json.
runtime-fallback bleibt fuer slugs ausserhalb des snapshots.

@types/node als devDependency ergaenzt, da node:fs/promises-Typen
fuer den SSR-Pfad benoetigt werden.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:40:17 +02:00
Jörg Lohrer 3fa85fcb07 ci: snapshot-step nach publish + output als artifact
Etappe 3 des prerender-snapshot-plans (variante 1: minimal — kein
neuer workflow, deploy bleibt manuell via scripts/deploy-svelte.sh):

- 'Snapshot'-step laeuft nach publish, ruft deno-snapshot-cli auf
- output (index.json + posts/*.json + .last-snapshot.json) wird als
  github-actions-artifact fuer 30 tage aufgehoben — debug-pfad falls
  ein deploy-bug nachvollzogen werden muss
- AUTHOR_PUBKEY_HEX + BOOTSTRAP_RELAY werden aus existierenden secrets
  uebernommen, keine neuen secrets noetig

Reihenfolge "publish dann snapshot": neue events muessen erst auf den
relays sein, bevor sie gesnapshottet werden koennen. Bei publish-fail
laeuft snapshot nicht — gewollt, weil unklarer relay-stand zu
fehlerhaftem snapshot-output fuehren wuerde.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:37:59 +02:00
Jörg Lohrer 2c4bceb768 fix(snapshot): cache akkumuliert deletedCoords + timeout-kommentar
Code-review-feedback aus etappe 2.9/2.10:

1. cli.ts: deletedCoords im cache wird ab jetzt akkumuliert statt
   ersetzt. Vorher wurden bei einem run nur die aktuell von relays
   gelieferten kind:5-coords geschrieben — wenn ein relay beim
   naechsten run die alten deletions nicht mehr liefert (GC,
   relay-tausch), waere die geschichte verloren und newDeletionsCount
   im naechsten lauf wieder "neu" -> false-positive hard-fail im
   drop-check.

2. relays.ts: kommentar zum belt-and-suspenders-setTimeout neben dem
   RxJS-timeout-operator, damit der zweck (handle-cleanup falls beide
   subscribe-callbacks verschluckt werden) klar ist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:27:12 +02:00
Jörg Lohrer d7bb62d469 feat(snapshot): cli-entrypoint verdrahtet alle module
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:23:55 +02:00
Jörg Lohrer d8a29ca389 feat(snapshot): relay-loader (kind:10002 + event-fetch)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:23:25 +02:00
Jörg Lohrer 10cb0d947d docs(snapshot): multi-lang-TODO fuer translation-inferenz
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:21:08 +02:00
Jörg Lohrer 49c740d908 docs(snapshot): dedup-tie-break dokumentiert
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:21:00 +02:00
Jörg Lohrer 63b68411e4 feat(snapshot): cache validiert format beim lesen
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:20:51 +02:00
Jörg Lohrer 998e08e073 feat(snapshot): config validiert BOOTSTRAP_RELAY-prefix
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:20:29 +02:00
Jörg Lohrer 1827817ad5 docs(snapshot): drop-check-semantik dokumentiert
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:20:01 +02:00
Jörg Lohrer 715c1f5e1e fix(snapshot): tagsAll filtert tags ohne value
Vorher konnten malformed tags wie ['t'] (ohne second element)
undefined ins string[]-array werfen, das im JSON als null landete.
Code-review-feedback aus etappe 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:19:51 +02:00
Jörg Lohrer 848cdf763e fix(snapshot): NIP-09-filter beachtet zeitliche reihenfolge
Per NIP-09 darf ein deletion nur events mit created_at <= deletion.created_at
loeschen. Vorher wurde ein re-publizierter post nach geloeschtem vorgaenger
stumm wegfiltern. Code-review-feedback aus etappe 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:19:20 +02:00
Jörg Lohrer 0755498937 feat(snapshot): output-writer (index.json + posts/<slug>.json)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:12:01 +02:00
Jörg Lohrer a199f1daf1 feat(snapshot): cache-state fuer last-known-good
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:11:36 +02:00
Jörg Lohrer 2af44035b8 feat(snapshot): cover-image-HEAD-probe-modul
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:11:17 +02:00
Jörg Lohrer 4b2c157938 feat(snapshot): post-json-builder mit fallback-summary
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:10:55 +02:00
Jörg Lohrer 7e38b73785 feat(snapshot): plausibilitaets-checks (relay-quorum, drop, min-events)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:10:07 +02:00
Jörg Lohrer ccd7daf14d feat(snapshot): NIP-09-filter
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:09:37 +02:00
Jörg Lohrer 300cd9bea9 feat(snapshot): dedup-by-d-tag
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:09:14 +02:00
Jörg Lohrer 45df54f2b3 feat(snapshot): config-loader mit env-validierung
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:08:46 +02:00
Jörg Lohrer b6366ea1fe feat(snapshot): modul-skelett
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:08:17 +02:00
Jörg Lohrer c391df0d55 chore(render): alte dompurify-deps entfernt + design-rationale-kommentar
Dead-code aus etappe 1 nachgezogen:
- dompurify + @types/dompurify aus package.json (jetzt isomorphic-dompurify
  als einziger sanitizer, bringt eigene typen mit)
- design-rationale-kommentar fuer markedInstance zurueckgebracht
  (Spec §3: lokale ersetzbarkeit der engine — nicht aus dem code ablesbar)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:05:37 +02:00
Jörg Lohrer e0d723df14 feat(render): renderMarkdown auf isomorphic-dompurify umgestellt
Funktioniert jetzt sowohl in Browser/jsdom als auch in Node (SvelteKit-Build).
Schritt 1 der prerender-snapshot-migration. Verhalten in der SPA unveraendert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:00:56 +02:00
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