diff --git a/README.md b/README.md index 9bce609..d0a1674 100644 --- a/README.md +++ b/README.md @@ -2,25 +2,16 @@ > The source code for my personal website, **[dvorakmortonxd.dev](https://dvorakmortonxd.dev)**. -This is not a normal portfolio page. It ships a hand-built **skeuomorphic console** plus a -**phone-only desktop simulation**, both rendering the same content: +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) — the site itself: a walnut-and-aluminium home-lab console on a workshop - bench. Every section is a physical object — an engraved nameplate, an aluminium patch bay, - analogue load meters for the gym numbers, a clipboard, a leather logbook, a rack of service - modules with live pilot lamps, a framed screenshot, a chart recorder, a game cartridge, a - software box, a pegboard of manila tags and a card-index drawer. Materials are CSS + inline-SVG - noise only: the theme ships **no images of its own**. One light source (top-left), layered - shadows for raised/recessed/embossed/stitched parts, and a deliberate two-font pairing: a - condensed engraved panel face for metal, a typewriter for anything on paper. -- **`desktop`** (phone-width viewports only) — 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. - -The desktop simulation is only offered at ≤ 768 px: on anything wider the switch is hidden and -the page always renders `skeuo`, so a desktop visitor can never end up stuck in a mode whose -switch they cannot reach. +- **`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 @@ -28,16 +19,8 @@ heatmap**, a gym SBD panel and links to friends' sites. ## ✨ Features -- **Two shells** — the skeuo console (default everywhere) and the KDE-style desktop simulation - (phone-width viewports only, flipped by the physical switch on the nameplate). The choice is - persisted in `localStorage` under `dmx-theme` and applied pre-paint to avoid a flash; legacy - `theme` values are migrated once. -- **Desktop mode is phone-only** — at ≤ 768 px the switch appears and both shells are reachable; - at 768 px and above it is hidden and any saved `desktop` preference is overridden, so wide - viewports can never get stuck. -- **CSS-only materials** — wood, brushed aluminium, brass, leather, black bakelite, paper, glass - and rubber are built from gradients, `color-mix()` and an inline-SVG `feTurbulence` grain; no - texture images ship with the theme. +- **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 `` 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 @@ -75,14 +58,11 @@ heatmap**, a gym SBD panel and links to friends' sites. - **Framework:** Next.js 16 (App Router, Turbopack) - **Language:** TypeScript, React 19 (client components everywhere interactivity lives) -- **Styling:** hand-written CSS — `src/app/skeuo.css` (the skeuo console: materials, objects, - depth), `src/app/desktop.css` (KDE desktop + mobile home), `src/app/shared.css` (styles for - components both shells render: service buttons, heatmap, project cards, logo) and - `src/app/globals.css` (base/reset). Tailwind v4 is imported for the base layer but the UI is - custom CSS. -- **Fonts:** Barlow Semi Condensed (engraved panel labels, headings, controls) + Courier Prime - (everything printed or typewritten), both via `next/font/google` with explicit fallback - stacks. Monocraft stays self-hosted in `public/` for the desktop's terminal windows. +- **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`) @@ -184,12 +164,11 @@ they contend for `:3000` and `.next/dev/lock`. ``` src/app/ - page.tsx → renders , imports the three stylesheets - layout.tsx → html shell + metadata, loads the two fonts, injects ThemeScript + page.tsx → renders , imports the two theme stylesheets + layout.tsx → html shell + metadata, injects ThemeScript globals.css → base/reset styles + Tailwind import - skeuo.css → the skeuo console: materials, objects, depth - desktop.css → KDE desktop + mobile home styles - shared.css → styles for components both shells render + 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/ @@ -200,17 +179,18 @@ src/app/ ThemeRoot.tsx → picks which shell(s) to mount ThemeScript.tsx → pre-paint script: theme + device detection useTheme.ts → theme state via useSyncExternalStore - SkeuoLayout.tsx → the skeuo console shell + 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 lamp + 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 scripts/ dev-server.mjs → custom dev server: live updates without the dev-only debug surface deploy/ diff --git a/agents.md b/agents.md index 5512a77..d947705 100644 --- a/agents.md +++ b/agents.md @@ -34,18 +34,13 @@ 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**. It's not a normal website — -it ships a hand-built **skeuomorphic console** (`skeuo`, the default) plus a -KDE-style **desktop simulation** that is only offered on phone-width viewports. +it ships **two fully interactive desktop/OS simulations** plus a terminal, and +picks which one to show based on theme and device. - Framework: **Next.js 16** (App Router, Turbopack), **React 19**, TypeScript. -- Styling: plain CSS files — `skeuo.css` (the console), `desktop.css` (KDE sim + - mobile home), `shared.css` (components both shells render) and `globals.css` - (base/reset). No CSS-in-JS, no Tailwind utilities in the components (Tailwind - is present via PostCSS but the look is hand-written CSS). **Materials are CSS - + inline-SVG noise only — no texture images.** -- Fonts: Barlow Semi Condensed (metal labels, headings, controls) + Courier Prime - (paper, readouts) via `next/font/google` with explicit fallbacks; Monocraft - stays self-hosted in `public/` for the desktop's terminal windows. +- Styling: plain CSS files (`page.css`, `skeuo.css`), no CSS-in-JS, no Tailwind + utilities in the components (Tailwind is present via PostCSS but the look is + hand-written CSS). - Path alias: `@/*` → `src/*`. - Version: `2.1.0` (see `package.json`). @@ -78,13 +73,12 @@ token.** Do not print it, copy it into new files, or push it anywhere else. ``` src/app/ - page.tsx → renders , imports shared.css + skeuo.css + desktop.css - layout.tsx → html shell, metadata, fonts, ThemeScript + page.tsx → renders , imports page.css + skeuo.css + layout.tsx → html shell, metadata, ThemeScript globals.css → base/reset styles + Tailwind import data.ts → socials, codingProjects, techProjects, friends, wallpapers - skeuo.css → the skeuo console: materials, objects, depth - desktop.css → Windows/Plasma desktop + mobile home styles - shared.css → styles for components both shells render + page.css → base / terminal theme styles + skeuo.css → Windows/Plasma desktop + mobile home styles revival-inc/page.tsx → fullscreen iframe embedding /public/revival-inc/index.html api/ heatmap/route.ts → proxy for git.dvorakmortonxd.dev contribution heatmap @@ -93,9 +87,9 @@ src/app/ frame/route.ts → header-stripping proxy so an unframeable friend site loads in a window; host allowlist components/ ThemeRoot.tsx → picks which shell to show (the router of the UI) - SkeuoLayout.tsx → "skeuo" theme (the console): every section as an object - WindowsDesktop.tsx → "desktop" theme, desktop: icons, windows, taskbar - MobileHome.tsx → "desktop" theme, phone: app grid + dock + TerminalLayout.tsx → "terminal" theme (Gruvbox) + WindowsDesktop.tsx → "skeuo" theme, desktop: icons, windows, taskbar + MobileHome.tsx → "skeuo" theme, phone: app grid + dock WinWindow.tsx → a single draggable/resizable window apps.tsx → APPS registry + the content of each app + in-app terminal + embedded-site windows + the Minecraft-style SMP menu @@ -107,31 +101,23 @@ src/app/ ContributionHeatmap.tsx → heatmap + recent-commit widget (uses the two proxies) Clock.tsx → live clock (useSyncExternalStore + interval) JokerLogo.tsx → site logo with a click easter egg + SlBackground.tsx → animated ASCII train background (terminal theme) scripts/ dev-server.mjs → custom dev server: live updates minus the dev-only debug surface ``` ### How UI selection works -1. `ThemeScript` runs before paint. It reads `localStorage['dmx-theme']`, - migrating the legacy `theme` key once (`terminal` → `skeuo`, `skeuo` → - `desktop`), then sets `data-theme` (`skeuo` | `desktop`) and `data-device` - (`phone` | `desktop`, from a user-agent sniff) on ``. Viewports wider - than 768 px always get `skeuo`. +1. `ThemeScript` runs before paint. It reads `localStorage.theme` and sets + `data-theme` (`skeuo` | `terminal`) and `data-device` (`phone` | `desktop`) + on `` from a user-agent sniff. 2. `useTheme()` (in `useTheme.ts`) reads `data-theme` via `useSyncExternalStore` and dispatches a `theme-change` event on toggle. - `setTheme("desktop")` is refused when the viewport is wider than 768 px, so - nothing can leave a desktop visitor stuck in the sim. -3. `ThemeRoot` always renders `SkeuoLayout` (kept mounted, just hidden, while - the sim is up so its scroll position survives). On phone-width viewports it - additionally mounts **both** `WindowsDesktop` and `MobileHome` and lets CSS - (`html[data-device="phone"]`) decide which is visible; they stay mounted while - hidden so the Welcome window isn't recreated. The sim is never mounted wider - than that. +3. `ThemeRoot` shows the terminal when `theme === "terminal"`; otherwise it + mounts **both** `WindowsDesktop` and `MobileHome` and lets CSS + (`html[data-device="phone"]`) decide which is visible. The desktop stays + mounted while hidden so the Welcome window isn't recreated. -Themes: `skeuo` = the site itself (walnut + aluminium console), `desktop` = the -phone-only KDE Plasma / Windows simulation. The physical switch between them sits -on the nameplate (`.sk-desktop-switch`, styled as `.sk-switch`) and is only -visible at ≤ 768 px. +Themes: `skeuo` = KDE Plasma / Windows desktop, `terminal` = Gruvbox terminal. --- @@ -231,31 +217,7 @@ list reordering, not free placement. Don't confuse the two. - Components are client components (`"use client"` at the top) — they use pointer events and window APIs freely. - CSS classes are prefixed by area: `win-` (desktop), `mobile-` (phone), - `app-` / `kickoff` / `terminal` etc. Grep by prefix to find styles. The skeuo - theme's own classes all start with `sk-` (`skeuo.css`) and that prefix is - reserved for it — `desktop.css` only ever uses `skeuo-*` for its two roots. -- **The skeuo theme is CSS-only.** No texture images, no `url()` beyond the - social SVG masks: wood, aluminium, brass, leather, bakelite, paper, glass and - rubber are gradients + `color-mix()` + an inline-SVG `feTurbulence` grain - (`--sk-noise`). Build new surfaces from those tokens (`--sk-raise-1/2`, - `--sk-sink-1`, `--sk-alu-*`, `--sk-brass-*`, `--sk-wood-*`, `--sk-paper-*`) - rather than inventing new colours, and keep the light coming from the - top-left. Simplify (drop noise, flatten shadows) at ≤ 768 px. -- **`shared.css` is shared.** Both shells render `ServiceButton`, - `ContributionHeatmap`, `JokerLogo`, the project cards and the social buttons. - Change their base styles only if you check the desktop (`.app-surface` / - `.win-body` in `desktop.css` layers its own overrides on top). The skeuo theme - restyles them from `skeuo.css`, scoped to `html[data-theme="skeuo"]`, so the - desktop keeps its look. The `:root` block in `shared.css` is only the fallback - palette those components inherit. -- **Motion stays cheap.** Transitions are 100–150 ms and only ever animate - `transform` / `opacity`; pressed states move down and swap their shadow - without animating it. Anything animated respects - `@media (prefers-reduced-motion: reduce)`. -- **The desktop sim is phone-only.** `.sk-switch` is hidden above 768 px and - `setTheme("desktop")` refuses to apply there; `ThemeRoot` also force-switches - back to `skeuo` when the viewport grows. Don't add another way into the sim - without keeping those three guards in place. + `app-` / `kickoff` / `terminal` etc. Grep by prefix to find styles. - Several places deliberately use **imperative DOM work** (drag ghost, transform-origin for the mobile launch animation). This is intentional for performance; prefer matching the existing pattern over "Reactifying" it. diff --git a/public/gruvbox.webp b/public/gruvbox.webp new file mode 100644 index 0000000..f4fe2d8 Binary files /dev/null and b/public/gruvbox.webp differ diff --git a/src/app/api/ping/route.ts b/src/app/api/ping/route.ts index fbd795b..0bc19d4 100644 --- a/src/app/api/ping/route.ts +++ b/src/app/api/ping/route.ts @@ -8,7 +8,7 @@ import { NextResponse } from 'next/server'; // // Host matching is exact or by subdomain (e.g. anything under // dvorakmortonxd.dev). Keep this in sync with the ServiceButton `url`/`checkUrl` -// values in components/apps.tsx and components/SkeuoLayout.tsx, and with the +// values in components/apps.tsx and components/TerminalLayout.tsx, and with the // friend list in data.ts. const ALLOWED_HOSTS = [ 'dvorakmortonxd.dev', // ai / jelly / navidrome / git / proxmox / mc (SMP) diff --git a/src/app/components/SkeuoLayout.tsx b/src/app/components/SkeuoLayout.tsx deleted file mode 100644 index 271014b..0000000 --- a/src/app/components/SkeuoLayout.tsx +++ /dev/null @@ -1,519 +0,0 @@ -"use client"; - -import Image from "next/image"; -import type { CSSProperties, ReactNode } from "react"; -import JokerLogo from "./JokerLogo"; -import ServiceButton from "./ServiceButton"; -import ContributionHeatmap from "./ContributionHeatmap"; -import { setTheme } from "./useTheme"; -import { socials, codingProjects, techProjects, friends } from "../data"; - -/* ------------------------------------------------------------------ parts */ - -/** A small engraved brass / enamel plate — every object is labelled like a machine. */ -function Plate({ - children, - tone = "brass", - className = "", -}: { - children: ReactNode; - tone?: "brass" | "red" | "ivory"; - className?: string; -}) { - return {children}; -} - -/** A recessed dark-glass window: where the console prints machine output. */ -function Readout({ children, className = "" }: { children: ReactNode; className?: string }) { - return ( -
-
- ); -} - -/** Weight → needle angle on a 240° dial. */ -const GAUGE_MAX = 180; -const needle = (kg: number) => `${(-120 + (kg / GAUGE_MAX) * 240).toFixed(1)}deg`; - -const GYM = [ - { key: "squat", label: "SQUAT", weight: 125, date: "5.1.2025", icon: "/squat.svg" }, - { key: "bench", label: "BENCH", weight: 111, date: "29.5.2026", icon: "/bench.svg" }, - { key: "deadlift", label: "DEADLIFT", weight: 165, date: "17.12.2024", icon: "/deadlift.svg" }, -]; - -/* ------------------------------------------------------------------- page */ - -export default function SkeuoLayout() { - return ( -
-
- {/* ------------------------------------------------------ nameplate */} -
- - - -

dvorakmortonxd.dev

- -
- -
- {/* ------------------------------------------------------ welcome */} -
- - README.MD - -
- - martin@dvorakmortonxd - :~$ whoami - -

- Welcome my personal website! Here I show off my projects and hardware I own, - aswell as my self-hosted services :) -

-
- -
- - {/* ------------------------------------------------------ socials */} -
- - SOCIALS.JS - -

Patch bay — every line is a live feed

- -
- {socials.map((s) => ( - - {s.name} - {s.name} - - ))} -
- -

-

-
- - {/* ---------------------------------------------------------- gym */} -
- - - GYM_SBD_AT_73KG_BW.DB - - -

Analogue load meters — best lifts, bodyweight 73 kg

- -
- {GYM.map((g) => ( -
-
- -
-
{g.label}
-
- {g.weight}kg -
-
{g.date}
-
- ))} -
-
- - {/* ---------------------------------------------------------- now */} -
- - - NOW.TXT - - -
-
-
- - {/* -------------------------------------------------- about me */} -
-
- - {/* ----------------------------------------------------- services */} -
-
- SERVICES.HTML -
- -
- - - - - - -
-
- - {/* ------------------------------------------------------- gitdxd */} -
- - GITDXD.GIT - -
-

GitDXD

-

My Self-hosted Git Instance

- -
-
- -
-

- My very own forgejo git instance, originally started as a private git instance for me - and my friends to boycott GitHub but I've made it public now so. Join at{" "} - git.dvorakmortonxd.dev. -

-
-
-
- - {/* ------------------------------------------------ contributions */} -
-
- - CONTRIBUTIONS@GITDXD.GIT - -
-
- -
-
- - {/* ----------------------------------------------------- revival */} -
- - - REVIVAL.INC - - -
-
-
- -
-

What is it?

-

- It's a game I made for the game jam "Mini Jame Gam #55", the theme was - Necromancy and the special item was Milk, the game also includes a tutorial so if you - wanna try it do it. Check it out at{" "} - itch.io or play{" "} - here. -

-
-
-
- - {/* --------------------------------------------------- rustywolf */} -
- - RUSTYWOLF.RS - -
-
- - RustyWolf Browser Preview -
- -
-

Introducing RustyWolf — what makes it so cool???

-

- A lightweight browser made in Rust with WebKitGTK. It's the successor to my previous - project Venturesome, aiming to provide a fast and minimalist browsing experience. - It's a perfect browser for old machines that struggle with modern browsers. Check it - out at{" "} - GitDXD. -

-
-
-
- - {/* ----------------------------------------------------- hardware */} -
-
- TECH_LIST.JSON -

All my hardware equipment :)

-
- -
-
- {techProjects.map((project) => ( -
-
- ))} -
-
-
- - {/* ----------------------------------------------------- projects */} -
-
- - PROJECTS.DOCX - -

All the stuff I've worked on :))

-
- -
-
-
- {codingProjects.map((project, idx) => ( - - -
-
-
-
- - {/* ------------------------------------------------------ friends */} -
- - FRIENDS.TSX -

- Friend's websites and projects -

- -
- {friends.map((friend, idx) => ( - } - name={friend.name} - desc={friend.desc} - /> - ))} -
-
-
- - {/* -------------------------------------------------------- footer */} -
-
-
-
- ); -} diff --git a/src/app/components/SlBackground.tsx b/src/app/components/SlBackground.tsx new file mode 100644 index 0000000..4f9ad36 --- /dev/null +++ b/src/app/components/SlBackground.tsx @@ -0,0 +1,106 @@ +"use client"; + +import { useEffect, useState } from "react"; + +const TRAIN_ASCII = ` ==== ________ ___________ + _D _| |_______/ \\__I_I_____===__|_________| + |(_)--- | H\\________/ | | =|___ ___| _________________ _________________ _________________ _________________ _________________ _________________ + / | | H | | | | ||_| |_|| _| \\_____| \\_____| \\_____| \\_____| \\_____| \\_____A + | | | H |__--------------------| [___] | =| | | | | | | + | ________|___H__/__|_____/[][]~\\_______| | -| | | | | | | + |/ | |-----------I_____I [][] [] D |=======|____|________________________|_______________________|_______________________|_______________________|_______________________|_______________________|_ +__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__|__________________________|_______________________|_______________________|_______________________|_______________________|_______________________| + |/-=|___|= || || || |_____/~\\___/ |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| |_D__D__D_| + \\_/ \\O=====O=====O=====O_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/`; + +export default function SlBackground() { + const [pos, setPos] = useState(150); + + useEffect(() => { + let animationFrameId: number; + let lastTime = 0; + + const animate = (timestamp: number) => { + if (!lastTime) lastTime = timestamp; + const delta = timestamp - lastTime; + + // Update position every ~30ms to create a retro sliding terminal refresh feel + if (delta > 45) { + setPos((prev) => { + if (prev <= -150) return 150; + return prev - 1.5; + }); + lastTime = timestamp; + } + animationFrameId = requestAnimationFrame(animate); + }; + + animationFrameId = requestAnimationFrame(animate); + return () => cancelAnimationFrame(animationFrameId); + }, []); + + return ( + <> + +
+
+          {TRAIN_ASCII}
+        
+
+ + ); +} + + + + + + + + + + diff --git a/src/app/components/TerminalLayout.tsx b/src/app/components/TerminalLayout.tsx new file mode 100644 index 0000000..e48b482 --- /dev/null +++ b/src/app/components/TerminalLayout.tsx @@ -0,0 +1,603 @@ +import Image from "next/image"; +import type { CSSProperties } from "react"; +import SlBackground from "./SlBackground"; +import JokerLogo from "./JokerLogo"; +import ServiceButton from "./ServiceButton"; +import ContributionHeatmap from "./ContributionHeatmap"; +import { useTheme } from "./useTheme"; +import { socials, codingProjects, techProjects, friends } from "../data"; + +type PanelStyle = CSSProperties & { "--panel-color"?: string }; + +const panelStyle = (color: string, style: CSSProperties = {}): PanelStyle => ({ + ...style, + "--panel-color": color, +}); + +export default function TerminalLayout() { + const { toggle } = useTheme(); + + return ( + <> + +
+
+
+ +

dvorakmortonxd.dev

+ +
+
+ +
+
+ + README.MD + +

$ whoami

+

+ Welcome my personal website! Here I show off my projects and hardware I own, + aswell as my self-hosted services :) +

+
+ +
+
+ + SOCIALS.JS + +
+ {socials.map((s) => ( + + {s.name} + {s.name} + + ))} +
+
+ mail if u ever wanna contact me:{" "} + dvorak@dvorakmortonxd.dev +
+
+
+ +
+
+ + GYM_SBD_AT_73KG_BW.DB + +
+
+ Squat +
SQUAT
+
125kg
+
5.1.2025
+
+
+ Bench +
BENCH
+
111kg
+
29.5.2026
+
+
+ Deadlift +
DEADLIFT
+
165kg
+
17.12.2024
+
+
+
+
+ +
+
+ + NOW.TXT + +
+

+ martin@dvorakmortonxd: + ~$ cat now.txt +

+
+

+ I'm currently hosting an SMP (dm me on discord). Also I'm pretty + much cooking daily, because im bulking through out the non-summer seasons. + And me and my pal Pepa are working on an + education app so we can study more efficiently, It's called{" "} + maturita.c! +

+
+
+
+
+ +
+
+ + README.MD + +
+

+ martin@dvorakmortonxd: + ~$ cat about_me.md +

+
+

+ Hey, I'm Martin Dvořák — a 17(soon to be 18)-year-old IT student based + in the Czech Republic, specializing in network management and + administration at sssvt.cz. I'm a + sophomore and I have wanted to go to this school since 7th grade (2022) so + I'm happy I got in in 2025, the school is pretty cool so if you are in + middle school and interested in IT, make sure to check it out. I'm a + homelabber and developer heavily focused on self-hosting{" "} + literally everything, writing code (for example games for gamejams), + tinkering with GNU/Linux or Musl/Linux systems and retro hardware. I own a + small collection of laptops ranging from 2009 to 2014 (and ofcourse my 2025 + macbook), most of these found in ewaste. In my free time I mostly spend + time with my gf {"<"}3, I also spend a bit of time setting up my self + hosted stuff (like jellyfin or gitdxd), and also when I'm in my gaming + mood I play terraria (around 1300hr playtime btw) and minecraft modpacks + with mekanism and/or create. I also go to the gym around 3-5 times a week, + running a PPL split focused on strength/powerlifting and especially SBD. I + take a big focus on my health and physique. + +

+
+
+
+
+ +
+
+ + SERVICES.HTML + +
+ + + + + + +
+
+
+ +
+
+ + GITDXD.GIT + +
+

+ GitDXD +

+

+ My Self-hosted Git Instance +

+
+ GitDXD Preview +
+
+

+ My very own forgejo git instance, originally started as a private git + instance for me and my friends to boycott GitHub but I've made it + public now so. Join at{" "} + + git.dvorakmortonxd.dev + + . +

+
+
+
+
+ +
+
+ + CONTRIBUTIONS@GITDXD.GIT + +
+ +
+
+
+ +
+
+ + REVIVAL.INC + +
+

+ Revival inc. +

+
+ revival inc thumbnail +
+

+ What is it? +

+
+

+ It's a game I made for the game jam "Mini Jame Gam #55", the + theme was Necromancy and the special item was Milk, the game also includes + a tutorial so if you wanna try it do it. Check it out at{" "} + + itch.io + {" "} + or play{" "} + + here + + . +

+
+
+
+
+ +
+
+ + RUSTYWOLF.RS + +
+

+ Introducing RustyWolf +

+
+ RustyWolf Browser Preview +
+

+ What makes it so cool??? +

+
+

+ A lightweight browser made in Rust with WebKitGTK. It's the successor + to my previous project Venturesome, aiming to provide a fast and minimalist + browsing experience. It's a perfect browser for old machines that + struggle with modern browsers. Check it out at{" "} + + + GitDXD + + + . +

+
+
+
+
+
+ +
+
+
+ + TECH_LIST.JSON + +

+ All my hardware equipment :) +

+
+ {techProjects.map((project) => ( +
+
+

{project.title}

+

{project.desc}

+
+ ))} +
+
+
+ +
+
+ + PROJECTS.DOCX + +

+ All the stuff I've worked on :)) +

+
+ {codingProjects.map((project, idx) => ( + + +
+
+ +
+
+ + FRIENDS.TSX + +

+ Friend's websites and projects +

+
+ {friends.map((friend, idx) => ( + + } + name={friend.name} + desc={friend.desc} + /> + ))} +
+
+
+
+ +
+ v2.1.0 + © 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just follow + the GPL3.0 License) +
+
+ + ); +} diff --git a/src/app/components/ThemeRoot.tsx b/src/app/components/ThemeRoot.tsx index 12f4ccc..8b49383 100644 --- a/src/app/components/ThemeRoot.tsx +++ b/src/app/components/ThemeRoot.tsx @@ -1,57 +1,32 @@ "use client"; -import { useEffect, useState } from "react"; -import { setTheme, useTheme } from "./useTheme"; -import SkeuoLayout from "./SkeuoLayout"; +import { useTheme } from "./useTheme"; +import TerminalLayout from "./TerminalLayout"; import WindowsDesktop from "./WindowsDesktop"; import MobileHome from "./MobileHome"; export default function ThemeRoot() { const { theme } = useTheme(); - const [phone, setPhone] = useState(false); - - // The desktop simulation only exists on phone-sized viewports. On anything - // wider the page is always the skeuo theme, and a stale "desktop" - // preference is overridden here so nobody is stuck in a mode whose switch - // they cannot reach. - useEffect(() => { - if (typeof window.matchMedia !== "function") return; - const mq = window.matchMedia("(max-width: 768px)"); - const sync = () => { - setPhone(mq.matches); - if (!mq.matches && document.documentElement.getAttribute("data-theme") === "desktop") { - setTheme("skeuo"); - } - }; - sync(); - mq.addEventListener("change", sync); - return () => mq.removeEventListener("change", sync); - }, []); - - const desktop = theme === "desktop"; + const terminal = theme === "terminal"; + // The desktop is kept mounted (just hidden) while the Gruvbox/terminal theme + // is active. That way the Welcome window is only created on a fresh page + // load and isn't reopened by toggling themes. return ( <> - {/* - The skeuo theme stays mounted (just hidden) while the desktop is up so - its scroll position survives a toggle. The desktop is mounted once the - viewport is known to be a phone and then kept mounted, so the Welcome - window is only created on demand and isn't reopened by toggling. - */} -
- +
+
- - {phone ? ( - <> -
- -
-
- -
- - ) : null} +
+ +
+ {terminal && } ); } diff --git a/src/app/components/ThemeScript.tsx b/src/app/components/ThemeScript.tsx index bf34d65..2546edf 100644 --- a/src/app/components/ThemeScript.tsx +++ b/src/app/components/ThemeScript.tsx @@ -7,27 +7,7 @@ import { useServerInsertedHTML } from "next/navigation"; // without a flash. It is injected with useServerInsertedHTML so the