fix(homepage): uniform 4-column grid, hold the status gutter, unleak AI Systems
The board's card width changed at every group boundary because `columns:` was being tuned per group under the 2026-08-18 "columns = member count" rule. That rule is retired: it sets `lg:grid-cols-N` for one group, so it fixes that group's CARD WIDTH, not its density. Measured on the live board, Notes rendered a single 1464px card, News and Media 728px, Eval & Retrieval 286px, everything else 360px. All 20 groups are now `columns: 4` and every card renders at 360. `.service-name` reserved a 78px status gutter with `padding-right` and relied on `overflow: hidden` to hold it, but overflow clips at the PADDING box — the gutter was spill room the title printed straight through. Six cards on the AI tab rendered their name underneath their own status pill, measured by testing the title text node's box against the status cluster's. The intended ellipsis never fired either: it is painted by whichever block's own line overflows, and that is the anonymous box around the bare title text node, which does not carry `overflow`. The gutter holds by wrapping now, and the description opts back out of it with a negative margin since the pill only ever covers the first line. Scriberr's `homepage.group=AI Systems` named a group absent from `layout:`, so it had no `tab:` and rendered on all four tabs — the same defect as UltraSeedbox in 2026-08-18, arriving this time from a container label. Relabelled to `AI - Audio Tools`, where the other ASR seats already live. The `homepage.group=AI Systems` sample in the repo-root CLAUDE.md was the source of the name and now carries the constraint, plus the fact that a labelled container is discovered from any of the five configured engines and must not also be listed in services.yaml. Also: descriptions clamped to three lines so a five-line outlier stops dragging its row 50px taller than its neighbours; icon ramp overridden off slate-400 -> slate-700, which was sinking the bottom half of every glyph into the card fill; bookmark groups and Jellyfin's trailing stream rows brought into the card and eyebrow vocabulary; group gap 10px -> 22px now that width no longer separates them. The icon override sits on `html[class]`, not `:root`: Homepage sets the same variables on `.theme-slate`, which is on the <html> element, and a class beats `:root` on the same element. Verified with Playwright against the live board — per-group card width, card height spread, and a geometric title-vs-status collision check, before and after. Before/after captures: http://10.100.10.50:8090/b/homepage-relayout/
This commit is contained in:
@@ -74,30 +74,50 @@ useEqualHeights: false
|
||||
# If you add an AI group, place it by asking "would I click this?", not by
|
||||
# how central the service is to the fleet.
|
||||
#
|
||||
# COLUMN COUNTS ARE NOT A STYLE CHOICE — they are the member count.
|
||||
# `columns: N` lays the group out N-per-row and leaves the remainder of the
|
||||
# last row as dead space. A 1-member group at columns:4 renders one card and
|
||||
# three empty cells, which is what made this dashboard look ragged before
|
||||
# 2026-08-18. Rule: set columns to the member count, or to the divisor that
|
||||
# leaves the smallest remainder. Re-check when a group gains or loses a
|
||||
# service — `GET /api/services` prints the live per-group counts.
|
||||
# COLUMNS ARE 4 EVERYWHERE. DO NOT TUNE THEM PER GROUP.
|
||||
#
|
||||
# EVERY GROUP NEEDS A `tab:` — including bookmark groups. A group with no tab
|
||||
# assignment renders on ALL FOUR TABS. That is how UltraSeedbox ended up
|
||||
# repeated at the bottom of every tab (fixed 2026-08-18); it is Homepage
|
||||
# behaviour, not a bug, and it will happen again to the next group added
|
||||
# without a tab.
|
||||
# `columns: N` is not a density dial — it sets `lg:grid-cols-N` on that one
|
||||
# group, so it fixes the CARD WIDTH for that group alone. Varying it per group
|
||||
# means the card width changes every time you cross a group boundary, and a
|
||||
# page whose grid keeps resizing as you scroll reads as broken layout even when
|
||||
# every individual group is fine.
|
||||
#
|
||||
# The predecessor rule here was "columns = the member count", written to avoid
|
||||
# the dead cells a 1-member group leaves in a 4-wide row. It trades one flaw
|
||||
# for a worse one: at columns:1 a single service becomes a 1500px-wide bar
|
||||
# holding six words, and at columns:2 a three-member group orphans its third
|
||||
# card onto a half-empty row. Measured on the live board 2026-08-24 — the
|
||||
# Notes, News, Media, AI - Image & Media and AI - Audio Tools groups were all
|
||||
# rendering cards two to four times wider than the groups above and below them.
|
||||
#
|
||||
# A short last row is what a grid looks like. A card that is wider than its
|
||||
# neighbours is what a mistake looks like. Uniform wins.
|
||||
#
|
||||
# Homepage's own responsive ramp (`grid-cols-1 md:grid-cols-2 lg:grid-cols-N`)
|
||||
# still collapses this to 2-up and 1-up on narrow viewports, so 4 is a desktop
|
||||
# maximum, not a hard floor.
|
||||
#
|
||||
# EVERY GROUP NEEDS A `tab:` — including bookmark groups, and including groups
|
||||
# that arrive from a `homepage.group=` container label rather than from this
|
||||
# file. A group with no tab assignment renders on ALL FOUR TABS. That is how
|
||||
# UltraSeedbox ended up repeated at the bottom of every tab (fixed 2026-08-18)
|
||||
# and how Scriberr's `AI Systems` label did the same from 2026-08-23 (fixed
|
||||
# 2026-08-24 by relabelling it into `AI - Audio Tools`). It is Homepage
|
||||
# behaviour, not a bug, and it will happen again to the next container labelled
|
||||
# with a group name that does not appear below.
|
||||
# `GET /api/services` prints the live group list — anything in it that is not a
|
||||
# key here is currently leaking onto all four tabs.
|
||||
layout:
|
||||
Notes:
|
||||
icon: mdi-note-text-outline
|
||||
tab: Main
|
||||
style: row
|
||||
columns: 1
|
||||
columns: 4
|
||||
News:
|
||||
icon: mdi-rss
|
||||
tab: Main
|
||||
style: row
|
||||
columns: 2
|
||||
columns: 4
|
||||
Monitoring:
|
||||
icon: mdi-chart-line
|
||||
tab: Main
|
||||
@@ -108,19 +128,16 @@ layout:
|
||||
tab: Main
|
||||
style: row
|
||||
columns: 4
|
||||
# 2 wide, not 3 — Plex and Jellyfin carry stat-block widgets that get
|
||||
# squeezed to unreadable at 4-across, and 4 members / 3 columns orphaned
|
||||
# Jellyfin onto a row of its own.
|
||||
Media:
|
||||
icon: mdi-play-box-multiple
|
||||
tab: Main
|
||||
style: row
|
||||
columns: 2
|
||||
columns: 4
|
||||
Games:
|
||||
icon: mdi-gamepad-square
|
||||
tab: Main
|
||||
style: row
|
||||
columns: 1
|
||||
columns: 4
|
||||
# Bookmarks. Listed here for the tab pin above all else — without it this
|
||||
# group appears on every tab. `style: row` also turns the eight entries
|
||||
# from full-width stacked bars into a compact grid.
|
||||
@@ -141,13 +158,14 @@ layout:
|
||||
icon: mdi-image-multiple
|
||||
tab: AI
|
||||
style: row
|
||||
columns: 2
|
||||
columns: 4
|
||||
# Mixed: YT Voice Clipper has an audition console, Parakeet is an API.
|
||||
# Scriberr joined here 2026-08-24 (it was the stray `AI Systems` group).
|
||||
AI - Audio Tools:
|
||||
icon: mdi-waveform
|
||||
tab: AI
|
||||
style: row
|
||||
columns: 2
|
||||
columns: 4
|
||||
# Below here: model seats whose href is a vLLM `/docs` page. Status at a
|
||||
# glance is the whole value; you consume these through the gateway, not by
|
||||
# clicking them.
|
||||
@@ -160,7 +178,7 @@ layout:
|
||||
icon: mdi-scale-balance
|
||||
tab: AI
|
||||
style: row
|
||||
columns: 5
|
||||
columns: 4
|
||||
AI - Speech (TTS):
|
||||
icon: mdi-account-voice
|
||||
tab: AI
|
||||
@@ -183,12 +201,12 @@ layout:
|
||||
icon: si-proxmox
|
||||
tab: Infrastructure
|
||||
style: row
|
||||
columns: 3
|
||||
columns: 4
|
||||
Infra - IRV:
|
||||
icon: mdi-brain
|
||||
tab: Infrastructure
|
||||
style: row
|
||||
columns: 2
|
||||
columns: 4
|
||||
Infra - ESH:
|
||||
icon: si-proxmox
|
||||
tab: Infrastructure
|
||||
|
||||
Reference in New Issue
Block a user