diff --git a/README.md b/README.md index 919ccff..c10eb22 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,16 @@ > The source code for my personal website, **[dvorakmortonxd.dev](https://dvorakmortonxd.dev)**. -It's a **skeuomorphic personal site**: a dark homelab desk built from anodised aluminium, OLED -glass, carbon fibre and paper, with the whole KDE desktop simulation kept behind a physical -power switch. Two modes, one content set: +It's a **skeuomorphic personal site**: a walnut desk with graphite hardware, cream paper and +brass details resting on it, with the whole KDE desktop simulation kept behind a physical power +switch. Two modes, one content set: -- **Web** (default) — the homelab desk. A 4U rack carries the headline on an engraved nameplate - and a live console readout; services are rack units with status LEDs, the 18 coding projects - are labelled SSD caddies in a drive drawer, hardware hangs on a pegboard, the contribution - heatmap is an LED matrix and the socials are a patch panel. Textures are CC0 — see - [`/credits`](http://localhost:3000/credits). +- **Web** (default) — the desk. A monitor carries the headline with a keyboard in front of it + and a small rack beside it; services are 1U rack units with health LEDs, the 18 coding + projects are labelled drives in a drawer, the machines hang as paper tags on a pegboard, the + contribution heatmap is printed on continuous dot-matrix paper, friends are business cards, + the gym log is a clipboard and the socials are a patch panel. Textures are CC0 — see + [`/credits`](https://dvorakmortonxd.dev/credits). - **Desktop mode** — the KDE Plasma / Windows-style **desktop simulation**: draggable snap-to-grid icons, resizable/floating windows, a Start menu, taskbar, live clock and a working in-browser terminal (Alacritty). Reached from the power switch and hidden on phones. @@ -23,8 +24,9 @@ heatmap**, gym SBD and links to friends' sites. - **Web theme is the landing view** — the site always opens on the desk; the theme is deliberately not persisted, so a reload never drops you into the desktop. -- **Skeuomorphic hardware** — rack, LEDs, rocker switch, screws, vents and panels are CSS - materials over five CC0 textures; every section is a real-world object rather than a card. +- **Skeuomorphic materials** — walnut desk, graphite faceplates, cream paper, brass plaques and + amber LEDs, all CSS over five CC0 textures. Every section is a physical object with a contact + shadow; nothing is pure white on black or grey on black. - **Desktop mode (desktop-only)** — a physical power switch in the top rail (and in the footer) flips to the KDE-style desktop for the session. Phones never get it: the switch is hidden, so the old iOS-style phone home screen is gone. @@ -64,15 +66,15 @@ heatmap**, gym SBD and links to friends' sites. - **Framework:** Next.js 16 (App Router, Turbopack) - **Language:** TypeScript, React 19 (client components everywhere interactivity lives) - **Styling:** `src/app/globals.css` holds the palette tokens, base styles, the Tailwind v4 - `@theme`/`@utility` classes and the scroll reveals. `src/app/web.css` is the skeuomorphic - material system (metal, OLED glass, paper, carbon, rubber, plastic, LEDs, screws, vents, - switches) and the object layouts. `page.css` keeps the shared component styles the desktop - apps still use, and `skeuo.css` is the KDE desktop. + `@theme`/`@utility` classes and the scroll reveals. `src/app/web.css` is the material system + (walnut desk, graphite metal, cream paper, brass, OLED glass, LEDs, screws, rack rails, rocker + switch) and the object layouts. `page.css` keeps the shared component styles the desktop apps + still use, and `skeuo.css` is the KDE desktop. - **Fonts:** Newsreader (headlines, paper) + IBM Plex Sans/Mono (body, machine labels) via `next/font/google`; the desktop keeps its system sans stack. -- **Textures:** five CC0 materials from ambientCG, downscaled to 512 px in `public/textures`. - Attribution is on `/credits`. -- **Version:** `3.1.0` (see `package.json`) +- **Textures:** five CC0 materials from ambientCG — `desk` (walnut), `metal`, `paper`, `carbon`, + `plastic` — downscaled to 512 px in `public/textures`. Attribution is on `/credits`. +- **Version:** `3.2.0` (see `package.json`) ## 🚀 Running Locally diff --git a/agents.md b/agents.md index 2024e64..92ba4e6 100644 --- a/agents.md +++ b/agents.md @@ -34,19 +34,20 @@ When in doubt, prefer updating. A stale README **or** agents.md is treated as a ## What this project is Personal portfolio site for **dvorakmortonxd.dev**. The default view is a -**skeuomorphic homelab desk** (a rack, LEDs, paper, anodised metal); a physical -power switch flips to a **KDE Plasma desktop simulation**. Phones only ever get -the desk. +**skeuomorphic desk**: a walnut surface with a monitor, keyboard, rack, drive +drawer, pegboard, dot-matrix report, business cards, clipboard and patch panel +resting on it. A physical power switch flips to a **KDE Plasma desktop +simulation**. Phones only ever get the desk. - Framework: **Next.js 16** (App Router, Turbopack), **React 19**, TypeScript. -- Styling: **Tailwind v4** for layout plus **`web.css`**, the skeuomorphic - material system (metal, OLED glass, paper, carbon, rubber, plastic, LEDs, - screws, vents, switches) over five CC0 textures in `public/textures` +- Styling: **Tailwind v4** for layout plus **`web.css`**, the material system + (walnut desk, graphite metal, cream paper, brass, OLED glass, LEDs, screws, + rack rails, rocker switch) over five CC0 textures in `public/textures` (credited on `/credits`). `globals.css` holds the tokens, base styles and the reveals; `skeuo.css` and `page.css` are the desktop and the shared desktop-app styles. - Path alias: `@/*` → `src/*`. -- Version: `3.1.0` (see `package.json`). +- Version: `3.2.0` (see `package.json`). ### Scripts ```bash @@ -123,11 +124,11 @@ scripts/ desktop is up so its scroll position survives; the desktop mounts on demand (phones can never reach `skeuo`). -Modes: `web` = the skeuomorphic homelab desk (default/landing), `skeuo` = KDE -Plasma desktop. +Modes: `web` = the skeuomorphic desk (default/landing), `skeuo` = KDE Plasma +desktop. -The desk uses **five CC0 textures** from ambientCG (`public/textures`: metal, -paper, carbon, rubber, plastic), downscaled to 512 px and credited on +The desk uses **five CC0 textures** from ambientCG (`public/textures`: desk +walnut, metal, paper, carbon, plastic), downscaled to 512 px and credited on `/credits`. The social SVGs are used as monochrome CSS masks (`.social-mask`); `linkedin.svg` is a filled badge that masks to a plain square, so `web-ui.tsx` renders an inline mark for it instead. The desktop still uses the image assets. @@ -235,7 +236,12 @@ not free placement. Don't confuse the two. collided with Tailwind's `w-screen` (`width: 100vw`) and silently stretched every panel to the viewport. Also remember `web.css` is unlayered, so its properties beat Tailwind utilities on the same element; use a dedicated class - (e.g. `.w-navlink`) or `!` when a utility must win. + (e.g. `.w-navlink`, `.w-corner-tr`) or `!` when a utility must win. (`.w-screw` + sets `position: relative` for its slot, which is why screws are placed with + `.w-corner-*` instead of Tailwind's `absolute`.) +- Angles and offsets that hover states need to override live in CSS custom + properties (e.g. `--tilt` on `.w-drive`), never in inline `style` transforms — + an inline transform wins over `:hover`. - The desk reveals blocks with `.reveal` (see `Reveal` in `web-ui.tsx`): hidden by default, `.is-in` shows. On load the first screenful cascades top-to-bottom (90ms per block, in DOM order); the rest reveal when they scroll in. **Wrap diff --git a/package.json b/package.json index 048a6c9..2af9046 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dvorakmortonxd", - "version": "3.1.0", + "version": "3.2.0", "private": true, "scripts": { "dev": "node scripts/dev-server.mjs", diff --git a/public/textures/desk.jpg b/public/textures/desk.jpg new file mode 100644 index 0000000..820ba7f Binary files /dev/null and b/public/textures/desk.jpg differ diff --git a/public/textures/rubber.jpg b/public/textures/rubber.jpg deleted file mode 100644 index ca98a3e..0000000 Binary files a/public/textures/rubber.jpg and /dev/null differ diff --git a/src/app/components/WebSite.tsx b/src/app/components/WebSite.tsx index 8ca65a0..70661a4 100644 --- a/src/app/components/WebSite.tsx +++ b/src/app/components/WebSite.tsx @@ -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 ( -
- {/* ----------------------------------------------------------- rail */} -
-
- - - dvorakmortonxd.local +
+ {/* -------------------------------------------------------------- rail */} +
+
+ + + dvorakmortonxd
{menuOpen ? ( -