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
|
|
|
|
<script lang="ts">
|
|
|
|
|
|
import { onMount } from 'svelte';
|
|
|
|
|
|
import type { NostrEvent, Profile } from '$lib/nostr/loaders';
|
2026-04-15 17:58:44 +02:00
|
|
|
|
import { loadPostList } from '$lib/nostr/loaders';
|
|
|
|
|
|
import { getProfile } from '$lib/nostr/profileCache';
|
|
|
|
|
|
import { AUTHOR_PUBKEY_HEX } from '$lib/nostr/config';
|
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
|
|
|
|
import PostCard from '$lib/components/PostCard.svelte';
|
|
|
|
|
|
import LoadingOrError from '$lib/components/LoadingOrError.svelte';
|
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
|
|
|
|
import SocialIcons from '$lib/components/SocialIcons.svelte';
|
|
|
|
|
|
|
|
|
|
|
|
// Lokales Profilbild aus static/ — schneller als der Nostr-kind:0-Roundtrip
|
|
|
|
|
|
// fürs kind:0 -> picture-Feld (URL wäre identisch, aber Netzwerk-Latenz).
|
|
|
|
|
|
const HERO_AVATAR = '/joerg-profil-2024.webp';
|
|
|
|
|
|
const LATEST_COUNT = 5;
|
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
|
|
|
|
|
|
|
|
|
|
let profile: Profile | null = $state(null);
|
|
|
|
|
|
let posts: NostrEvent[] = $state([]);
|
|
|
|
|
|
let loading = $state(true);
|
|
|
|
|
|
let error: string | null = $state(null);
|
|
|
|
|
|
|
|
|
|
|
|
onMount(async () => {
|
|
|
|
|
|
try {
|
2026-04-15 17:58:44 +02:00
|
|
|
|
const [p, list] = await Promise.all([getProfile(AUTHOR_PUBKEY_HEX), loadPostList()]);
|
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
|
|
|
|
profile = p;
|
|
|
|
|
|
posts = list;
|
|
|
|
|
|
loading = false;
|
|
|
|
|
|
if (list.length === 0) {
|
|
|
|
|
|
error = 'Keine Posts gefunden auf den abgefragten Relays.';
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
loading = false;
|
|
|
|
|
|
error = e instanceof Error ? e.message : 'Unbekannter Fehler';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$effect(() => {
|
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
|
|
|
|
const p = profile;
|
|
|
|
|
|
const name = (p && (p.display_name ?? p.name)) ?? 'Jörg Lohrer';
|
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
|
|
|
|
document.title = `${name} – Blog`;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
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
|
|
|
|
const displayName = $derived.by(() => {
|
|
|
|
|
|
const p = profile;
|
|
|
|
|
|
return (p && (p.display_name ?? p.name)) ?? 'Jörg Lohrer';
|
|
|
|
|
|
});
|
|
|
|
|
|
const avatarSrc = HERO_AVATAR;
|
|
|
|
|
|
const about = $derived.by(() => profile?.about ?? '');
|
|
|
|
|
|
const website = $derived.by(() => profile?.website ?? '');
|
|
|
|
|
|
const latest = $derived(posts.slice(0, LATEST_COUNT));
|
|
|
|
|
|
const hasMore = $derived(posts.length > LATEST_COUNT);
|
|
|
|
|
|
</script>
|
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
|
|
|
|
|
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
|
|
|
|
<section class="hero">
|
|
|
|
|
|
<div class="hero-left">
|
|
|
|
|
|
<img class="avatar" src={avatarSrc} alt={displayName} />
|
|
|
|
|
|
<SocialIcons />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="hero-text">
|
|
|
|
|
|
<h1 class="hero-name">{displayName}</h1>
|
|
|
|
|
|
<p class="hero-greeting">
|
|
|
|
|
|
Hi <span aria-hidden="true">🖖</span> Willkommen auf meinem Blog
|
|
|
|
|
|
<span aria-hidden="true">🤗</span>
|
|
|
|
|
|
</p>
|
|
|
|
|
|
{#if about}
|
|
|
|
|
|
<p class="hero-about">{about}</p>
|
|
|
|
|
|
{/if}
|
|
|
|
|
|
{#if website}
|
|
|
|
|
|
<div class="meta-line">
|
|
|
|
|
|
<a href={website} target="_blank" rel="noopener">
|
|
|
|
|
|
{website.replace(/^https?:\/\//, '').replace(/\/$/, '')}
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{/if}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
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
|
|
|
|
|
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
|
|
|
|
<section class="latest">
|
|
|
|
|
|
<h2 class="section-title">Neueste Beiträge</h2>
|
|
|
|
|
|
<LoadingOrError {loading} {error} />
|
|
|
|
|
|
{#each latest as post (post.id)}
|
|
|
|
|
|
<PostCard event={post} />
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
{#if hasMore}
|
|
|
|
|
|
<div class="more">
|
|
|
|
|
|
<a href="/archiv/" class="more-link">Alle Beiträge im Archiv →</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{/if}
|
|
|
|
|
|
</section>
|
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
|
|
|
|
|
|
|
|
|
|
<style>
|
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
|
|
|
|
.hero {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 1.25rem;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
padding: 1rem 0 2rem;
|
|
|
|
|
|
margin-bottom: 1.5rem;
|
|
|
|
|
|
border-bottom: 1px solid var(--border);
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-left {
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
.avatar {
|
|
|
|
|
|
width: 96px;
|
|
|
|
|
|
height: 96px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
background: var(--code-bg);
|
|
|
|
|
|
border: 2px solid var(--accent);
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-text {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-name {
|
|
|
|
|
|
margin: 0 0 0.3rem;
|
|
|
|
|
|
font-size: 1.6rem;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-greeting {
|
|
|
|
|
|
margin: 0 0 0.5rem;
|
|
|
|
|
|
font-size: 1.05rem;
|
|
|
|
|
|
color: var(--fg);
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-about {
|
|
|
|
|
|
margin: 0 0 0.5rem;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
|
line-height: 1.45;
|
|
|
|
|
|
}
|
|
|
|
|
|
.meta-line {
|
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.meta-line a {
|
|
|
|
|
|
color: var(--accent);
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.meta-line a:hover {
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
}
|
|
|
|
|
|
.section-title {
|
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
|
|
|
|
margin: 0 0 1rem;
|
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
|
|
|
|
font-size: 1.25rem;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
.more {
|
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.more-link {
|
|
|
|
|
|
color: var(--accent);
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
.more-link:hover {
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 520px) {
|
|
|
|
|
|
.hero {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
gap: 0.8rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-left {
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
|
</style>
|