Commit Graph

8 Commits

Author SHA1 Message Date
Jörg Lohrer bb9d35076d chore(spa): toter code aus pre-prerender-aera entfernt
Nach etappe 5 (runtime-fallback entfernt) sind diese files/exports
ohne aufrufer:

Files (ganz weg):
- app/src/lib/components/PostView.svelte
- app/src/lib/components/LanguageAvailability.svelte
- app/src/lib/nostr/translations.ts
- app/src/lib/nostr/translations.test.ts
- app/src/lib/nostr/loaders.loadTranslations.test.ts

Aus app/src/lib/nostr/loaders.ts entfernt:
- loadPost(), loadTranslations(), TranslationInfo
- resolveTranslationsFromRefs() (nur von loadTranslations.test.ts genutzt)
- TranslationRef-import von ./translations

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:25:14 +02:00
Jörg Lohrer 0ec72f9426 refactor(spa): detail-route nur noch snapshot-pfad
Runtime-fallback (loadPost + LoadingOrError + PostView) entfernt.
Detail-seite rendert jetzt ausschliesslich aus dem snapshot. Imports
und state, die nur fuer den fallback gebraucht wurden, sind weg.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:05: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 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 259d7949dd feat(app): post-route + komponenten lokalisiert (titel, datum, hinweise) 2026-04-21 14:13:59 +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 feb336fc5b spa(phase 3, tasks 15-22): routing, komponenten, home, postview
Phase 3 komplett:
- Task 15: LoadingOrError-Komponente (loading/error-states, Habla-Fallback)
- Task 16: app.html mit CSS-Variablen (light/dark), Base-Typography
- Task 17: +layout.svelte mit Container + bootstrapReadRelays onMount
- Task 18: ProfileCard-Komponente (Avatar, Name, About, NIP-05, Website)
- Task 19: PostCard-Komponente (Thumbnail + Titel/Summary/Datum), responsive
- Task 20: +page.svelte als Home (Profil + Liste, Promise.all für beides)
- Task 21: PostView-Komponente (Titel, Meta, Cover, Summary, Markdown-Body)
- Task 22: [...slug]/+page.ts+svelte — Catch-all-Route mit Legacy-301-Redirect

Alle $props()-abhängigen Werte via $derived() (Svelte-5-Runes-Konformität).

npm run check: 0 errors, 0 warnings, 592 files. npm run build grün.

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