Skip to content

Restyle the web UI with Cozy and Console themes - #16

Merged
chadleeshaw merged 72 commits into
mainfrom
cursor/ignite-frontend-restyle-8c34
Oct 23, 2026
Merged

chadleeshaw merged 72 commits into
mainfrom
cursor/ignite-frontend-restyle-8c34

Conversation

@chadleeshaw

@chadleeshaw chadleeshaw commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

Draft head d6bde68. Merges backend phase 1 at a928568 and lands the round-4 UI fixes plus the original flame mark. This pull request stays a draft.

CI: https://github.com/chadleeshaw/ignite/actions/runs/39875466832

  • Test & Quality Assurance: success
  • Build and Push Docker Image: success
  • Create Release: skipped (not a version tag)

Overview DHCP cards

The DHCP server cards use the same two-column grid as the Services row, so two cards span the full width at 1280 and at 1024. The badge and Start sit in a fixed slot on the right. "If DHCP is disabled, Start explains why." is a muted line under the pool meta.

BMC TLS

a928568 removes BMC_TLS_INSECURE. Redfish skips BMC certificate checks unless BMC_TLS_VERIFY is a strconv.ParseBool true (1, t, T, TRUE, true, True). Unset, false, and any other value leave verification off. dialGofish sets gofish Insecure: !verify.

Flame

The nav, login page, favicon, and apple-touch icon use a crop of the original illustrated flame. The source now lives at assets/brand/Ignite_small.png, and scripts/build-flame.mjs drops the faint circle and swirl lines. It writes PNG and WebP for the nav at 1x and 2x (25×32 and 49×64), plus favicon 32, apple-touch 180, and 512. Each file is under 30 KB. Nothing in public/ serves the 1.3 MB original. Resource tiles that used the generic flame.svg use this same mark, and a stopped tile stays greyscale.

Nav logo in Cozy
Nav logo in Console

The navy bar is shared by both modes, so the close crop of the mark matches.

Round-4 UI

  • DHCP Start, and a save that restarts a listener, show the 409 user message as written: "DHCP is disabled. Set DHCP_ENABLED=true before starting a server."
  • A Syslinux version whose extract cache is missing shows re-download instead of Activate.
  • The TFTP breadcrumb is ⌂ TFTP root / boot-bios. The absolute path appears only in the Root tile.
  • Cozy hides .lease-rows.
  • The provision editor is capped to the viewport with internal scroll. [hidden] { display: none !important; } keeps Quick Help closed until it is opened.
  • Timestamps include the short zone name. The no-JS label uses the value's own zone and adds UTC only when the value is UTC.

Phase 2 stays out: command palette, greeting, activity feed, checklist, and drag-and-drop.

Exercised against a running server

No response was 403 or 500.

  • Login: 200
  • Reserve a lease: 200
  • Delete a lease: 200
  • DHCP Start with DHCP_ENABLED=false: 409, and the toast is the sentence above
  • TFTP upload: 200
  • TFTP delete: 303
  • Syslinux activate 6.04-pre1: 200, Syslinux 6.04-pre1 is active
  • Change password: 200
  • Logout: 200

README screenshots

Overview in Cozy and Overview in Console are the only inline screenshots. They were recaptured after the DHCP card fix, along with the DHCP page shots.

Overview in Cozy
Overview in Console

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 30 commits October 19, 2026 20:12
BoltLeaseRepository wrote the lease and its _by_mac entry in separate
bbolt transactions, so a failure between them could leave the index
pointing at a row that was never saved. Save and Delete now update both
keys inside one transaction, and a failed transaction rolls back.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Heartbeat, state changes, and caller saves now read and write under the
same allocation lock as DHCP renewal. A stale UpdateLease keeps a newer
expiry, last-seen, and provisioning state from the stored row. Reserved
leases keep their address after the expiry timestamp. A maintainer runs
cleanup and offline marking until its context is cancelled.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Hosts being provisioned authenticate with a per-lease token, so they can
report state (including failed) and send heartbeats without a browser
session. Admin routes stay behind the session cookie. Overview can poll
lease and pool counts, each user can store cozy or console, and /status
redirects to the overview page.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The frontend sets data-theme on html from the Mode value already passed into every page render.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Cloud-init, Kickstart, preseed, and AutoYaST call the per-lease state and heartbeat routes with the provision token. Callbacks time out and ignore errors so an unreachable server cannot stop an install. Installer files are rendered with text/template, which also lets AutoYaST scripts render.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Error, login, modal, and picker renders now carry .Mode, and data-theme comes from that value. A missing session or a failed preference lookup falls back to cozy.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Server Mode sets data-theme on the app and login shells, falling back to cozy when it is empty. The ignite DaisyUI theme is removed. Overview absorbs the status summary, and the nav toggle posts the preference without blocking when the save fails.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Add make screenshots, which seeds a temporary database and captures Cozy pages plus a Console overview with headless Chrome. Drop the Status image and document the command in the README.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
make screenshots now writes a Cozy and Console pair for every page. The README shows both under each section.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Build the lease history dialog with text nodes, drop the other named innerHTML sinks, hide Syslinux Activate, and post the mode toggle as a form that JS enhances with fetch. Add the accessibility hooks, delete the unused status page template, and stop hardcoding Mode to cozy.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
A DHCP renew counts as activity and restores the last non-offline stage.
Offline marking uses the lease duration when a host is mid-install or has
never heartbeated, and a heartbeat restores that same stage. Scans take a
per-MAC lock and re-check inside the write so Stop can cancel them.
UpdateLease no longer recreates a deleted row, legacy MAC spellings are
repaired inside the index transaction, and DeleteServer takes the lease lock.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
IP fields must be IPv4 and hostnames must be DNS labels. Shell and XML
interpolations are escaped, the canonical MAC is written back, and a missing
provision token fails the render. GET /configs/{type}/{name} is served only
to the lease IP or a presented token. Preseed early_command uses wget.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Host and admin state updates use one JSON envelope, reject markup in source,
and require a canonical MAC on manual leases. Unauthenticated 404 and 405
pages no longer render the admin shell. data-theme stays ignite while Mode
is still applied on every render, including login. Pool free space uses the
same reserved-or-unexpired count as the dashboard.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
JSON, Accept JSON, and HTMX saves still return 204. A plain form post
returns 303 to the Referer when that URL is a same-origin relative path,
and to / otherwise. Invalid mode stays 400. README and the status handler
describe /status as a redirect, not a page.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Keep cozy and console on every shell, use dhcp.PoolOccupancy for pool free, and remove the remaining HTML insertion sinks. Syslinux Activate stays hidden while that route returns 501.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview now shows the live dashboard summary, and the DHCP free counts follow pool occupancy.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
POST /api/syslinux/activate/{version} installs the boot files already on
disk and flips the active flag. A version that was never downloaded
returns 409 so the UI can offer download again. Other downloads stay
downloaded.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Status stayed "unknown" because nothing called SetTFTPRunning. Start now
marks TFTP running, and both a failed bind and shutdown mark it stopped.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The handler rendered a placeholder string. Browsers and htmx now get an
HTML fragment, and JSON clients get the same server views including
pool used and free counts.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
NewOSImageRepository now returns the bucket error instead of handing back
a repository that fails on the first read. NewContainer stops startup
and closes the database when that happens.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview is the status surface. GET /status stays only as a compatibility
redirect to / because the shell still links there. status.templ is left
for the frontend change to delete.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
BMC TLS verification is on unless BMC_TLS_INSECURE is set. A host that is
off is powered On; ForceRestart is used only when it is already On. The
client is an interface with a timeout, and more than one system without
an id is an error instead of systems[0].

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
POST, PUT, and DELETE from a logged-in session need the session token in
X-CSRF-Token or the csrf_token form field. Login and the per-lease host
callbacks stay exempt. Page data now includes CSRFToken for the base template.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The anonymous 404 now loads the same stylesheets as the login shell. The provision preview no longer keeps the unused HTML highlighters.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
ActivateVersion now removes the TFTP boot files and installs the extracted
files for the chosen version. Download uses that same function instead of
only flipping the active flag.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Download status and UI preference stores ignored GetOrCreateBucket errors
and kept going. Both constructors now return the error and NewContainer
stops startup.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview polls GET /status/content, so that route stays. GET /status is
no longer registered, and the release image health check no longer calls it.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Session POSTs, PUTs, and DELETEs, including logout and change-password,
need a same-host Origin as well as the CSRF token. A missing Origin is
not treated as same-site. The UI mode cookie is HttpOnly because page
theme is rendered from .Mode, not read from document.cookie.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The value is appended raw to the PXE line. Newlines and other control
characters are rejected before the boot menu is saved.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
README image and binary URLs and the release Dockerfile still named
v2.0.0. No tag is created.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
cursoragent and others added 28 commits October 19, 2026 22:57
A bookmark for /status returns 302 to /. /status/content stays the
fragment Overview polls.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The page label is TFTP_DIR as given. File handlers still use the
absolute directory, and a failed create shows the temporary path
that is actually served.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview and DHCP show in-flight and failed totals beside the
occupancy counts. A lease can be in both, because those totals do
not follow the active, reserved, and expired partition.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The status fragment already stores healthy, partial, or down. An
empty page-health callback was replacing that word, so the badge
read System Down while a DHCP listener was only stopped.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The lease and pool strip uses the same two-column grid as the service cards. The badge and subtitle share one issue list, so configured DHCP is named in the sentence. Absolute timestamps render in the browser's local zone, and screenshot captures reset to Cozy before each page.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview, the DHCP page, and the status bar share one running/stopped word. Lease menus show the OS name, and every server has a full lease table next to a detail panel.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview, the DHCP page, and the status bar read one helper and keep running, configured, and stopped as given. A menu path, including /tmp, renders as an em dash until the backend supplies a friendly name.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
GET /dhcp/servers, /status/content, and /dashboard/summary share the
raw running, stopped, or configured word. Overview, the DHCP page, and
the status bar render it through one helper. Leases show menu_name, and
a missing name stays an em dash.

TFTP folders sort first, the name opens the directory, and Delete stays
in a fixed slot. Counts and modified times use the shared helpers, and
the page shows the TFTP root the server reports.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The restyle left Preview as plain text, and the old highlighters were
removed because they built HTML strings and nothing called them. A
shared tokenizer now paints spans with textContent for the template
languages, including a file that contains a script tag.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
DHCP status is the listener word running, stopped, or configured on
the JSON and HTML views. Configured servers stay labeled and do not
make Overview partial. Leases show menu_name, with an em dash when it
is empty, and menu.filename is left blank.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview stays healthy while DHCP is configured, and the lease table
shows menu names.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
gofmt wants a blank line before StatusHandlers.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Send the CSRF token with every form, show host health on every page, and lay the lease strip out as one row of equal cells. Rebuild Provision and OS Images to the mock layout, and keep menus and lease rows from being clipped.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Health, timestamps, and the TFTP crumb each go through one helper. Pages use Status, MenuName, and TFTPStatus from the merged code, and leave the newer layout fields unread until they land.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Overview and DHCP each use one six-cell strip, with in-flight and failed counts derived from lease states until the summary API exposes them. Configured servers use the idle cyan pill, and health copy is sentence case on the pill and the status bar.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Bring in overall status on every page, RFC3339 timestamps, TFTP display root, in-flight and failed counts, the /status redirect, and COOKIE_SECURE.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Use OverallStatus, RFC3339 attributes, and CountProvision, and drop the host-health snapshot and the client-side in-flight derivation.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
VOLUME /app/data holds ignite.db. SYSLINUX_CACHE_DIR defaults to a
syslinux directory under DB_PATH and is created at startup. Downloads
that lived in /tmp/syslinux-downloads are not migrated.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
HTTP_PORT stays the web listen port. TFTP_PORT defaults to 69.
DHCP_ENABLED=false skips the DHCP listener, reports every server as
configured so health stays healthy, and returns 409 if a start is requested.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Bring in the data volume, SYSLINUX_CACHE_DIR, TFTP_PORT, and DHCP_ENABLED.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Crop the illustrated mark for the nav, login, and icons, and keep the 1.3 MB source out of public/. Surface the DHCP-disabled 409 as written, mark a missing Syslinux cache for re-download, keep the TFTP root path in its tile, hide the Cozy lease table, cap the provision editor, and label every timestamp with its zone.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Link the other page shots, including login and the DHCP host detail, and capture those two from the same 1280-wide screenshot run.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Redfish accepts a self-signed BMC certificate by default.
BMC_TLS_VERIFY=true turns checks on. BMC_TLS_INSECURE is gone.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
The capture script now refuses a busy port and checks that the process it started is serving this tree's CSS and flame before Chrome runs.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
BMC TLS verification is off unless BMC_TLS_VERIFY=true. BMC_TLS_INSECURE is removed.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
Keep the badge and Start in a fixed slot, and put the disabled hint on its own muted line under the pool meta.

Co-authored-by: Chad Shaw <chadleeshaw@users.noreply.github.com>
@chadleeshaw
chadleeshaw marked this pull request as ready for review October 23, 2026 00:10
@chadleeshaw
chadleeshaw merged commit 8b58c39 into main Oct 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants