7 KiB
👾 dvorakmortonxd.dev
The source code for my personal website, dvorakmortonxd.dev.
This is not a normal portfolio page. It ships two fully interactive shells and picks which one to show based on the saved theme and the device, all from the same content:
skeuo(default) — a KDE Plasma / Windows-style desktop simulation: draggable snap-to-grid icons, resizable/floating windows, a Start menu, taskbar and live clock. On phones it becomes an iOS-style home screen with a widget grid, dock, drag-to-reorder and an iOS launch animation.terminal— a Gruvbox TUI version of the site: TUI panels, an animated ASCII train background, a clickable easter-egg logo, and a working in-browser terminal (Alacritty) with commands likehelp,ls,cat,neofetch,emerge,sshand more.
Both shells surface the same personal content: socials, self-hosted services with live up/down health checks, a hardware collection, coding projects, a GitDXD contribution heatmap, a gym SBD panel and links to friends' sites.
✨ Features
- Two themes / shells — KDE-style desktop and Gruvbox terminal, toggled from either UI
and persisted in
localStorage(applied pre-paint to avoid a flash). - Phone vs. desktop detection — a user-agent sniff on
<html data-device>decides whether the desktop or the mobile home screen is shown. - Draggable desktop icons — free placement that snaps to a measured grid, one icon per cell, with a follow-the-cursor drag ghost.
- Multi-window manager — draggable, resizable, minimizable, maximizable, focus/z-order and animated open/close (with reduced-motion support).
- Working terminal app — command input with history (
↑/↓,Ctrl+Lto clear) and a hiddenssheaster egg. - Live service status — each self-hosted service is health-checked through the site's own API; Minecraft is checked through mcstatus.io.
- Live GitDXD stats — contribution heatmap + latest commit activity proxied server-side from the self-hosted Forgejo instance.
- Extras — a playable
Revival Inc.game embedded at/revival-inc,llms.txt,robots.txtand asitemap.xml.
🛠️ Tech Stack
- Framework: Next.js 16 (App Router, Turbopack)
- Language: TypeScript, React 19 (client components everywhere interactivity lives)
- Styling: hand-written CSS —
src/app/page.css(terminal theme),src/app/skeuo.css(desktop + mobile),src/app/globals.css(base/reset). Tailwind v4 is imported for the base layer but the UI is custom CSS. - Fonts: Monocraft (self-hosted in
public/, used by the terminal theme; the desktop theme uses the system sans stack) - Images:
next/image - Version:
2.1.0(seepackage.json)
🚀 Running Locally
Requires Node.js >= 20.9.0 (Next.js 16).
git clone https://git.dvorakmortonxd.dev/dvorakmortonxd/dvorakmortonxd.dev
cd dvorakmortonxd.dev
npm install
npm run dev
Then open http://localhost:3000.
One-shot setup on Debian/Ubuntu
install-dependencies-deb.sh installs the system packages, Node.js LTS (>= 20.9.0) and npm,
then runs npm install and npm run build:
./install-dependencies-deb.sh # system deps + npm install + build
./install-dependencies-deb.sh --no-build # system deps + npm install only
./install-dependencies-deb.sh --no-npm # system packages only
Scripts
npm run dev # next dev --turbopack
npm run build # next build --turbopack
npm run start # next start (production)
npm run lint # eslint
Handy checks before shipping: npx tsc --noEmit, npx eslint <files>, npm run build.
Testing from a phone on your LAN
next.config.ts sets allowedDevOrigins so the dev server can be reached from other devices
on the local network (otherwise Next.js 403s the dev asset requests).
📡 API Routes
| Route | Method | What it does |
|---|---|---|
/api/heatmap |
GET |
Proxies the user's contribution heatmap from git.dvorakmortonxd.dev. |
/api/activities |
GET |
Fetches the GitDXD activity feed and keeps only the user's own events. |
/api/ping?url=… |
GET |
Health-checks a service. Handles minecraft://host:port via mcstatus.io; treats any non-5xx HTTP response as "up". |
📁 Project Structure
src/app/
page.tsx → renders <ThemeRoot/>, imports the two theme stylesheets
layout.tsx → html shell + metadata, injects ThemeScript
globals.css → base/reset styles + Tailwind import
page.css → terminal theme styles
skeuo.css → desktop + mobile home styles
data.ts → socials, codingProjects, techProjects, friends, wallpapers
revival-inc/page.tsx → embeds the bundled game at /public/revival-inc/index.html
api/
heatmap/route.ts → contribution heatmap proxy
activities/route.ts → GitDXD activity feed proxy
ping/route.ts → service health check (HTTP + Minecraft)
components/
ThemeRoot.tsx → picks which shell(s) to mount
ThemeScript.tsx → pre-paint script: theme + device detection
useTheme.ts → theme state via useSyncExternalStore
TerminalLayout.tsx → the Gruvbox terminal shell
WindowsDesktop.tsx → desktop shell: icons, windows, taskbar, Start menu
MobileHome.tsx → phone shell: iOS home screen + app view
WinWindow.tsx → one draggable/resizable window
apps.tsx → APPS registry, window contents, in-app terminal
useDesktopIcons.ts → desktop icon grid + drag/drop logic
useDragOrder.ts → list reordering (mobile grid/dock)
ServiceButton.tsx → service link + live status dot
ContributionHeatmap.tsx → heatmap + recent commits widget
Clock.tsx → live clock
JokerLogo.tsx → logo with click easter egg
SlBackground.tsx → animated ASCII train background
public/ → fonts, wallpapers, icons, friend pages, /revival-inc game, llms.txt, robots.txt, sitemap.xml
🌍 Deploying?
In order to deploy the website you'd want to set up a reverse proxy and something that runs it as a service. Me personally, I use cloudflared and pm2. You could also use something like Vercel, but I prefer self-hosting. Also, if you want to deploy it, you gotta change it enough so that you don't directly copy my website, and also follow the GPL3.0-only license, meaning you gotta make your code open source too.
Detailed step-by-step production instructions for PM2 + npm on Debian and Alpine Linux
(including the Cloudflare Tunnel / Nginx reverse-proxy setup) are in
DEPLOYMENT.md.
📬 Contact
To see my projects or get in touch, visit the live site or email me at dvorak@dvorakmortonxd.dev.
📄 License
GPL-3.0-only — see LICENSE.