feat(design): comprehensive redesign — top-tier portfolio UX
Größeres Redesign, das die Seite spürbar besser macht. Behält das
Magenta/Grün-Dark-Thing, poliert aber alles drumherum.
Neue Komponenten:
- hero-banner: full-bleed Hero mit AI-generiertem Hintergrund (grok-imagine-image,
1280×720, Magenta/Grün-Akzente), Terminal-Boot-Animation mit Tipp-Effekt,
Rotating-Role-Animation, animiertes Grid-Overlay.
- command-palette: �K / Ctrl+K öffnet ein durchsuchbares Modal mit Navigation,
Projekt-Suche, Aktionen (Gitea/w-make.com/Admin) und Easter Eggs. Tastatur
↑↓/Enter/Esc, gruppiert nach Typ, mit Vorschau-Hints.
- custom-cursor: Canvas-basierter Cursor mit Trail für Desktop, 14 Punkte,
Farbwechsel Magenta↔Grün, Hover-State für interaktive Elemente. Touch-
Devices behalten den Default-Cursor.
- scroll-progress: Top-Bar mit Magenta→Grün-Gradient.
- tilt-card: 3D-Hover mit Mouse-Tracking (CSS-Variablen --rx/--ry/--mx/--my).
- stack-icon: 13 handgezeichnete inline SVGs (TypeScript, Node, Python, Rust,
SQLite, Tailwind, React, Docker, Gitea, Next, Nix, Hermes, Shell, Self-Host).
Kein CDN, kein Hydration, currentColor-aware.
- project-filter: tag-basierter Filter für Projekt-Liste, Status-Tone-Tags
(live/warm/muted) plus Kategorie-Tags, useTransition für sanfte Updates.
Pages-Update:
- Home (/): neuer Hero-Banner, Featured-Grid mit Tilt-Cards und KI-generierten
Thumbnails (hermes.jpg, casino-bot.jpg, polymarket-trader.jpg), darunter
filterbare Projekt-Liste, Bio + Links Sidebar.
- Projects: filterbar nach Kategorie und Status.
- Project-Detail: Hero-Image (für 3 Projekte), Stack-Pills mit SVG-Icons,
bessere Sektionierung (~/stack, ~/notes).
- About: Stack-Visualisierung mit 13 Einträgen in einem Grid.
- OpenGraph-Image pro Projekt (Next.js native, 1200×630): eldov-Logo,
Projekt-Slug in Magenta, Status-Badge, Kategorie-Badge.
Build-Hash-Support:
- NEXT_PUBLIC_BUILD_HASH + NEXT_PUBLIC_BUILD_DATE werden via Docker ARG in
die Footer geschrieben ("build abc1234 · 2026-08-31"), deploy-vps.sh
ermittelt Commit-Hash automatisch aus git und gibt ihn weiter.
Theme v2:
- Tiefere Palette (--bg #0a0a10, --bg-deep #050508), --fg-dim für Hierarchie.
- Neue Komponenten-Klassen: tilt-card, stack-pill, tag, hero-bg, hero-banner,
scroll-progress, cursor-blink, type-in, glow-text.
- ASCII-Box-Hover-Effekt mit Akzent-Border.
Public-Bilder unter public/img/{hero,projects}/ — KI-generiert via xAI
grok-imagine-image (Token aus .hermes-state/credentials/xai.json), alle
im Marken-Stil (Magenta/Grün/dunkel). 4 Bilder, ~960 KB total.
Sonstiges:
- Header mit ⌘K-Hint, sticky+blur.
- Footer mit Build-Hash, externen Links, Datenschutz-Badge.
- About-Page mit Stack-Grid.
This commit is contained in:
@@ -5,8 +5,15 @@ import { getDict } from "@/i18n/dictionaries";
|
||||
import { LanguageSwitcher } from "./language-switcher";
|
||||
import { MobileNav } from "./mobile-nav";
|
||||
import { site } from "@/content/site";
|
||||
import { CommandPalette } from "./command-palette";
|
||||
|
||||
export function SiteHeader({ locale }: { locale: Locale }) {
|
||||
export function SiteHeader({
|
||||
locale,
|
||||
projects,
|
||||
}: {
|
||||
locale: Locale;
|
||||
projects: Array<{ slug: string; summary: string; category: string; status: string }>;
|
||||
}) {
|
||||
const dict = getDict(locale);
|
||||
const nav = [
|
||||
{ href: publicPath(locale, "about"), label: dict.nav.about },
|
||||
@@ -15,34 +22,63 @@ export function SiteHeader({ locale }: { locale: Locale }) {
|
||||
];
|
||||
|
||||
return (
|
||||
<header className="border-b border-hairline bg-[var(--bg-deep)]">
|
||||
<div className="mx-auto flex max-w-5xl items-center justify-between px-4 py-4">
|
||||
<Link href={publicPath(locale, "home")} className="flex items-center gap-2 font-mono text-sm">
|
||||
<span className="text-accent">$</span>
|
||||
<span className="text-[var(--fg)]">{site.handle}</span>
|
||||
<span className="text-muted">@eldov.win</span>
|
||||
</Link>
|
||||
<nav className="hidden gap-6 md:flex" aria-label="primary">
|
||||
{nav.map((n) => (
|
||||
<Link
|
||||
key={n.href}
|
||||
href={n.href}
|
||||
className="font-mono text-sm text-[var(--fg)] transition-colors hover:text-accent"
|
||||
<>
|
||||
<header className="sticky top-0 z-40 border-b border-hairline bg-[color-mix(in_oklab,var(--bg-deep)_85%,transparent)] backdrop-blur-md">
|
||||
<div className="mx-auto flex max-w-[var(--max-w)] items-center justify-between gap-3 px-4 py-3 md:px-6">
|
||||
<Link href={publicPath(locale, "home")} className="group flex items-center gap-2.5 font-mono text-sm" data-cursor="hover">
|
||||
<span className="inline-flex h-6 w-6 items-center justify-center rounded-sm border border-accent text-[11px] font-bold text-accent transition-colors group-hover:bg-accent group-hover:text-[var(--bg-deep)]">e</span>
|
||||
<span className="text-[var(--fg)]">{site.handle}</span>
|
||||
<span className="hidden text-muted md:inline">@eldov.win</span>
|
||||
</Link>
|
||||
<div className="flex items-center gap-1 md:gap-4">
|
||||
<nav className="hidden gap-1 md:flex" aria-label="primary">
|
||||
{nav.map((n) => (
|
||||
<Link
|
||||
key={n.href}
|
||||
href={n.href}
|
||||
className="rounded px-3 py-1.5 font-mono text-sm text-[var(--fg-dim)] transition-colors hover:bg-[color-mix(in_oklab,var(--accent)_8%,transparent)] hover:text-accent"
|
||||
data-cursor="hover"
|
||||
>
|
||||
{n.label}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
<div className="hidden md:block">
|
||||
<LanguageSwitcher currentLocale={locale} />
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Command palette öffnen"
|
||||
data-cursor="hover"
|
||||
onClick={() => {
|
||||
window.dispatchEvent(new KeyboardEvent("keydown", { key: "k", metaKey: true }));
|
||||
}}
|
||||
className="flex items-center gap-1.5 rounded border border-hairline bg-[color-mix(in_oklab,var(--panel)_50%,transparent)] px-2.5 py-1.5 font-mono text-xs text-muted transition-colors hover:border-accent hover:text-[var(--fg)]"
|
||||
>
|
||||
{n.label}
|
||||
</Link>
|
||||
))}
|
||||
<LanguageSwitcher currentLocale={locale} />
|
||||
</nav>
|
||||
<MobileNav locale={locale} items={nav} menuLabel={dict.nav.menu} switchLabel={dict.actions.languageSwitch} />
|
||||
</div>
|
||||
{locale === defaultLocale ? (
|
||||
<div className="border-t border-hairline bg-[var(--bg-deep)]">
|
||||
<div className="mx-auto max-w-5xl px-4 py-1 font-mono text-xs text-muted">
|
||||
<span className="text-accent">note:</span> geschäftliche Anfragen bitte an w-make.com.
|
||||
<span className="font-mono text-base leading-none">⌘</span>
|
||||
<span>K</span>
|
||||
</button>
|
||||
<MobileNav locale={locale} items={nav} menuLabel={dict.nav.menu} switchLabel={dict.actions.languageSwitch} />
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</header>
|
||||
{locale === defaultLocale ? (
|
||||
<div className="border-t border-hairline-2 bg-[var(--bg-deep)]">
|
||||
<div className="mx-auto max-w-[var(--max-w)] px-4 py-1 font-mono text-[11px] text-muted md:px-6">
|
||||
<span className="text-accent">note:</span>{" "}
|
||||
geschäftliche Anfragen bitte an{" "}
|
||||
<a
|
||||
href="https://w-make.com"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[var(--fg-dim)] underline decoration-dotted underline-offset-2 hover:text-accent"
|
||||
>
|
||||
w-make.com
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</header>
|
||||
<CommandPalette locale={locale} projects={projects} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user