Commit graph

174 commits

Author SHA1 Message Date
4ab0b2fff6 Document theme palettes + organize assets (#4)
All checks were successful
CI / validate (push) Successful in 49s
2026-06-24 16:27:33 +00:00
04d491c277 System design, CloudFormation, theming assets (#3)
All checks were successful
CI / validate (push) Successful in 48s
2026-06-24 13:55:04 +00:00
320f816100 Add auto-start SSH tunnel hook (#2)
All checks were successful
CI / validate (push) Successful in 48s
2026-06-23 22:58:09 +00:00
d1697fc811 Add Forgejo Actions CI, remove GitHub Actions (#1)
All checks were successful
CI / validate (push) Successful in 47s
2026-06-23 22:52:35 +00:00
Samuel James
4422840dd3 the
Some checks failed
Deploy to racknerd1 / validate (push) Successful in 2m26s
Deploy to racknerd1 / deploy (push) Failing after 4s
2026-06-23 15:55:31 -04:00
Samuel James
b499759936 modified files
Some checks are pending
Deploy to racknerd1 / validate (push) Waiting to run
Deploy to racknerd1 / deploy (push) Blocked by required conditions
2026-06-22 16:10:05 -06:00
Samuel James
08139ff831
Make Appearance light mode work (gray theme) + roadmap GNOME/KDE RDP (#50)
Appearance tab was local-state-only — light mode did nothing. Wire it up:
- index.css: theme color tokens are now CSS variables on :root (dark default)
  with a [data-theme="light"] override using a soft GRAY page background
  (#E4E6EB), not white. The @theme tokens + html/body + select reference the
  vars, so the app shell and any component using bg-page/text-text-primary/etc.
  themes automatically.
- New src/lib/theme.ts: localStorage-backed appearance prefs (theme/fontSize/
  radius/animations) + applyAppearance() toggling data-theme on <html>, mirroring
  the terminalPrefs pattern.
- main.tsx applies saved theme before first render (no flash).
- Settings AppearanceSection persists + applies on change; theme/fontSize/radius/
  animations are live. Dropped the non-functional "Sidebar Expanded by default"
  toggle. (accent color is still cosmetic-only — full token migration of
  hardcoded-hex pages is a separate task, noted in ROADMAP.)

Also adds the Remote Desktop GNOME & KDE support work to ROADMAP as an add-on
(XFCE confirmed working; GNOME needs a FreeRDP-3 guacd image, KDE via xrdp +
startplasma-x11). Full detail in docs/rdp-debug-handoff.md.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 16:39:50 -04:00
Samuel James
d8223b01cc
Document working RDP state (XFCE) + GNOME/KDE support research (#49)
Records the full chain that got RDP working end-to-end on XFCE (auth/xrdp,
session, compositing, scaling, ping echo, input, 1080p — PRs #41-48), and adds
a desktop-environment support matrix plus researched paths to make GNOME and KDE
work too.

Key findings (VM-verified, not theory):
- XFCE over xrdp works today with guacd's FreeRDP 2.
- GNOME 50 is Wayland-only (no Xorg session for xrdp) AND gnome-remote-desktop
  mandates NLA that FreeRDP 2 can't do — blocked both ways. The real unlock is a
  custom guacd image built against FreeRDP 3; GNOME headless "system" RDP (GDM
  handover, GNOME 46+) then becomes viable.
- KDE Plasma 6 should work like XFCE via xrdp + startplasma-x11 (X11 session
  supported through ~early 2027); KRdp is the Wayland-native future path.

Includes a suggested order of work for the next agent.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 16:18:54 -04:00
Samuel James
7b13108627
Default remote desktop resolution to 1080p (#48)
Bump the guacd connectionDefaultSettings for rdp/vnc/telnet from 1024x768 to
1920x1080 so new remote desktop sessions open at 1080p by default. dpi stays 96.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 16:04:56 -04:00
Samuel James
8ccc959dc9
Wire mouse + keyboard input for RDP sessions (#47)
The multi-session RemoteDesktop view rendered the remote display but never
captured input — no Guacamole.Mouse / Guacamole.Keyboard were created — so the
desktop showed but the mouse and keyboard did nothing.

Add per-session input:
- Guacamole.Mouse on the display element, forwarding mouse state via
  client.sendMouseState with coordinates divided by the current display scale so
  clicks land correctly on the scaled-down canvas.
- Guacamole.Keyboard on document, forwarding key events via client.sendKeyEvent,
  but only while that session is the active/visible tab so a background session
  can't steal keystrokes.
- Detach keyboard handlers on session close and on unmount.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 16:00:09 -04:00
Samuel James
5f27943974
Fix RDP drop loop: echo guacamole-common-js tunnel ping server-side (#46)
THE actual root cause of the flicker-then-blank / "connected but drops" RDP
behavior. guacamole-common-js's WebSocketTunnel sends an internal stability
"ping" (empty INTERNAL_DATA_OPCODE: `0.,4.ping,<ts>;`) and resets its
receiveTimeout only on inbound data. guacamole-lite 1.2.0 forwards that ping
straight to guacd, which neither understands nor echoes it. On an idle desktop
(no frames flowing), nothing resets the client timer, so the tunnel hits
UPSTREAM_TIMEOUT, closes, and reconnects — the flicker/drop loop seen in guacd
as "User is not responding".

Fix: intercept the internal ping on the WS in guacamole.ts and echo it straight
back to the client before ClientConnection forwards it to guacd, so the client's
stability timer is satisfied even when the remote desktop is idle.

Verified separately: a guacd connection that echoes sync held 30s/116 syncs with
no drop; server/xrdp/XFCE are healthy. This was purely the missing ping echo.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 15:46:36 -04:00
Samuel James
58a46553d9
Fix RDP session drop/flicker: stop re-parenting Guacamole display (#45)
Symptom: desktop flickers in for a moment then goes blank while the tab still
says "connected"; guacd logs "User is not responding" and the client reconnects
in a loop.

Root cause: the multi-session view moved each session's display element between
DOM nodes on tab switch (host.innerHTML='' + appendChild). Detaching a
guacamole-common-js display from the DOM stalls its sync loop, so the client
stops echoing guacd's sync instructions and guacd drops it as unresponsive.
Proven out-of-band: a raw guacd client that echoes sync held a connection for
30s/116 syncs with no drop, while the browser dropped within seconds.

Fix: mount each session's container into the display host ONCE and never move
it; toggle visibility (display:none) to switch tabs so every session's display
stays in the DOM and its sync loop keeps running. Containers are absolutely
positioned in a relative host; close still removes the container.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 15:31:43 -04:00
Samuel James
a7fbbabeb2
Fix blank RDP screen in multi-session view: scale display + fit on activate (#44)
The multi-session RemoteDesktop tabs (05e78f0) appended the Guacamole display
into an off-DOM container before connecting, and never called display.scale().
Frames arrived while the canvas was detached/zero-sized, so the desktop rendered
but painted to an invisible area — connected-but-blank.

Fix: track the display per session, fit/scale it to the visible panel when a
session becomes active, on the display's own onresize, and on window resize.
Verified the VM/xrdp/guacd side streams frames fine (13-36 img frames in direct
guacd tests); this was purely the client-side mount/scale regression.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 15:12:00 -04:00
Samuel James
6c1f167f15
Document xrdp blank-screen fix #2: disable xfwm4 compositing on virtio GPU (#43)
Even with XFCE running, the screen stayed blank because xfwm4's GPU compositor
fails on the Virtio GPU (no GL driver): "Another compositing manager is running",
"failed to load driver: virtio_gpu". Fixed by disabling xfwm4 compositing via
xfconf and forcing LIBGL_ALWAYS_SOFTWARE for the RDP user. Verified a fresh
session renders cleanly through guacd.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 15:01:22 -04:00
Samuel James
060ac6c078
Document xrdp blank-screen fix (Wayland-only GNOME needs XFCE) (#42)
After replacing gnome-remote-desktop with xrdp, the connection succeeded but
showed a blank screen: GNOME 50 on Fedora is Wayland-only and can't run on
xrdp's Xorg backend, so the session started and died in ~2s. Fixed by installing
XFCE (an X11 desktop that works without GL) and creating the missing
/etc/xrdp/startwm.sh to launch it. Verified xfce4-session/xfwm4 persist and
guacd streams sustained desktop frames.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 14:50:55 -04:00
Claude
05e78f0fa5
Support multiple remote desktop sessions as tabs with disconnect controls 2026-06-22 18:44:42 +00:00
Claude
a47583a8e4
Update RDP handoff doc: connection now succeeds, blank screen is new symptom 2026-06-22 18:30:12 +00:00
Samuel James
d1fefd3a63
Resolve RDP debugging: root cause + xrdp fix for gnome-remote-desktop (#41)
The "Server refused connection (wrong security type?)" failure was root-caused
end-to-end: guacd 1.5.5 ships FreeRDP 2.11.5, whose NLA/CredSSP client cannot
authenticate against gnome-remote-desktop, which mandates NLA (HYBRID_REQUIRED_
BY_SERVER) with no option to disable it. The earlier EGL/Mesa/Zink GPU theory
was a red herring.

Proven at every layer: direct xfreerdp v3 to the VM, the real guacd protocol
path (all security modes fail identically), and guacd's own logs. Also verified
guacd:1.6.0 still ships FreeRDP 2.11.7, so an image bump would NOT fix it.

Fix applied to the test VM: replaced gnome-remote-desktop with xrdp (masked the
GNOME user service so it can't re-grab port 3389), which interoperates with
guacd's FreeRDP 2. Verified a real session streams through guacd with
security=any. No ArchNest code change was needed — the existing security/
ignore-cert handling in guacamole.ts is correct.

Documents this as a general finding since other users will hit GNOME's built-in
RDP the same way.

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-22 14:18:04 -04:00
Claude
74f8b9f705
Add RDP debugging handoff doc for next investigator 2026-06-22 14:54:47 +00:00
Claude
9578820bbd
Add RDP security mode override for hosts that reject auto-negotiated security 2026-06-22 13:26:06 +00:00
Claude
903645e789
Trust self-signed certs on RDP connections (FreeRDP rejects them by default) 2026-06-22 13:19:12 +00:00
Claude
f3dcbab444
Merge icon fallback chain and SSH name-based icon matching
# Conflicts:
#	src/pages/Infrastructure.tsx
2026-06-21 20:15:48 +00:00
Claude
03159ecde4
Match SSH connection name to specific icon (e.g. Linode, Portainer) before falling back to generic Linux icon 2026-06-21 20:13:18 +00:00
Claude
437f14e330
Add icon candidates for proxmox, weather, remote_desktop integrations 2026-06-21 20:11:34 +00:00
Claude
ba8683f5a8
Add per-integration custom icon + multi-repo fallback chain for Node Status
Settings → Integrations now has a universal "Icon" field (any integration
type) accepting a pasted URL or an uploaded image, stored as config.iconUrl.
This overrides the built-in icon for that integration's Node Status tile.

Node Status tiles now resolve their icon through a priority chain: custom
iconUrl, then each built-in CDN candidate in order (assets-public first
where available, falling back to the existing dashboard-icons CDN), and
finally the generic per-kind Lucide icon if every candidate 404s. AWS now
tries samuelsjames.github.io/assets-public's aws-logo.svg before the
jsDelivr fallback; SSH gets a Linux logo from the same repo. Proxmox,
Weather, and Remote Desktop have no built-in candidates yet (no matching
assets in that repo) and fall back to the generic icon until added.
2026-06-21 20:11:34 +00:00
Samuel James
4f765b512a
Add per-integration custom icon + multi-repo fallback chain for Node Status (#40)
Settings → Integrations now has a universal "Icon" field (any integration
type) accepting a pasted URL or an uploaded image, stored as config.iconUrl.
This overrides the built-in icon for that integration's Node Status tile.

Node Status tiles now resolve their icon through a priority chain: custom
iconUrl, then each built-in CDN candidate in order (assets-public first
where available, falling back to the existing dashboard-icons CDN), and
finally the generic per-kind Lucide icon if every candidate 404s. AWS now
tries samuelsjames.github.io/assets-public's aws-logo.svg before the
jsDelivr fallback; SSH gets a Linux logo from the same repo. Proxmox,
Weather, and Remote Desktop have no built-in candidates yet (no matching
assets in that repo) and fall back to the generic icon until added.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 16:03:51 -04:00
Samuel James
9f10e8ee6f
Group all integration node tiles by integration except Proxmox (#39)
Generalizes the Uptime Kuma monitor-grouping pattern to every integration:
Node Status now collapses each integration's resources into one tile (e.g.
30 EC2 instances under one "AWS" tile) instead of flooding the grid, with
members listed in Node Detail on selection. Proxmox stays ungrouped since
its VMs/LXCs are managed individually elsewhere in the app.

Adds integrationType to the /api/integrations/resources response so the
frontend can group/exclude by adapter type rather than resource kind (kind
alone can't distinguish Proxmox VMs from AWS VMs, for example).

Documents the grouping rule in HANDOFF.md and adds a paid-tier roadmap
entry for per-integration node tabs that will show every individual node.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 09:35:55 -04:00
Samuel James
9a1d2803a2
Fix monitor ID type mismatch causing all Uptime Kuma statuses to read unknown (#38)
heartbeatList/importantHeartbeatList emit monitor IDs as strings (server
iterates object keys), while monitorList and the live heartbeat event use
numbers. The lastHeartbeat map was keyed by the numeric monitor.id, so
string-keyed lookups from heartbeatList/importantHeartbeatList never hit.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 09:21:09 -04:00
Samuel James
b4943b1155
Listen for heartbeatList in Uptime Kuma adapter to catch monitors with no status-change history (#37)
importantHeartbeatList only contains entries for status transitions, so a
monitor that's been continuously up since creation never populates it,
showing as "unknown" in ArchNest despite being healthy in Uptime Kuma.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 09:06:01 -04:00
Claude
d50ec0076e
Group monitoring-app resources into one Node Status tile per integration
Integrations whose resources represent many sub-items (Uptime Kuma's
monitors) now collapse into a single tile using the Uptime Kuma CDN
icon, instead of flooding Node Status with one tile per monitor.
Selecting that tile lists every underlying monitor's status in a
scrollable Node Detail panel, so hundreds of monitors stay manageable.

Also drops the temporary debug logging added while diagnosing the
listener-timing bug, now that real monitor/heartbeat data confirmed
coming through.
2026-06-21 13:00:50 +00:00
Claude
0b9acd32a5
Fix Node Status grid not scrolling when it overflows
The grid's flex column parent had no min-h-0, so it grew to fit all
content instead of being capped to the card height — overflow-y:auto
on the grid itself never had anything to scroll within.
2026-06-21 12:56:54 +00:00
Claude
f390e8c586
Fix Uptime Kuma listResources missing monitorList/heartbeat events
Listeners for monitorList/importantHeartbeatList/heartbeat were being
attached after the login ack resolved, but the server pushes that
data right after login — sometimes in the same tick as the ack — so
Socket.IO dropped it before a listener existed. Listeners now attach
before login is sent.
2026-06-21 12:50:44 +00:00
Claude
89dd3471db
Add temporary debug logging to Uptime Kuma listResources
Diagnosing why a connected Uptime Kuma instance with real monitors is
producing zero Resources — logs monitor count, active flags, and last
heartbeat per monitor so we can see exactly what the Socket.IO session
returns.
2026-06-21 12:16:44 +00:00
Claude
58f007e6db
Add per-resource kind labeling and proper Node Status icons
Each adapter now tags its Resources with a kind (vm, container, app,
host, network) so Node Status tiles show the right icon instead of a
generic server glyph — Proxmox LXCs/Docker containers get a container
icon, VMs get a VM icon, Uptime Kuma monitors get an app icon, etc.

Also stops silently swallowing listResources() failures — they're now
logged as warnings, since a connected-but-empty integration (e.g.
Uptime Kuma reporting zero monitors) was previously indistinguishable
from a real adapter error.
2026-06-21 12:03:25 +00:00
Claude
8a60279720
Add selectable node status tiles and a Node Detail card
Clicking a tile in Node Status highlights it and surfaces its name,
source integration, status, and detail in a new Node Detail card on
the bottom row, between Integration Health and a now-narrower Recent
Activity card.
2026-06-21 11:43:10 +00:00
Claude
99ca1ba39c
Tighten Integration Health row spacing and make the list scrollable
Status text now sits close to the name instead of being pushed to the
far edge, and the list caps at a fixed height with scroll so it stays
usable as more integrations are added.
2026-06-21 11:38:16 +00:00
Claude
bcdecd86d6
Merge branch 'claude/youthful-cerf-ibvxfb' 2026-06-21 11:03:38 +00:00
Claude
bbb26dab0d
Implement real Uptime Kuma monitor reporting via Socket.IO
Uptime Kuma has no REST API for monitor data; connect over the same
Socket.IO session the web UI uses (login, then read monitorList and
heartbeat events) so connected monitors now surface as Resources.
Switches the integration's credentials from an API key to
username/password, matching what Uptime Kuma's session login expects.
2026-06-21 11:00:47 +00:00
Claude
d0cd9d83a7
Force explicit grid gap + clip panes to fix missing row gap in 4-pane view
Use an explicit inline gap instead of relying solely on a dynamically
templated Tailwind class, and clip each pane's content (overflow-hidden)
so a pane can't visually bleed into the row gap below it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 10:16:18 +00:00
Claude
f191119a28
Add breathing room around terminal pane borders and content
Wider gap between panes in split view (borders were crowding each other
in 4-up grid), more inset between the pane border and the connect/
disconnect header, and a small horizontal gutter around the xterm mount
so the prompt text doesn't sit flush against the border.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 09:54:40 +00:00
Claude
1da719c541
Merge branch 'claude/youthful-cerf-ibvxfb': in-app shell prompt picker, Help page scroll fix, Glance/System Status tweaks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk

# Conflicts:
#	src/pages/Help.tsx
2026-06-21 09:26:42 +00:00
Claude
4674f4e209
Fix Help page scroll, widen Connected Integrations grid, color-code System Status ring
- Help page now scrolls (it sat under a clipped section with no overflow handling).
- Connected Integrations on Glance shows 5 per row in a scrollable area with the
  transparent ghost scrollbar, instead of growing the card unbounded.
- System Status KPI ring is now a thicker, vertically centered, multi-segment
  donut broken down by integration type, each type colored consistently from a
  shared first-come-first-served palette (src/lib/integrationColors.ts) so e.g.
  whichever type connects first always gets the same color everywhere it's used.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 09:21:56 +00:00
Claude
a964591431
Add in-app shell prompt picker: install Starship + Nerd Font on demand
Lets a user pick one of three Starship presets (Nerd Font Symbols,
Pastel Powerline, Tokyo Night) from the Terminal page and install
Starship + a Nerd Font on the active pane's SSH host with one click,
instead of running a script by hand. Idempotent on the host side, and
available to all authenticated users like the rest of the SSH/Docker
tooling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk
2026-06-21 09:10:30 +00:00
Claude
5ed6bb591f
Add host setup script for Starship + JetBrainsMono Nerd Font
Pairs with the Terminal page's Nerd Font glyph fallback: run this on any VM you SSH into from ArchNest to get a full icon-rich Starship prompt, not just working icon rendering.
2026-06-21 09:03:33 +00:00
Samuel James
ae066a738c
Containers/Infrastructure styling fixes + Terminal Nerd Font fallback (#36)
* Add mesh prerequisite gate (NetBird verification before app config)

Implements the design in docs/mesh-prerequisite-gate.md per the user's
DECIDE A-D answers: a permanent admin override, B1 (reachable) verification
with host mesh IP shown informationally, members allowed in with a notice
instead of being blocked, and mesh.required defaulting off so the live
production instance is unaffected.

- system_config kv table + getConfig/setConfig helpers
- /api/system/mesh-status, /mesh/verify, /mesh/override, /mesh/required
- AuthContext gains a 'needs-mesh' status (admins only) and exposes
  meshStatus for a member-facing banner
- MeshGate page reuses the integration create+test flow to connect NetBird

* Make mesh verification universal (CIDR check, not NetBird-specific)

Replace the NetBird-adapter-based "reachable" check with a vendor-agnostic
one: the admin supplies the mesh's IP range (CIDR), and verification just
confirms this host has an address inside it. Works identically for
NetBird, WireGuard, ZeroTier, Tailscale, or any other mesh tech, with no
integration record or vendor API call required.

* Add reachability fallback for routed meshes (VPC peering, etc.)

A host can be on the mesh's "side" of a routed network (e.g. a VPC peered
into a NetBird/WireGuard mesh) without holding a local IP in the mesh's
own CIDR. Local-IP-in-CIDR stays the primary check; if it fails, the admin
can supply a known peer/gateway IP on the mesh and we verify by pinging
it instead. Adds iputils to the backend image for the ping binary.

* Add Mesh section to Settings for configuring/testing the mesh gate

Admins can now toggle mesh.required, run verify/override, and see
current mesh status entirely from the app, without hitting the API
directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hu9pZvJY4BgmcQeAw2ugk

* Show a host-specific Docker remote-API setup script in Settings

When adding/editing a Docker integration with a tcp:// or http:// remote
URL, display a copyable systemd override + curl verification script
scoped to the entered host:port, so enabling the daemon's API doesn't
require looking up the steps separately.

* Expand Help page with quick-start guide and real-world examples

Adds a quick-start ordering card and per-feature example callouts (with icons) so first-time users see concrete use cases, not just descriptions.

* Update HANDOFF/README for handoff: mesh gate shipped, Docker UX work, no feature queued

Corrects the stale 'mesh gate not built' framing (it shipped across 4 commits, all merged) and documents the Docker setup-script hint + Help page expansion done this session. Leaves a clear next-task list for the picking-up agent: decide on merging claude/youthful-cerf-ibvxfb, then check with the user for the next priority.

* Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs

* Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar

* Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly

Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-21 05:01:39 -04:00
Claude
f41b700904
Add Nerd Font icon fallback to the Terminal so Starship-style prompts render correctly
Bundles Symbols Nerd Font Mono (MIT, ryanoasis/nerd-fonts) as a glyph-only @font-face and appends it to every Terminal font-family option, so distro icons / git branch glyphs / etc. from prompts like Starship show up instead of broken-glyph boxes. It carries no letterforms, so it never changes how normal text renders.
2026-06-21 09:00:39 +00:00
Claude
9372767443
Make Node Status card scrollable with a 5-column layout and invisible-by-default scrollbar 2026-06-21 08:52:58 +00:00
Claude
98b69e47d5
Improve Containers table/tab readability: bold centered headers, taller rows, filing-cabinet tabs 2026-06-21 08:47:52 +00:00
Samuel James
fecaa61c3f
Add files via upload 2026-06-21 04:38:58 -04:00
Samuel James
1594afdb5a
Add files via upload 2026-06-21 04:38:26 -04:00