bump to 2.2.5; friends: emoji avatars + always-2-column grid
This commit is contained in:
parent
d30945e400
commit
2fbfd6d096
9 changed files with 73 additions and 37 deletions
|
|
@ -72,7 +72,7 @@ more.
|
||||||
- **Fonts:** the web theme uses the system sans stack; Monocraft (self-hosted in `public/`) is
|
- **Fonts:** the web theme uses the system sans stack; Monocraft (self-hosted in `public/`) is
|
||||||
used by the desktop theme's SMP menu and the in-desktop terminal.
|
used by the desktop theme's SMP menu and the in-desktop terminal.
|
||||||
- **Images:** `next/image`
|
- **Images:** `next/image`
|
||||||
- **Version:** `2.2.4` (see `package.json`)
|
- **Version:** `2.2.5` (see `package.json`)
|
||||||
|
|
||||||
## 🚀 Running Locally
|
## 🚀 Running Locally
|
||||||
|
|
||||||
|
|
|
||||||
31
agents.md
31
agents.md
|
|
@ -31,6 +31,19 @@ When in doubt, prefer updating. A stale README **or** agents.md is treated as a
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Bump the version on EVERY prompt — also do this every time
|
||||||
|
|
||||||
|
Another standing requirement: increment the **patch** version (`x.x.+1`, so
|
||||||
|
`2.2.5` → `2.2.6` → …) as part of every task, even the small ones. Keep all of
|
||||||
|
these in sync:
|
||||||
|
|
||||||
|
- `package.json` → `"version"`
|
||||||
|
- `package-lock.json` → the root `"version"` **and** `packages[""].version`
|
||||||
|
- the `vX.Y.Z` label in `WebLayout.tsx`'s `.web-footer-label`
|
||||||
|
- the version line in `README.md` and in this file
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## What this project is
|
## What this project is
|
||||||
|
|
||||||
Personal portfolio site for **dvorakmortonxd.dev**. It's not a normal website —
|
Personal portfolio site for **dvorakmortonxd.dev**. It's not a normal website —
|
||||||
|
|
@ -43,7 +56,7 @@ frosted-glass **web** site, and an alternate KDE/Plasma **desktop simulation**
|
||||||
utilities in the components (Tailwind is present via PostCSS but the look is
|
utilities in the components (Tailwind is present via PostCSS but the look is
|
||||||
hand-written CSS).
|
hand-written CSS).
|
||||||
- Path alias: `@/*` → `src/*`.
|
- Path alias: `@/*` → `src/*`.
|
||||||
- Version: `2.2.4` (see `package.json`).
|
- Version: `2.2.5` (see `package.json`).
|
||||||
|
|
||||||
### Scripts
|
### Scripts
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -129,10 +142,13 @@ Themes: `web` = default frosted-glass website (sidebar + content, light/dark),
|
||||||
section nav, light/dark switch, desktop switch, contact/clock) beside a single
|
section nav, light/dark switch, desktop switch, contact/clock) beside a single
|
||||||
content column of `.glass` panels: hero (with a compact "Find me" socials row),
|
content column of `.glass` panels: hero (with a compact "Find me" socials row),
|
||||||
a `.web-quick` 2-up ("Right now" + "Gym PRs"), then services, activity,
|
a `.web-quick` 2-up ("Right now" + "Gym PRs"), then services, activity,
|
||||||
projects, hardware, features (Revival/RustyWolf) and friends. Friend cards are
|
projects, hardware, features (Revival/RustyWolf) and friends. Friend cards show
|
||||||
**text-only** (name + domain) in a `.friends-grid` that collapses to a 2×2
|
a big `friend.emoji` glyph (sized ~the name + domain combined) beside the name +
|
||||||
grid on phones; the desktop friend icons use a 🧙 emoji glyph (the old
|
domain; the `.friends-grid` is **always exactly 2 columns** so it stays a clean
|
||||||
per-friend SVGs are gone). Projects/hardware use a CSS multi-column
|
rectangle/square and never ends in an orphan "L" row (a 4th friend made the old
|
||||||
|
3-column grid do that). The same `friend.emoji` drives the desktop friend icon
|
||||||
|
(Josef is 🧌 goblin, the rest 🧙 — the old per-friend SVGs are gone).
|
||||||
|
Projects/hardware use a CSS multi-column
|
||||||
**masonry** gallery (`.project-grid`) so short cards don't leave half-empty
|
**masonry** gallery (`.project-grid`) so short cards don't leave half-empty
|
||||||
grid slots; on phones it drops to 2 columns with a shorter card image. The two feature panels (`.web-split`) stretch
|
grid slots; on phones it drops to 2 columns with a shorter card image. The two feature panels (`.web-split`) stretch
|
||||||
to equal height and share a fixed `16 / 10` `.web-shot` frame with
|
to equal height and share a fixed `16 / 10` `.web-shot` frame with
|
||||||
|
|
@ -393,8 +409,9 @@ knows about icon ids, via `APP_BY_ID`.
|
||||||
two differ. `bukovinafilip.com`, `vlcak.me` and `k0t4tkos-portfolio.com` send
|
two differ. `bukovinafilip.com`, `vlcak.me` and `k0t4tkos-portfolio.com` send
|
||||||
no framing headers, so they frame the live site. `skopec.dev` sends
|
no framing headers, so they frame the live site. `skopec.dev` sends
|
||||||
`X-Frame-Options: SAMEORIGIN` on every path, so `friend.proxy` routes it
|
`X-Frame-Options: SAMEORIGIN` on every path, so `friend.proxy` routes it
|
||||||
through `/api/frame`. Friend icons are a 🧙 emoji everywhere (no per-friend
|
through `/api/frame`. Friend icons come from the `friend.emoji` field (no
|
||||||
images); the web theme's friends section is text-only.
|
per-friend images) and are used both in the web friends section and on the
|
||||||
|
desktop.
|
||||||
- `/api/frame` is a **host-allowlisted** header-stripping proxy for sites that
|
- `/api/frame` is a **host-allowlisted** header-stripping proxy for sites that
|
||||||
refuse framing. It fetches the HTML server-side (so the upstream
|
refuse framing. It fetches the HTML server-side (so the upstream
|
||||||
`X-Frame-Options` never reaches the browser), injects `<base href="origin/">`
|
`X-Frame-Options` never reaches the browser), injects `<base href="origin/">`
|
||||||
|
|
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "dvorakmortonxd",
|
"name": "dvorakmortonxd",
|
||||||
"version": "2.2.4",
|
"version": "2.2.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "dvorakmortonxd",
|
"name": "dvorakmortonxd",
|
||||||
"version": "2.2.4",
|
"version": "2.2.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "^16.3.5",
|
"next": "^16.3.5",
|
||||||
"react": "^19.3.0",
|
"react": "^19.3.0",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "dvorakmortonxd",
|
"name": "dvorakmortonxd",
|
||||||
"version": "2.2.4",
|
"version": "2.2.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/dev-server.mjs",
|
"dev": "node scripts/dev-server.mjs",
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,7 @@ export default function WebLayout() {
|
||||||
key={idx}
|
key={idx}
|
||||||
url={friend.realUrl || friend.url}
|
url={friend.realUrl || friend.url}
|
||||||
className="friend"
|
className="friend"
|
||||||
|
icon={friend.emoji}
|
||||||
name={friend.name}
|
name={friend.name}
|
||||||
desc={friend.desc}
|
desc={friend.desc}
|
||||||
/>
|
/>
|
||||||
|
|
@ -344,7 +345,7 @@ export default function WebLayout() {
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<footer className="web-footer glass">
|
<footer className="web-footer glass">
|
||||||
<span className="web-footer-label">v2.2.4</span>
|
<span className="web-footer-label">v2.2.5</span>
|
||||||
© 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just
|
© 2025-2026 Martin Dvořák. All rights reserved (not really I dont care, just
|
||||||
follow the GPL3.0 License)
|
follow the GPL3.0 License)
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ const FRIEND_SHORTCUTS: Shortcut[] = friends.map((f, i) => ({
|
||||||
: f.url,
|
: f.url,
|
||||||
embed: f.iframe,
|
embed: f.iframe,
|
||||||
color: "#c0392b",
|
color: "#c0392b",
|
||||||
icon: "🧙",
|
icon: f.emoji,
|
||||||
desc: f.desc,
|
desc: f.desc,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -362,7 +362,7 @@ export default function WindowsDesktop() {
|
||||||
id: f.id,
|
id: f.id,
|
||||||
label: f.label,
|
label: f.label,
|
||||||
title: f.label,
|
title: f.label,
|
||||||
glyph: "🧙",
|
glyph: f.icon,
|
||||||
onOpen: () => openShortcut(f),
|
onOpen: () => openShortcut(f),
|
||||||
}));
|
}));
|
||||||
const allEntries = [...leftEntries, ...serviceEntries, ...friendEntries];
|
const allEntries = [...leftEntries, ...serviceEntries, ...friendEntries];
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ function FriendsApp() {
|
||||||
key={idx}
|
key={idx}
|
||||||
url={friend.realUrl || friend.url}
|
url={friend.realUrl || friend.url}
|
||||||
className="friend"
|
className="friend"
|
||||||
icon="🧙"
|
icon={friend.emoji}
|
||||||
name={friend.name}
|
name={friend.name}
|
||||||
desc={friend.desc}
|
desc={friend.desc}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ export interface Friend {
|
||||||
/** The live site: the window's `www` button and the status check use this. */
|
/** The live site: the window's `www` button and the status check use this. */
|
||||||
realUrl: string;
|
realUrl: string;
|
||||||
desc: string;
|
desc: string;
|
||||||
|
/** Avatar glyph shown next to the name (web) and as the desktop icon. */
|
||||||
|
emoji: string;
|
||||||
/** Render in an iframe in a desktop window. */
|
/** Render in an iframe in a desktop window. */
|
||||||
iframe: boolean;
|
iframe: boolean;
|
||||||
/**
|
/**
|
||||||
|
|
@ -245,6 +247,7 @@ export const friends: Friend[] = [
|
||||||
url: "https://skopec.dev/",
|
url: "https://skopec.dev/",
|
||||||
realUrl: "https://skopec.dev/",
|
realUrl: "https://skopec.dev/",
|
||||||
desc: "skopec.dev",
|
desc: "skopec.dev",
|
||||||
|
emoji: "🧌", // goblin, per the author
|
||||||
iframe: true,
|
iframe: true,
|
||||||
proxy: true,
|
proxy: true,
|
||||||
},
|
},
|
||||||
|
|
@ -253,6 +256,7 @@ export const friends: Friend[] = [
|
||||||
url: "https://bukovinafilip.com/",
|
url: "https://bukovinafilip.com/",
|
||||||
realUrl: "https://bukovinafilip.com/",
|
realUrl: "https://bukovinafilip.com/",
|
||||||
desc: "bukovinafilip.com",
|
desc: "bukovinafilip.com",
|
||||||
|
emoji: "🧙",
|
||||||
iframe: true,
|
iframe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -260,6 +264,7 @@ export const friends: Friend[] = [
|
||||||
url: "https://vlcak.me",
|
url: "https://vlcak.me",
|
||||||
realUrl: "https://vlcak.me",
|
realUrl: "https://vlcak.me",
|
||||||
desc: "vlcak.me",
|
desc: "vlcak.me",
|
||||||
|
emoji: "🧙",
|
||||||
iframe: true,
|
iframe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -268,6 +273,7 @@ export const friends: Friend[] = [
|
||||||
url: "https://k0t4tkos-portfolio.com/",
|
url: "https://k0t4tkos-portfolio.com/",
|
||||||
realUrl: "https://k0t4tkos-portfolio.com/",
|
realUrl: "https://k0t4tkos-portfolio.com/",
|
||||||
desc: "k0t4tkos-portfolio.com",
|
desc: "k0t4tkos-portfolio.com",
|
||||||
|
emoji: "🧙",
|
||||||
iframe: true,
|
iframe: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -482,6 +482,11 @@ html[data-theme="web"] body {
|
||||||
.services-buttons.services-main {
|
.services-buttons.services-main {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
/* Friends: always exactly 2 columns at every width, so the grid stays a clean
|
||||||
|
rectangle/square instead of ending in an orphan "L" row. */
|
||||||
|
.services-buttons.friends-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.service-button {
|
.service-button {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -572,25 +577,37 @@ html[data-theme="web"] body {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Friend cards centre their text (the web theme has no icon; the desktop
|
/* Friend cards: a big emoji beside the name + website, sized to roughly the
|
||||||
Friends app shows the wizard emoji above the name). */
|
two text lines combined so the (wide) card doesn't look empty. */
|
||||||
.service-button.friend {
|
.service-button.friend {
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 16px;
|
||||||
padding: 18px 16px;
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
/* Let the corner status dot anchor to the card, not to the emoji. */
|
||||||
|
.service-button.friend .service-icon-wrap {
|
||||||
|
position: static;
|
||||||
}
|
}
|
||||||
.service-button.friend .service-text {
|
.service-button.friend .service-text {
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
width: 100%;
|
width: auto;
|
||||||
/* Leave room for the corner status dot so names don't run under it. */
|
min-width: 0;
|
||||||
padding-inline: 10px;
|
|
||||||
}
|
}
|
||||||
/* Friend cards are text-only now, so let long names wrap instead of running
|
|
||||||
under the corner status dot. */
|
|
||||||
.service-button.friend .service-name {
|
.service-button.friend .service-name {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
.service-button.friend .service-icon {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
line-height: 1;
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
/* Long domains must wrap on narrow cards instead of overflowing. */
|
||||||
|
.service-button.friend .service-desc {
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
.service-button.friend .service-status-dot {
|
.service-button.friend .service-status-dot {
|
||||||
top: 12px;
|
top: 12px;
|
||||||
right: 12px;
|
right: 12px;
|
||||||
|
|
@ -603,13 +620,6 @@ html[data-theme="web"] body {
|
||||||
transform: none;
|
transform: none;
|
||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
/* The desktop Friends app shows a big wizard emoji in place of the old avatars. */
|
|
||||||
.service-button.friend .service-icon {
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
font-size: 2.6rem;
|
|
||||||
filter: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
PROJECTS / HARDWARE
|
PROJECTS / HARDWARE
|
||||||
|
|
@ -1203,9 +1213,11 @@ html[data-theme="web"][data-scheme="dark"] .heatmap-legend-cell[data-level="4"]
|
||||||
.services-buttons.services-main {
|
.services-buttons.services-main {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
/* Friends are text-only cards now, so they read fine as a 2x2 grid. */
|
/* Friend cards stay 2-up here, so tighten the padding to give the text room
|
||||||
.services-buttons.friends-grid {
|
next to the big emoji. */
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
.service-button.friend {
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 14px;
|
||||||
}
|
}
|
||||||
.social-buttons {
|
.social-buttons {
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue