rebuild the web theme as a physical desk (walnut surface, monitor + keyboard, real rack, drive drawer, paper tags, dot-matrix report, brass plaques)

This commit is contained in:
Martin Dvořák 2026-09-30 09:09:47 +00:00
commit cfc256c7bd
9 changed files with 1604 additions and 869 deletions

View file

@ -1,13 +1,17 @@
"use client";
import { useState } from "react";
import { useState, type CSSProperties } from "react";
import { useTheme } from "./useTheme";
import { codingProjects, friends, socials, techProjects } from "../data";
import {
Bay,
ContributionsPanel,
Keyboard,
Led,
MiniRack,
Monitor,
Plaque,
Report,
Reveal,
SectionHead,
ServiceUnit,
SocialGlyph,
type ServiceAccess,
@ -17,10 +21,10 @@ import {
const NAV = [
{ href: "#about", label: "about" },
{ href: "#services", label: "rack" },
{ href: "#services", label: "services" },
{ href: "#projects", label: "projects" },
{ href: "#hardware", label: "inventory" },
{ href: "#contact", label: "ports" },
{ href: "#hardware", label: "machines" },
{ href: "#contact", label: "contact" },
];
const SERVICES: {
@ -40,20 +44,9 @@ const SERVICES: {
];
const LIFTS = [
{ lift: "squat", weight: "125", unit: "kg", date: "05 Jan 2025" },
{ lift: "bench", weight: "111", unit: "kg", date: "29 May 2026" },
{ lift: "deadlift", weight: "165", unit: "kg", date: "17 Dec 2024" },
];
const NEOFETCH: [string, string][] = [
["host", "Proxmox VE · home rack"],
["os", "Gentoo Linux (x86_64)"],
["cpu", "Xeon E5-2680 v4 · 14c/28t"],
["gpu", "RTX 3070 · passthrough"],
["memory", "68 GB DDR4 RDIMM"],
["storage", "256 GB NVMe · 1 TB · 750 GB"],
["services", "6 containers, 0 subscriptions"],
["uptime", "17 years"],
{ lift: "squat", weight: "125", date: "05 Jan 2025" },
{ lift: "bench", weight: "111", date: "29 May 2026" },
{ lift: "deadlift", weight: "165", date: "17 Dec 2024" },
];
/** Titles carry their state in parentheses, e.g. "dxdwm (Discontinued)". */
@ -62,12 +55,12 @@ function splitStatus(title: string) {
return m ? { name: m[1], status: m[2] } : { name: title, status: null };
}
function statusKind(status: string | null): "green" | "amber" | "red" | "off" {
function statusKind(status: string | null): "on" | "amber" | "off" {
if (!status) return "off";
const s = status.toLowerCase();
if (s.includes("finished") || s.includes("available")) return "green";
if (s.includes("finished") || s.includes("available")) return "on";
if (s.includes("wip") || s.includes("unfinished")) return "amber";
return "red";
return "off";
}
/* ------------------------------------------------------------------ page */
@ -76,30 +69,19 @@ export default function WebSite() {
const { setTheme } = useTheme();
const [menuOpen, setMenuOpen] = useState(false);
const stats = [
{ value: String(SERVICES.length), label: "self-hosted services" },
{ value: String(codingProjects.length), label: "projects on the shelf" },
{ value: String(techProjects.length), label: "machines logged" },
{ value: "401", label: "kg best SBD total" },
];
return (
<div className="w-root">
{/* ----------------------------------------------------------- rail */}
<header className="w-rail w-metal-flat" style={{ borderRadius: 0 }}>
<div className="shell flex h-16 items-center gap-5">
<a href="#top" className="flex shrink-0 items-center gap-3" aria-label="Back to top">
<Led kind="green" pulse />
<span className="w-rack__title">dvorakmortonxd.local</span>
<div className="w-page">
{/* -------------------------------------------------------------- rail */}
<header className="w-rail w-mt-metal-flush" style={{ borderRadius: 0 }}>
<div className="mx-auto flex h-16 w-full max-w-[1120px] items-center gap-5 px-5 sm:px-8">
<a href="#top" className="flex shrink-0 items-center gap-2.5" aria-label="Back to top">
<Led kind="on" pulse slow />
<span className="w-wordmark w-engrave">dvorakmortonxd</span>
</a>
<nav className="ml-auto hidden items-center gap-6 md:flex" aria-label="Main">
{NAV.map((item) => (
<a
key={item.href}
href={item.href}
className="w-navlink"
>
<a key={item.href} href={item.href} className="w-navlink">
{item.label}
</a>
))}
@ -109,15 +91,16 @@ export default function WebSite() {
<button
type="button"
aria-label="Switch to Desktop mode"
data-desktop-mode="off"
onClick={() => setTheme("skeuo")}
className="desktop-toggle flex items-center gap-3"
title="Flip to Desktop mode"
>
<span className="w-plate">desktop</span>
<span className="w-switch">
<span className="w-switch__knob" />
<Led kind="off" className="w-switch__led" />
<span className="w-mono hidden text-[0.6rem] tracking-[0.2em] text-[var(--ftext-faint)] sm:inline">
DESKTOP
</span>
<span className="w-rocker">
<span className="w-rocker__knob" />
<Led kind="off" className="w-rocker__led" />
</span>
</button>
@ -127,7 +110,7 @@ export default function WebSite() {
onClick={() => setMenuOpen((v) => !v)}
aria-expanded={menuOpen}
aria-label={menuOpen ? "Close menu" : "Open menu"}
className="w-btn px-3 py-2"
className="w-keybtn !px-3 !py-2"
>
{menuOpen ? "close" : "menu"}
</button>
@ -136,13 +119,16 @@ export default function WebSite() {
</div>
{menuOpen ? (
<nav className="shell w-metal-flat mb-3 mt-1 flex flex-col gap-1 p-3 md:hidden" aria-label="Main">
<nav
className="w-mt-metal-flush mx-auto mb-3 flex w-[calc(100%-2.5rem)] max-w-[1120px] flex-col gap-1 rounded-lg p-3 md:hidden"
aria-label="Main"
>
{NAV.map((item) => (
<a
key={item.href}
href={item.href}
onClick={() => setMenuOpen(false)}
className="w-unit__name block border-b border-[rgba(255,255,255,0.06)] py-3"
className="w-mono border-b border-[rgba(255,226,180,0.07)] py-3 text-[0.78rem] text-[var(--ftext-dim)] last:border-b-0"
>
{item.label}
</a>
@ -153,177 +139,205 @@ export default function WebSite() {
<span id="top" />
<main className="pt-16">
{/* --------------------------------------------------------- hero */}
<section className="shell pt-12 pb-14 sm:pt-16">
<Reveal>
<div className="w-rack w-metal">
<div className="w-rack__head">
<Led kind="green" pulse />
<span className="w-rack__title">dvorakmortonxd.local</span>
<span className="w-unit__meta ml-auto hidden sm:block">4U · asus p9x79 · 24/7</span>
<span className="w-screw ml-2 hidden sm:block" />
<span className="w-screw hidden sm:block" />
<main className="pt-24 sm:pt-28">
{/* ------------------------------------------------------------ hero */}
<section className="mx-auto w-full max-w-[1120px] px-5 sm:px-8">
<div className="grid gap-10 lg:grid-cols-[minmax(0,1.5fr)_minmax(0,1fr)] lg:items-end lg:gap-8">
<Reveal>
<Monitor>
<p className="w-tft">
<span className="a">martin@dvorakmortonxd</span>:~$ whoami
<span className="w-caret ml-2" />
</p>
<h1 className="w-serif mt-5 text-[clamp(1.85rem,4.2vw,2.85rem)] text-[var(--ftext)]">
My own little internet — one rack, zero subscriptions.
</h1>
<p className="w-prose mt-5 max-w-[54ch] text-[var(--ftext-dim)]">
I&rsquo;m Martin Dvořák. Git, media, music, an AI box and a Minecraft server all run on a
Proxmox machine in my room — plus the hardware graveyard I keep rescuing from e-waste.
</p>
<p className="mt-7 flex flex-wrap gap-x-8 gap-y-3">
<a href="#services" className="w-cmd">
$ open rack --services
</a>
<a href="#projects" className="w-cmd">
$ open drawer --projects
</a>
</p>
</Monitor>
<div className="-mt-1 px-1 pt-7 sm:px-8">
<Keyboard />
</div>
</Reveal>
<div className="grid gap-3 lg:grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)]">
<div className="w-nameplate min-w-0">
<p className="w-kicker">homelab · czech republic · online</p>
<h1 className="mt-4 text-[2rem] leading-[1.05] sm:text-[2.6rem] lg:text-[3rem]">
My own little internet — one rack, zero subscriptions.
</h1>
<p className="w-prose mt-5 max-w-[48ch]">
I’m Martin Dvořák. Git, media, music, an AI box and a Minecraft server all run on a
Proxmox machine in my room — plus the hardware graveyard I keep rescuing from e-waste.
</p>
<div className="mt-7 flex flex-wrap items-center gap-3">
<a href="#services" className="w-btn w-btn--accent">
<Led kind="amber" /> see what I run
</a>
<a href="#projects" className="w-btn">
open the drive drawer
</a>
</div>
</div>
<div className="w-panel min-w-0 p-4">
<div className="w-rack__head !border-b-0 !pb-2">
<span className="w-rack__title">console — neofetch</span>
<Led kind="green" className="ml-auto" />
</div>
<div className="w-screen-text">
{NEOFETCH.map(([k, v]) => (
<p key={k} className="flex gap-3">
<span className="k w-[8ch] shrink-0">{k}</span>
<span className="v min-w-0 truncate">{v}</span>
</p>
))}
<p className="mt-1">
<span className="k">$</span> <span className="w-cursor" />
</p>
</div>
<Reveal delay={120}>
<div className="flex flex-col gap-6">
<MiniRack />
<div className="grid grid-cols-2 gap-3">
<Plaque value={String(SERVICES.length)} label="services" />
<Plaque value={String(codingProjects.length)} label="projects" />
<Plaque value={String(techProjects.length)} label="machines" />
<Plaque value="401" label="kg best SBD" />
</div>
</div>
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
{stats.map((s) => (
<div key={s.label} className="w-unit w-metal-flat">
<Led kind="amber" />
<span className="min-w-0">
<span className="w-digits block text-[1.5rem] leading-none">{s.value}</span>
<span className="w-unit__meta mt-1 block truncate">{s.label}</span>
</span>
</div>
))}
</div>
</div>
</Reveal>
</Reveal>
</div>
</section>
<div className="shell flex flex-col gap-16 pb-20 sm:gap-24">
{/* -------------------------------------------------------- about */}
<Bay id="about" index="01" label="about" title="Who is behind the rack">
<div className="grid gap-6 md:grid-cols-2">
<Reveal delay={40}>
<article className="w-paper w-card h-full">
<div className="flex items-center gap-3">
<span className="w-grommet" />
<span className="w-kicker !text-[var(--paper-ink-soft)]">manifest.txt</span>
<div className="mx-auto flex w-full max-w-[1120px] flex-col gap-24 px-5 pt-28 pb-24 sm:gap-28 sm:px-8">
{/* --------------------------------------------------------- about */}
<section id="about" className="scroll-mt-28">
<Reveal>
<SectionHead index="01" label="about" title="Who is behind the rack" />
</Reveal>
<div className="grid gap-7 lg:grid-cols-[minmax(0,1.55fr)_minmax(0,1fr)] lg:items-start">
<Reveal delay={60}>
<article className="w-mt-paper w-sheet">
<div className="w-sheet__head">
<span>manifest.txt</span>
<span className="ml-auto">printed on the desk</span>
</div>
<div className="mt-5 grid gap-x-9 gap-y-4 sm:grid-cols-2">
<p className="w-prose">
I&rsquo;m a sophomore at{" "}
<a className="w-link" href="https://sssvt.cz" target="_blank" rel="noopener noreferrer">
sssvt.cz
</a>
, studying network management and administration. I wanted to go there since 7th
grade, so getting in was a good day.
</p>
<p className="w-prose">
I&rsquo;m a homelabber first: my own Git, media, music, AI and game servers, most of it
running on hardware other people threw away.
</p>
<p className="w-prose">
A laptop collection from 2009 to 2025, mostly e-waste rescues — ThinkPads, MacBooks,
a Legion Go, an Xbox with a bad-update exploit and one very dead 2010 unibody.
</p>
<p className="w-prose">
Away from the rack: PPL training 3–5× a week, Terraria (~1300 h), Minecraft modpacks
and the occasional game jam.
</p>
</div>
<p className="w-prose mt-4">
I’m a sophomore at{" "}
<a className="w-link" href="https://sssvt.cz" target="_blank" rel="noopener noreferrer">
sssvt.cz
</a>
, studying network management and administration. I wanted to go there since 7th
grade, so getting in was a good day.
</p>
<p className="w-prose mt-3">
I’m a homelabber first: my own Git, media, music, AI and game servers, most of it
running on hardware other people threw away.
</p>
</article>
</Reveal>
<Reveal delay={130}>
<article className="w-paper w-card w-note--tilt h-full">
<div className="flex items-center gap-3">
<span className="w-grommet" />
<span className="w-kicker !text-[var(--paper-ink-soft)]">inventory.txt</span>
</div>
<p className="w-prose mt-4">
A laptop collection from 2009 to 2025, mostly e-waste rescues — ThinkPads, MacBooks,
a Legion Go, an Xbox with a bad-update exploit and one very dead 2010 unibody.
<Reveal delay={150}>
<aside className="w-mt-paper w-cardindex lg:mt-12">
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[var(--ink-soft)]">
INDEX CARD
</p>
<p className="w-prose mt-3">
Away from the rack: PPL training 3–5× a week, Terraria (~1300 h), Minecraft modpacks
and the occasional game jam.
<p className="w-serif mt-3 text-[1.15rem] text-[var(--ink)]">
&ldquo;If it has a fan, I&rsquo;ll find a use for it.&rdquo;
</p>
</article>
<div className="w-rule my-4" />
<ul className="w-mono space-y-2 text-[0.66rem] text-[var(--ink-soft)]">
<li>school · sssvt.cz</li>
<li>gym · PPL 3–5×/week</li>
<li>games · Terraria, Minecraft</li>
<li>currently · bulking season</li>
</ul>
</aside>
</Reveal>
</div>
</Bay>
</section>
{/* ---------------------------------------------------------- now */}
<Bay id="now" index="02" label="now" title="On the bench right now">
<Reveal delay={40}>
<div className="grid gap-4 lg:grid-cols-[minmax(0,1.25fr)_minmax(0,1fr)]">
<article className="w-paper w-note min-w-0">
<span className="w-kicker !text-[var(--paper-ink-soft)]">now.txt · updated 09/2026</span>
<p className="w-prose mt-4">
I’m hosting an SMP — message me on Discord if you want in. I’m also cooking most days,
bulking through the non-summer seasons.
{/* ----------------------------------------------------------- now */}
<section id="now" className="scroll-mt-28">
<Reveal>
<SectionHead index="02" label="now" title="On the bench right now" />
</Reveal>
<div className="grid gap-7 lg:grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)] lg:items-start">
<Reveal delay={60}>
<div className="w-sticky">
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[#6b6047]">
NOW.TXT · UPDATED 09/2026
</p>
<p className="w-prose mt-3">
<p className="w-prose mt-4 text-[#4a4232]">
I&rsquo;m hosting an SMP — message me on Discord if you want in. I&rsquo;m also cooking most
days, bulking through the non-summer seasons.
</p>
<p className="w-prose mt-3 text-[#4a4232]">
Me and my friend{" "}
<a className="w-link" href="https://skopec.dev" target="_blank" rel="noopener noreferrer">
Pepa
</a>{" "}
are building an education app so we can study more efficiently. It’s called{" "}
<a className="w-link" href="https://git.dvorakmortonxd.dev/edu/maturita.c" target="_blank" rel="noopener noreferrer">
are building an education app so we can study more efficiently. It&rsquo;s called{" "}
<a
className="w-link"
href="https://git.dvorakmortonxd.dev/edu/maturita.c"
target="_blank"
rel="noopener noreferrer"
>
maturita.c
</a>
.
</p>
</article>
</div>
</Reveal>
<div className="w-panel min-w-0 p-4">
<div className="w-rack__head !border-b-0 !pb-2">
<span className="w-rack__title">status</span>
<Led kind="green" pulse className="ml-auto" />
<Reveal delay={140}>
<div className="flex flex-col gap-6">
<div className="w-mt-paper w-cardindex w-cardindex--alt">
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[var(--ink-soft)]">
BENCH STATUS
</p>
<ul className="w-mono mt-3 space-y-2 text-[0.7rem] text-[var(--ink)]">
<li className="flex items-center gap-2">
<Led kind="on" /> smp · accepting players
</li>
<li className="flex items-center gap-2">
<Led kind="amber" pulse /> maturita.c · in development
</li>
<li className="flex items-center gap-2">
<Led kind="on" /> gym · PPL 3–5×/week
</li>
</ul>
</div>
<div className="w-screen-text">
<p><span className="k">smp</span> <span className="v">accepting players</span></p>
<p><span className="k">bulk</span> <span className="v">in progress</span></p>
<p><span className="k">maturita.c</span> <span className="v">in development</span></p>
<p><span className="k">gym</span> <span className="v">PPL · 3–5×/week</span></p>
<i className="w-pencil ml-6 w-44" aria-hidden="true" />
</div>
</Reveal>
</div>
</section>
{/* ------------------------------------------------------ services */}
<section id="services" className="scroll-mt-28">
<Reveal>
<SectionHead index="03" label="rack" title="Six machines, one shelf" />
</Reveal>
<Reveal delay={60}>
<div className="w-mt-metal w-rack">
<div className="w-rack__top">
<Led kind="on" pulse slow />
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">RACK 01 · SERVICES</span>
<span className="w-mono ml-auto hidden text-[0.6rem] tracking-[0.14em] text-[var(--ftext-faint)] sm:inline">
health checked from this page
</span>
<span className="w-rack__vent w-vents" />
</div>
<div className="w-rack__grid">
<span className="w-rails" />
<div>
{SERVICES.map((s) => (
<ServiceUnit key={s.name} {...s} />
))}
</div>
<span className="w-rails" />
</div>
</div>
</Reveal>
</Bay>
</section>
{/* ----------------------------------------------------- services */}
<Bay id="services" index="03" label="rack" title="Rack elevation — live status">
<Reveal delay={40}>
<div className="w-rack w-metal">
<div className="w-rack__head">
<span className="w-rack__title">services</span>
<span className="w-unit__meta ml-auto">checked through this site</span>
</div>
{SERVICES.map((s) => (
<ServiceUnit key={s.name} {...s} />
))}
</div>
{/* ------------------------------------------------------ projects */}
<section id="projects" className="scroll-mt-28">
<Reveal>
<SectionHead index="04" label="drawer" title="Eighteen drives, all labelled" />
</Reveal>
</Bay>
{/* ----------------------------------------------------- projects */}
<Bay id="projects" index="04" label="projects" title="The drive drawer">
<Reveal delay={40}>
<div className="w-drawer w-metal">
<div className="w-drawer__handle mx-auto mb-4 w-40" />
<div className="max-h-[560px] overflow-y-auto pr-1">
<div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
<Reveal delay={60}>
<div className="w-mt-metal w-drawer">
<div className="w-mt-plastic w-drawer__inner w-scroll">
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
{codingProjects.map((p, i) => {
const { name, status } = splitStatus(p.title);
return (
@ -332,131 +346,164 @@ export default function WebSite() {
href={p.url}
target="_blank"
rel="noopener noreferrer"
className="w-caddy w-carbon"
className="w-drive"
style={{ "--tilt": `${i % 2 ? 0.5 : -0.6}deg` } as CSSProperties}
title={p.desc}
>
<Led kind={statusKind(status)} />
<span className="min-w-0 flex-1">
<span className="w-caddy__label block truncate">{name}</span>
<span className="w-caddy__status block truncate">
<span className="w-drive__port" aria-hidden="true" />
<span className="w-drive__sticker">
<span className="w-drive__name">{name}</span>
<span className="w-drive__meta">
{status ?? "unlabelled"} · {p.desc}
</span>
</span>
<Led kind={statusKind(status)} className="w-drive__led" />
</a>
);
})}
</div>
</div>
</div>
</Reveal>
</Bay>
{/* ----------------------------------------------------- hardware */}
<Bay id="hardware" index="05" label="inventory" title="On the pegboard">
<Reveal delay={40}>
<div className="w-pegboard w-metal">
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
{techProjects.map((t) => (
<article key={t.title} className="w-paper w-tag">
<span className="w-tag__ring" />
<h3 className="w-serif text-[1rem]">{t.title}</h3>
<p className="w-prose mt-2 text-[0.8rem]">{t.desc}</p>
</article>
))}
<div className="w-mt-metal-flush w-drawer__front">
<i className="w-screw" aria-hidden="true" />
<span className="w-drawer__handle" aria-hidden="true" />
<i className="w-screw" aria-hidden="true" />
</div>
</div>
</Reveal>
</Bay>
</section>
{/* -------------------------------------------------- contributions */}
<Bay id="gitdxd" index="06" label="gitdxd" title="Forge telemetry">
<Reveal delay={40}>
<ContributionsPanel />
{/* ------------------------------------------------------ hardware */}
<section id="hardware" className="scroll-mt-28">
<Reveal>
<SectionHead index="05" label="machines" title="Tagged on the pegboard" />
</Reveal>
</Bay>
<Reveal delay={60}>
<div className="w-mt-metal w-pegboard">
<div className="w-pegboard__face">
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
{techProjects.map((t) => (
<article key={t.title} className="w-mt-paper w-hangtag">
<span className="w-hangtag__hole" aria-hidden="true" />
<h3 className="w-serif text-[1.02rem] text-[var(--ink)]">{t.title}</h3>
<p className="w-prose mt-2 text-[0.8rem] text-[var(--ink-soft)]">{t.desc}</p>
</article>
))}
</div>
</div>
</div>
</Reveal>
</section>
{/* -------------------------------------------------------- friends */}
<Bay id="friends" index="07" label="friends" title="Cards on the desk">
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{/* -------------------------------------------------- activity feed */}
<section id="gitdxd" className="scroll-mt-28">
<Reveal>
<SectionHead index="06" label="gitdxd" title="The printer spits out the forge" />
</Reveal>
<Reveal delay={60}>
<Report />
</Reveal>
</section>
{/* ------------------------------------------------------- friends */}
<section id="friends" className="scroll-mt-28">
<Reveal>
<SectionHead index="07" label="friends" title="Cards on the desk" />
</Reveal>
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
{friends.map((f, i) => (
<Reveal key={f.name} delay={40 + i * 70}>
<Reveal key={f.name} delay={60 + i * 70}>
<a
href={f.realUrl || f.url}
target="_blank"
rel="noopener noreferrer"
className={`w-paper w-card block transition-transform hover:-translate-y-1 ${i % 2 ? "w-note--tilt" : ""}`}
className="w-mt-paper w-bizcard"
style={{ "--tilt": `${i === 1 ? 0.9 : i === 2 ? -1 : -1.4}deg` } as CSSProperties}
>
<h3 className="w-serif text-[1.1rem]">{f.name}</h3>
<p className="mt-1 font-mono text-[0.72rem] text-[var(--paper-ink-soft)]">{f.desc}</p>
<p className="w-serif text-[1.15rem] text-[var(--ink)]">{f.name}</p>
<p className="w-mono mt-1 text-[0.66rem] text-[var(--ink-soft)]">{f.desc}</p>
</a>
</Reveal>
))}
</div>
</Bay>
</section>
{/* ------------------------------------------------------------ gym */}
<Bay id="gym" index="08" label="strength" title="On the platform">
<Reveal delay={40}>
<div className="w-metal p-5">
<div className="grid gap-3 sm:grid-cols-3">
{LIFTS.map((l) => (
<div key={l.lift} className="w-panel p-4 text-center">
<div className="w-digits text-[2.2rem] leading-none">
{l.weight}
<span className="ml-1 text-[1rem] opacity-70">{l.unit}</span>
{/* ----------------------------------------------------------- gym */}
<section id="gym" className="scroll-mt-28">
<Reveal>
<SectionHead index="08" label="strength" title="Numbers on the clipboard" />
</Reveal>
<Reveal delay={60}>
<div className="w-clipboard">
<div className="w-mt-metal w-clipboard__clip" aria-hidden="true" />
<div className="w-mt-paper w-logsheet">
<div className="w-sheet__head">
<span>training log</span>
<span className="ml-auto">73 kg bodyweight</span>
</div>
<div className="mt-3">
{LIFTS.map((l) => (
<div key={l.lift} className="w-logrow">
<span className="w-logrow__lift">{l.lift}</span>
<span className="w-logrow__weight">{l.weight} kg</span>
<span className="w-logrow__date">{l.date}</span>
</div>
<div className="w-kicker mt-3">{l.lift}</div>
<div className="w-unit__meta mt-1">{l.date} · 73 kg BW</div>
</div>
))}
))}
</div>
<p className="w-mono mt-4 text-[0.62rem] tracking-[0.14em] text-[var(--ink-soft)]">
BEST SBD TOTAL · 401 KG · 165 + 111 + 125
</p>
</div>
</div>
</Reveal>
</Bay>
</section>
{/* -------------------------------------------------------- contact */}
<Bay id="contact" index="09" label="ports" title="Patch panel">
<Reveal delay={40}>
<div className="w-patch w-metal">
<div className="w-rack__head">
<span className="w-rack__title">socials</span>
<span className="w-unit__meta ml-auto">12 ports</span>
</div>
<div className="mt-4 grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
{socials.map((s) => (
<a key={s.name} href={s.url} target="_blank" rel="noopener noreferrer" className="w-port">
<span className="w-port__jack" />
<span className="text-[var(--faint)]">
<SocialGlyph name={s.name} icon={s.icon} />
</span>
<span className="w-port__label min-w-0 truncate">{s.name}</span>
<Led kind="green" className="ml-auto" />
{/* ------------------------------------------------------- contact */}
<section id="contact" className="scroll-mt-28">
<Reveal>
<SectionHead index="09" label="patch panel" title="Twelve ports, all live" />
</Reveal>
<Reveal delay={60}>
<div className="w-mt-metal w-patch">
<div className="w-mt-metal-flush w-patch__face">
<div className="w-patch__head">
<i className="w-screw" aria-hidden="true" />
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">PATCH 01 · SOCIALS</span>
<i className="w-screw ml-auto" aria-hidden="true" />
</div>
<div className="grid gap-2.5 sm:grid-cols-2 xl:grid-cols-3">
{socials.map((s) => (
<a key={s.name} href={s.url} target="_blank" rel="noopener noreferrer" className="w-port">
<span className="w-port__jack" aria-hidden="true">
<span className="w-port__slot" />
</span>
<span className="w-port__icon">
<SocialGlyph name={s.name} icon={s.icon} />
</span>
<span className="w-port__label">{s.name}</span>
</a>
))}
</div>
<p className="w-mono mt-5 text-[0.64rem] tracking-[0.06em] text-[var(--ftext-faint)]">
fastest reply is Discord or Instagram · mail{" "}
<a className="w-link" href="mailto:dvorak@dvorakmortonxd.dev">
dvorak@dvorakmortonxd.dev
</a>
))}
</p>
</div>
<p className="w-unit__meta mt-5">
fastest reply is Discord or Instagram · mail{" "}
<a className="w-link" href="mailto:dvorak@dvorakmortonxd.dev">
dvorak@dvorakmortonxd.dev
</a>
</p>
</div>
</Reveal>
</Bay>
</section>
</div>
</main>
{/* --------------------------------------------------------- footer */}
<footer className="shell pb-14 pt-10">
{/* ------------------------------------------------------------ footer */}
<footer className="mx-auto w-full max-w-[1120px] px-5 pb-16 sm:px-8">
<Reveal>
<div className="w-metal-flat flex flex-col gap-5 p-5 md:flex-row md:items-center md:justify-between">
<div className="w-mt-brass relative flex flex-col gap-5 px-6 py-5 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<div className="flex items-center gap-3">
<Led kind="green" />
<span className="w-rack__title">dvorakmortonxd.local</span>
</div>
<p className="w-unit__meta mt-2">
built with Next.js · textures CC0 via ambientCG ·{" "}
<p className="w-mono text-[0.72rem] tracking-[0.2em]">DVORAKMORTONXD.LOCAL</p>
<p className="w-mono mt-1.5 text-[0.62rem] opacity-80">
v3.2.0 · GPL-3.0-only · built with Next.js · textures CC0 via{" "}
<a className="w-link" href="/credits">
credits
</a>
@ -465,17 +512,17 @@ export default function WebSite() {
<button
type="button"
onClick={() => setTheme("skeuo")}
className="w-btn desktop-toggle shrink-0"
className="w-keybtn desktop-toggle shrink-0 self-start sm:self-auto"
title="Flip to Desktop mode"
>
<Led kind="amber" /> desktop mode
</button>
<i className="w-screw w-screw--brass w-corner-tr" aria-hidden="true" />
<i className="w-screw w-screw--brass w-corner-bl" aria-hidden="true" />
</div>
<div className="mt-4 flex flex-col gap-1 font-mono text-[0.68rem] text-[var(--faint)] sm:flex-row sm:justify-between">
<span>v3.1.0 · © 2025–2026 Martin Dvořák</span>
<span>GPL-3.0-only — follow it or don’t, I don’t mind</span>
</div>
<p className="w-mono mt-4 text-[0.62rem] text-[var(--ftext-faint)]">
© 2025–2026 Martin Dvořák — follow the licence or don&rsquo;t, I don&rsquo;t mind
</p>
</Reveal>
</footer>
</div>

View file

@ -31,7 +31,7 @@ export function Reveal({
}
}
},
{ rootMargin: "0px 0px -12% 0px", threshold: 0.08 }
{ rootMargin: "0px 0px -12% 0px", threshold: 0.06 }
);
const rect = el.getBoundingClientRect();
@ -58,51 +58,132 @@ export function Reveal({
/* ------------------------------------------------------------- hardware */
export function Led({
kind = "green",
kind = "on",
pulse = false,
slow = false,
className = "",
title,
style,
}: {
kind?: "green" | "amber" | "red" | "blue" | "off";
kind?: "on" | "amber" | "off";
pulse?: boolean;
slow?: boolean;
className?: string;
title?: string;
style?: CSSProperties;
}) {
return (
<span
className={`w-led w-led--${kind}${pulse ? " w-led--pulse" : ""} ${className}`}
title={title}
<i
aria-hidden="true"
className={`w-led w-led--${kind}${pulse ? (slow ? " w-led--pulse-slow" : " w-led--pulse") : ""} ${className}`}
style={style}
/>
);
}
/** Section header, mounted on the chassis. */
export function Bay({
id,
index,
label,
title,
children,
}: {
id: string;
index: string;
label: string;
title: ReactNode;
children: ReactNode;
}) {
export function Screws({ count = 2, brass = false, className = "" }: { count?: number; brass?: boolean; className?: string }) {
return (
<section id={id} className="scroll-mt-28">
<Reveal>
<div className="flex flex-wrap items-center gap-x-4 gap-y-3">
<span className="w-plate">
{index} <span className="opacity-50">/</span> {label}
<span className={`w-unit__screws ${className}`}>
{Array.from({ length: count }).map((_, i) => (
<i key={i} className={`w-screw${brass ? " w-screw--brass" : ""}`} />
))}
</span>
);
}
/** Section heading: a brass tab screwed to the desk + painted title. */
export function SectionHead({ index, label, title }: { index: string; label: string; title: string }) {
return (
<div className="w-sechead">
<span className="w-mt-brass w-sechead__tab">{index} · {label}</span>
<h2 className="w-serif w-paint w-sechead__title">{title}</h2>
</div>
);
}
/* ----------------------------------------------------------- the machine */
export function Monitor({ children, className = "" }: { children: ReactNode; className?: string }) {
return (
<div className={`w-monitor ${className}`}>
<div className="w-monitor__frame">
<div className="w-mt-glass w-monitor__glass">{children}</div>
<div className="w-monitor__chin">
<Led kind="amber" />
<span className="w-monitor__brand">DXD</span>
<span className="w-monitor__osd" aria-hidden="true">
<i className="w-osdkey" />
<i className="w-osdkey" />
<i className="w-osdkey" />
</span>
<h2 className="w-serif text-[1.6rem] sm:text-[2rem]">{title}</h2>
</div>
</Reveal>
<div className="mt-8">{children}</div>
</section>
</div>
<div className="w-monitor__stand" aria-hidden="true">
<i className="w-monitor__neck" />
<i className="w-monitor__base" />
</div>
</div>
);
}
const KEY_ROWS = ["1234567890-=".split(""), "qwertyuiop[]".split(""), "asdfghjkl;'".split("")];
export function Keyboard() {
return (
<div className="w-keyboard" aria-hidden="true">
<div className="w-keyboard__deck">
{KEY_ROWS.map((row, i) => (
<div key={i} className="w-keyboard__row">
{row.map((k) => (
<span key={k} className="w-key">
{k}
</span>
))}
</div>
))}
<div className="w-keyboard__row">
<span className="w-key w-key--space" />
</div>
</div>
</div>
);
}
/** A small rack that sits on the desk in the hero. */
export function MiniRack({ label = "DXD-01" }: { label?: string }) {
return (
<div className="w-rack w-mt-metal" aria-hidden="true">
<div className="w-rack__top">
<Led kind="on" pulse />
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">{label}</span>
<span className="w-rack__vent w-vents" />
</div>
<div className="w-rack__grid">
<span className="w-rails" />
<div>
{[0, 1, 2, 3].map((i) => (
<div key={i} className="w-unit !min-h-[46px] !gap-[10px] !py-2">
<span className="w-unit__grille !h-6 !w-9" />
<Led kind="on" pulse style={{ animationDelay: `${i * 0.5}s` }} />
<Led kind="amber" pulse slow style={{ animationDelay: `${i * 0.3}s` }} />
<span className="ml-auto w-engrave text-[0.58rem] tracking-[0.14em]">
{["pxe", "aio", "nas", "web"][i]}
</span>
</div>
))}
</div>
<span className="w-rails" />
</div>
</div>
);
}
/** A brass plate with one number stamped into it. */
export function Plaque({ value, label }: { value: string; label: string }) {
return (
<div className="w-mt-brass w-plaque relative">
<span className="w-plaque__value">{value}</span>
<span className="w-plaque__label">{label}</span>
<i className="w-screw w-screw--brass w-plaque__screw" />
</div>
);
}
@ -143,17 +224,10 @@ export function ServiceUnit({
};
}, [url, checkUrl, disabled]);
const effective = disabled ? "up" : status;
const kind = effective === "up" ? "green" : effective === "down" ? "red" : "off";
const statusLabel = disabled
? "standby"
: effective === "up"
? "online"
: effective === "down"
? "offline"
: "checking";
const accessLabel =
access === "public" ? "public" : access === "private" ? "private" : access === "on_request" ? "on request" : null;
const live = disabled ? "up" : status;
const kind = live === "up" ? "on" : live === "down" ? "off" : "amber";
const label = disabled ? "STANDBY" : live === "up" ? "ONLINE" : live === "down" ? "OFFLINE" : "POLLING";
const accessLabel = access === "public" ? "public" : access === "private" ? "private" : access === "on_request" ? "on request" : null;
const host = (() => {
try {
@ -165,42 +239,39 @@ export function ServiceUnit({
const inner = (
<>
<span className="w-unit__leds">
<Led kind={kind} pulse={effective === "up"} />
<Led kind="amber" pulse={effective === "up"} />
</span>
<span className="min-w-0 flex-1">
<span className="w-unit__name block truncate">{name}</span>
<span className="w-unit__meta block truncate">
{host} {accessLabel ? `· ${accessLabel}` : ""}
<span className="w-unit__grip" aria-hidden="true" />
<span className="w-unit__grille w-grille" aria-hidden="true" />
<span className="w-unit__id">
<span className="w-unit__name w-engrave">{name}</span>
<span className="w-tape mt-1">
{host}
{accessLabel ? ` · ${accessLabel}` : ""}
</span>
<span className="sr-only">{desc}</span>
</span>
<span className="hidden text-right sm:block">
<span className="w-unit__meta block max-w-[26ch] truncate">{desc}</span>
</span>
<span className="w-plate shrink-0">
<Led kind={kind} /> {statusLabel}
<span className="w-unit__state">
<Led kind={kind} pulse={live === "up"} />
<span className="w-unit__status w-engrave">{label}</span>
</span>
<Screws />
</>
);
const cls = "w-unit w-metal-flat";
if (disabled) {
return (
<span className={cls} aria-disabled="true">
<span className="w-unit" aria-disabled="true">
{inner}
</span>
);
}
return (
<a href={url} target="_blank" rel="noopener noreferrer" className={`${cls} w-unit--link`}>
<a href={url} target="_blank" rel="noopener noreferrer" className="w-unit w-unit--link" title={desc}>
{inner}
</a>
);
}
/* -------------------------------------------------------- contributions */
/* -------------------------------------------------------- activity report */
interface HeatmapPoint {
timestamp: number;
@ -213,7 +284,9 @@ interface Activity {
repo?: { full_name?: string };
}
export function ContributionsPanel() {
const DOT_OPACITY = [0.07, 0.3, 0.48, 0.64, 0.82];
export function Report() {
const [weeks, setWeeks] = useState<{ date: string; contribs: number; level: number }[][]>([]);
const [total, setTotal] = useState(0);
const [activities, setActivities] = useState<Activity[]>([]);
@ -291,50 +364,52 @@ export function ContributionsPanel() {
};
}, []);
// level 4 = brightest LED, level 0 = off
const levelOn = (l: number) => (l <= 0 ? "0" : String(5 - l));
return (
<div className="w-dashboard w-metal">
<div className="w-rack__head">
<span className="w-rack__title">gitdxd.activity</span>
<span className="ml-auto flex items-center gap-2">
<Led kind={state === "error" ? "red" : "green"} pulse={state === "ready"} />
<span className="w-unit__meta">{state === "error" ? "link down" : "streaming"}</span>
</span>
</div>
<div className="w-printout">
<div className="w-mt-paper w-printout__paper">
<span className="w-printout__perf w-printout__perf--l" aria-hidden="true" />
<span className="w-printout__perf w-printout__perf--r" aria-hidden="true" />
<div className="mt-4 flex flex-wrap items-end justify-between gap-3">
<div className="w-digits text-[2rem] leading-none sm:text-[2.5rem]">{total}</div>
<div className="w-kicker">contributions / last year</div>
</div>
<p className="w-print__head">
<span>GITDXD // ACTIVITY REPORT</span>
<span className="ml-auto">{state === "ready" ? "PRINTED LIVE" : state === "error" ? "PRINTER OFFLINE" : "SPOOLING…"}</span>
</p>
{state === "loading" ? (
<p className="w-screen-text mt-5 opacity-70">reading matrix…</p>
) : state === "error" ? (
<p className="w-screen-text mt-5 opacity-70">could not reach the forge.</p>
) : (
<>
<div className="w-ledgrid mt-5">
{weeks.map((w, i) => (
<div key={i} className="w-ledgrid__col">
{w.map((d) => (
<div key={d.date} className="w-ledgrid__cell" data-on={levelOn(d.level)} title={`${d.contribs} on ${d.date}`} />
))}
{state === "error" ? (
<p className="w-mono mt-5 text-[0.72rem] text-[#4a4133]">could not reach the forge.</p>
) : (
<>
<div className="mt-5 flex flex-wrap items-end gap-x-6 gap-y-2">
<div>
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[#4a4133]">TOTAL / 12 MONTHS</p>
<p className="w-serif text-[2.6rem] leading-none text-[var(--ink)]">
{state === "loading" ? "—" : total}
</p>
</div>
))}
</div>
<div className="mt-3 flex items-center justify-end gap-2">
<span className="w-unit__meta">less</span>
{[4, 3, 2, 1, 0].map((l) => (
<span key={l} className="w-ledgrid__cell" data-on={levelOn(l)} />
))}
<span className="w-unit__meta">more</span>
</div>
<p className="w-mono text-[0.62rem] leading-relaxed text-[#6f6450]">
each dot = one day
<br />
darkest = busiest
</p>
</div>
{activities.length > 0 ? (
<div className="w-panel mt-5 p-3">
<div className="w-screen-text">
<div className="w-dotgrid w-scroll" aria-hidden={state === "loading"}>
{weeks.map((w, i) => (
<span key={i} className="w-dotgrid__col">
{w.map((d) => (
<span
key={d.date}
className="w-dot"
style={{ opacity: DOT_OPACITY[d.level] }}
title={`${d.contribs} on ${d.date}`}
/>
))}
</span>
))}
</div>
{activities.length > 0 ? (
<div className="w-print__log">
{activities.map((a, i) => {
let msg = "commit";
try {
@ -353,15 +428,15 @@ export function ContributionsPanel() {
}
return (
<p key={i} className="truncate">
<span className="k">$</span> {a.repo?.full_name || "unknown"} — {msg}
&gt; {a.repo?.full_name || "unknown"} — {msg}
</p>
);
})}
</div>
</div>
) : null}
</>
)}
) : null}
</>
)}
</div>
</div>
);
}