diff --git a/src/components/InteractiveSystemOverview.tsx b/src/components/InteractiveSystemOverview.tsx index 632316d..883f5bf 100644 --- a/src/components/InteractiveSystemOverview.tsx +++ b/src/components/InteractiveSystemOverview.tsx @@ -36,9 +36,60 @@ const CONTENT_MODULES = [ content: (
- {['Rust', 'Go', 'C/C++', 'eBPF', 'Kubernetes', 'TrueNAS', 'Linux/KWin', 'React'].map((skill) => ( - - {skill} + {[ + { + label: 'Infra & Self-Hosting', + details: + 'Docker, Podman, Traefik, Gitea, Jellyfin, Home Assistant, systemd, Nginx, Linux (Arch), Pacman, SSH, S3-compatible storage, rclone', + }, + { + label: 'Desktop & Systems Tooling', + details: + 'KDE Plasma, KWin scripting, Wayland, X11, Tauri, Electron, GTK, Qt (QML), PipeWire, PulseAudio, Krunner, supergfxctl, nbfc', + }, + { + label: 'Browser Extensions & Web', + details: + 'Manifest V3, WebExtensions API, Chrome Extensions API, Firefox Add-ons, React, TypeScript, Vue, REST APIs', + }, + { + label: 'Simulation & Design', + details: + 'TypeScript, Node.js, structured world state design, deterministic intent systems, JSON schema modeling', + }, + { + label: 'Low Level Development', + details: 'Rust, Cargo, Tokio, Serde, Tauri, egui', + }, + { + label: 'Automation & Scripting', + details: 'Python, Selenium, BeautifulSoup, Bash, cron', + }, + { + label: 'Hardware/Embedded', + details: + 'ESP32, Arduino ecosystem, relays, ACPI/EC interaction, eDP controller boards, UART, I2C', + }, + { + label: 'Media Data', + details: + 'FFmpeg, FLAC, Opus, AAC, AV1, H.264, H.265, SQLite, vector-based indexing', + }, + { + label: 'Frontend & AppDev', + details: + 'React, TypeScript, Qt/QML, Tauri, VuePress, REST integration', + }, + ].map((skill) => ( + + {skill.label} + + {skill.label} + {skill.details} + ))}
@@ -167,7 +218,7 @@ export function InteractiveSystemOverview() { key={node.id} onClick={() => handleSplit(i)} className={` - sketch-border bg-[var(--bg-panel)] p-4 relative group overflow-hidden flex flex-col + sketch-border bg-[var(--bg-panel)] p-4 relative group overflow-visible flex flex-col transform ${rotation} transition-all duration-500 hover:scale-[1.01] hover:z-10 ${nextModuleIndex < CONTENT_MODULES.length ? 'cursor-crosshair' : 'cursor-default'} ${getNodeClass(activeNodes.length, i)} @@ -181,7 +232,7 @@ export function InteractiveSystemOverview() { [{node.tty}]
-
+
{node.content}
diff --git a/src/components/ResumeSection.tsx b/src/components/ResumeSection.tsx index 166edaa..c8cfeb9 100644 --- a/src/components/ResumeSection.tsx +++ b/src/components/ResumeSection.tsx @@ -9,7 +9,7 @@ export function ResumeSection() {
-
+

Grab the latest snapshot of my experience, projects, and research focus.

diff --git a/src/utils.tsx b/src/utils.tsx new file mode 100644 index 0000000..e3020fd --- /dev/null +++ b/src/utils.tsx @@ -0,0 +1,18 @@ +function deterministicIpValue(ip: string, x: number): number { + if (!Number.isInteger(x) || x <= 0) { + throw new Error("x must be a positive integer"); + } + + // fnv1a hash + let hash = 0x811c9dc5; + + for (let i = 0; i < ip.length; i++) { + hash ^= ip.charCodeAt(i); + hash = Math.imul(hash, 0x01000193); // 32b multiply + } + + const unsignedHash = hash >>> 0; + + // map to range + return (unsignedHash % x) + 1; +} \ No newline at end of file