The code for the website https://dvorakmortonxd.dev
  • HTML 56.5%
  • TypeScript 25%
  • CSS 16.3%
  • JavaScript 1.2%
  • Shell 1%
Find a file
2026-09-24 09:20:06 +00:00
public mobile: iOS-style widget + animations, 2-click desktop icons, new wallpapers 2026-09-22 21:02:49 +02:00
src SMP: Minecraft-style join window with live status; allow beta tunnel origin for dev HMR 2026-09-24 09:20:06 +00:00
.gitignore small changes regarding my proxmox maintenance checks 2026-09-21 00:02:54 +02:00
DEPLOYMENT.md full on update with new npm and instructions and maintenance update 2026-09-13 22:11:06 +02:00
eslint.config.mjs full on update with new npm and instructions and maintenance update 2026-09-13 22:11:06 +02:00
install-dependencies-deb.sh script support for doas added (actually now) 2026-09-24 07:12:14 +00:00
LICENSE Initial commit 2026-05-13 13:17:17 +02:00
next.config.ts SMP: Minecraft-style join window with live status; allow beta tunnel origin for dev HMR 2026-09-24 09:20:06 +00:00
opencode.md SMP: Minecraft-style join window with live status; allow beta tunnel origin for dev HMR 2026-09-24 09:20:06 +00:00
package-lock.json version bump, 2.1.0, some bug fixes and animations and a full on working terminal (WiP) 2026-09-23 14:40:21 +02:00
package.json version bump, 2.1.0, some bug fixes and animations and a full on working terminal (WiP) 2026-09-23 14:40:21 +02:00
postcss.config.mjs first commit/push 2026-05-13 13:22:58 +02:00
README.md SMP: Minecraft-style join window with live status; allow beta tunnel origin for dev HMR 2026-09-24 09:20:06 +00:00
tsconfig.json full on update with new npm and instructions and maintenance update 2026-09-13 22:11:06 +02:00

👾 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 like help, ls, cat, neofetch, emerge, ssh and 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). The taskbar shrinks its window buttons as more apps open and scrolls when they still don't fit, so every open app stays reachable.
  • Working terminal app — command input with history (↑/↓, Ctrl+L to clear) and a hidden ssh easter egg.
  • Live service status — each self-hosted service is health-checked through the site's own API; Minecraft is checked through mcstatus.io.
  • Embedded live services — opening a self-hosted service (Llama.cpp/Open WebUI, Jellyfin, Navidrome, GitDXD) from the desktop shows the real site inside the window (an iframe). The service must allow framing; SMP (Discord) keeps a link card because Discord sends X-Frame-Options: DENY.
  • Minecraft-style SMP window — the SMP shortcut opens a join menu modelled on Minecraft's multiplayer screen, with live status, player count, MOTD and version pulled from mcstatus.io through the site's own ping API.
  • 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.txt and a sitemap.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 (see package.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 and from the beta.dvorakmortonxd.dev tunnel. Without it Next.js rejects the dev asset requests and the HMR WebSocket, which leaves the page un-hydrated (stacked icons, dead buttons).

📡 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.