rename terminal theme to web, make it the default, drop the mobile home screen, and rebuild the web shell as a light/dark glassmorphism layout
This commit is contained in:
parent
32d622f80e
commit
d947ecfb1a
21 changed files with 1707 additions and 2978 deletions
91
agents.md
91
agents.md
|
|
@ -34,15 +34,16 @@ 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 **two fully interactive desktop/OS simulations** plus a terminal, and
|
||||
picks which one to show based on theme and device.
|
||||
it ships **two shells** and renders whichever the saved theme selects: a default
|
||||
frosted-glass **web** site, and an alternate KDE/Plasma **desktop simulation**
|
||||
(desktop-only). Phones always get the web shell.
|
||||
|
||||
- Framework: **Next.js 16** (App Router, Turbopack), **React 19**, TypeScript.
|
||||
- Styling: plain CSS files (`page.css`, `skeuo.css`), no CSS-in-JS, no Tailwind
|
||||
- Styling: plain CSS files (`web.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`).
|
||||
- Version: `2.2.0` (see `package.json`).
|
||||
|
||||
### Scripts
|
||||
```bash
|
||||
|
|
@ -73,12 +74,12 @@ token.** Do not print it, copy it into new files, or push it anywhere else.
|
|||
|
||||
```
|
||||
src/app/
|
||||
page.tsx → renders <ThemeRoot/>, imports page.css + skeuo.css
|
||||
page.tsx → renders <ThemeRoot/>, imports web.css + skeuo.css
|
||||
layout.tsx → html shell, metadata, ThemeScript
|
||||
globals.css → base/reset styles + Tailwind import
|
||||
data.ts → socials, codingProjects, techProjects, friends, wallpapers
|
||||
page.css → base / terminal theme styles
|
||||
skeuo.css → Windows/Plasma desktop + mobile home styles
|
||||
web.css → web theme: frosted glass, light + dark tokens
|
||||
skeuo.css → Windows/Plasma desktop styles (desktop theme only)
|
||||
revival-inc/page.tsx → fullscreen iframe embedding /public/revival-inc/index.html
|
||||
api/
|
||||
heatmap/route.ts → proxy for git.dvorakmortonxd.dev contribution heatmap
|
||||
|
|
@ -86,38 +87,62 @@ src/app/
|
|||
ping/route.ts → service health check (HTTP + minecraft:// via mcstatus.io); host allowlist
|
||||
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)
|
||||
TerminalLayout.tsx → "terminal" theme (Gruvbox)
|
||||
ThemeRoot.tsx → picks which shell to mount (the router of the UI)
|
||||
WebLayout.tsx → "web" theme (default): sticky sidebar + glass content
|
||||
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
|
||||
useDesktopIcons.ts → desktop icon grid + drag/drop (THE KEY FILE, see below)
|
||||
useDragOrder.ts → simple list reordering (mobile home screen only)
|
||||
useTheme.ts → theme state via useSyncExternalStore
|
||||
ThemeScript.tsx → inline pre-hydration script: theme + device detection
|
||||
useTheme.ts → theme state (web | skeuo) via useSyncExternalStore
|
||||
useColorScheme.ts → light/dark scheme state via useSyncExternalStore
|
||||
ThemeScript.tsx → inline pre-hydration script: theme + scheme
|
||||
ServiceButton.tsx → service link + live status dot (pings /api/ping)
|
||||
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.theme` and sets
|
||||
`data-theme` (`skeuo` | `terminal`) and `data-device` (`phone` | `desktop`)
|
||||
on `<html>` from a user-agent sniff.
|
||||
2. `useTheme()` (in `useTheme.ts`) reads `data-theme` via
|
||||
`useSyncExternalStore` and dispatches a `theme-change` event on toggle.
|
||||
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.
|
||||
`data-theme` (`web` | `skeuo`) on `<html>`, defaulting to `web`; it also reads
|
||||
`localStorage.scheme` and sets `data-scheme` (`light` | `dark`), defaulting to
|
||||
`light`. There is no device sniff anymore.
|
||||
2. `useTheme()` (in `useTheme.ts`) reads `data-theme` via `useSyncExternalStore`
|
||||
and dispatches a `theme-change` event on toggle. `useColorScheme()` does the
|
||||
same for `data-scheme` via a `scheme-change` event.
|
||||
3. `ThemeRoot` mounts **one** shell at a time: `WebLayout` unless the theme is
|
||||
`skeuo`, in which case it mounts `WindowsDesktop`. It is deliberately *not*
|
||||
kept mounted while hidden — the desktop icon grid is measured from real
|
||||
rendered boxes, so a `display:none` desktop would measure zero-sized cells and
|
||||
break its grid when shown again.
|
||||
|
||||
Themes: `skeuo` = KDE Plasma / Windows desktop, `terminal` = Gruvbox terminal.
|
||||
Themes: `web` = default frosted-glass website (sidebar + content, light/dark),
|
||||
`skeuo` = KDE Plasma desktop simulation (desktop-only; the web sidebar's
|
||||
"Desktop" control switches to it, and it has a "Web" control in its tray).
|
||||
|
||||
### Web theme + light/dark (v2.2.0 rework)
|
||||
- `WebLayout.tsx` is the default shell. Layout is a **sticky sidebar** (brand,
|
||||
section nav, light/dark switch, desktop switch, contact/clock) beside a single
|
||||
content column of `.glass` panels (hero, quick tiles, services, activity,
|
||||
projects, hardware, features, friends). The old stacked TUI panel layout and
|
||||
the `SlBackground` ASCII train were removed with it.
|
||||
- Glassmorphism lives in one utility class, `.glass`, in `web.css`: a subtle
|
||||
`linear-gradient` over `--glass-hi`/`--glass-lo` with
|
||||
`backdrop-filter: blur(20px) saturate(165%)`. The page blobs behind the panels
|
||||
are `.web-bg` (a fixed radial-gradient layer at `z-index: 0`; `.web-root` sits
|
||||
at `z-index: 1`).
|
||||
- Colours are tokenised in `web.css` under `:root` (light) and
|
||||
`html[data-theme="web"][data-scheme="dark"]` (dark). The shared token names
|
||||
(`--fg`, `--gray`, `--accent`, `--green`, …) are reused so `ServiceButton` and
|
||||
`ContributionHeatmap` need no changes. `skeuo.css` overrides the same names
|
||||
while the desktop theme is active, so the two themes don't bleed into each
|
||||
other.
|
||||
- The desktop switch (`.web-ctl-desktop`) is hidden on phones: under the
|
||||
`max-width: 960px` breakpoint and under `(hover: none) and (pointer: coarse)`.
|
||||
There is no device sniff anymore — phones just get the responsive web shell.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -180,9 +205,8 @@ Guard (already in place, keep it that way):
|
|||
`e.target` is always the button.
|
||||
|
||||
### Related
|
||||
`useDragOrder.ts` is a **different, simpler** hook used only by `MobileHome` for
|
||||
reordering the phone app grid/dock (drag one item over another to swap). It is
|
||||
list reordering, not free placement. Don't confuse the two.
|
||||
Nothing else consumes the desktop grid. `apps.tsx` is the only other place that
|
||||
knows about icon ids, via `APP_BY_ID`.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -216,11 +240,12 @@ 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.
|
||||
- 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.
|
||||
- CSS classes are prefixed by area: `web-` (web theme), `glass` (the shared glass
|
||||
panel utility), `win-` (desktop), `app-` / `kickoff` etc. Grep by prefix to
|
||||
find styles.
|
||||
- Several places deliberately use **imperative DOM work** (the desktop drag
|
||||
ghost). This is intentional for performance; prefer matching the existing
|
||||
pattern over "Reactifying" it.
|
||||
- `setState` inside an effect is blocked by the ESLint config
|
||||
(`react-hooks/set-state-in-effect`). The one intentional exception is the
|
||||
grid init in `useDesktopIcons.ts`, which carries a scoped
|
||||
|
|
@ -326,6 +351,10 @@ list reordering, not free placement. Don't confuse the two.
|
|||
## Testing notes
|
||||
- There is **no test suite**. Verification is `tsc --noEmit`, `eslint`, and
|
||||
`next build`.
|
||||
- The default shell is the web theme: `curl -s http://localhost:3000/` should
|
||||
contain `data-theme="web"` / `data-scheme="light"` and the `.web-root` markup.
|
||||
Theme + scheme are read pre-paint from `localStorage.theme` / `.scheme`, so a
|
||||
quick check is to set those in devtools and reload.
|
||||
- A dev server may already be running on port 3000 — on this host it is normally
|
||||
the **system** `dvorakmortonxd-dev` service, so check
|
||||
`systemctl status dvorakmortonxd-dev` first. Two dev servers on this repo
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue