Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
icons.tsx becomes thin lucide-react wrappers (same names, same h-4 w-4 default). Real WordPress/Docker/PHP logos via a curated simple-icons subset baked offline by scripts/gen-brand-icons.mjs (Faro plan-14 pattern) — zero icon network calls. KindBadge shows the brand mark and gains a PHP variant (php sites previously mislabeled "WP"). CopyButton gets copy/check glyphs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SiteTile hashes a stable hue from the slug — saturated + glow when up, dimmed same-hue when stopped, pulse while creating. Grid cards lead with the tile, hero violet Open, iconed actions (Clone/Delete icon-only so the row never wraps), hover lift behind motion-reduce. List rows get small tiles; sidebar gets a Layers icon + live running-count pill; the empty state becomes a tile illustration + invitation. stackLabel now renders the php kind as "PHP x.y" instead of an empty "WP · PHP". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Large SiteTile beside the h1, icons on every header action, and a shared SectionTitle (aria-hidden leading icon, so text-matching tests and the screenshot script are unaffected) across the detail sections and the Snapshots / Sync / Tools panels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Untracked captures (import-site, site-tools, snapshots) and the README refresh remain uncommitted — they belong to the in-progress docs work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Capture script gains toast dismissal before every shot, element-crop captures (shotElement), and three new pages: import-site, site-tools, snapshots. All PNGs regenerated against the plan-27 UI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The zinc ramp resolves to CSS variables (dark keeps the exact navy palette; light inverts the values, not the semantics) — the token layer the ROADMAP said a light theme needed. Titles move text-white -> text-zinc-50 so they flip; solid accent buttons keep literal white. Settings -> General gains an Appearance toggle; main.tsx stamps data-theme pre-render. Blueprint-grid utility (ServerKit squares) and theme-aware scrollbars + dimmed-tile lightness included. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SiteTile gains the Faro corner stamp — the real WordPress/Docker/PHP mark on a chip riding the tile. Kind pills leave the cards (the stamp carries it; list rows show the bare brand glyph). Card and row actions go icon-only with tooltips + aria-labels; "Resume setup" keeps its label. New rail icons: House, ChevronsLeft/Right. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Home is the new landing page: status headline, glowing tile wall, needs-attention list, environment card, quick actions — all from existing stores. The sidebar becomes a collapsible rail (persisted via railCollapsed) listing every site with tile + status dot; the active site expands sub-links into the detail tabs. SiteDetail splits into Overview | Tools | Snapshots | Logs with the tab in the nav store so the rail deep-links. Blueprint-grid background on the content pane; mod+0 "Go to Home" palette command. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captures now run in the light theme and start with home.png; the snapshots capture clicks its new tab. Dark spot-checked separately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expand the screenshot grid from 4 to 6 panels, adding Tools, Snapshots, Import, and ServerKit screenshots. Updates captions to reflect multi-stack support (WordPress, PHP, Docker). Applied consistently across EN, ES, PT, and ZH-CN READMEs.
There was a problem hiding this comment.
Pull request overview
This PR delivers the “plans 27/28” frontend redesign for LocalKit: a more visual, glanceable UI with deterministic site identity tiles, a new Home landing screen, a live/collapsible sidebar rail, and a theme-token layer enabling an instant light theme across the app.
Changes:
- Introduces a CSS-variable token layer for the zinc ramp and wires up a persisted Light/Dark theme toggle (applied pre-render to prevent flashing).
- Adds new navigational structure: Home as the default landing page, tabbed Site Detail deep-linking, and a live collapsible site rail in the sidebar.
- Replaces/extends UI presentation with monogram SiteTiles, lucide-based icon wrappers, offline brand glyphs (Iconify), refreshed dashboard actions, and updated docs/screenshot tooling.
Reviewed changes
Copilot reviewed 43 out of 56 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tailwind.config.js | Remaps zinc-* colors to CSS-variable tokens so existing Tailwind classes become theme-aware. |
| src/stores/settings.ts | Adds persisted theme + rail-collapse settings helpers and applyTheme()/useTheme() APIs. |
| src/stores/nav.ts | Adds home page and optional tab deep-linking for site detail. |
| src/pages/Terminal.tsx | Adjusts active tab text color to use theme-aware zinc token. |
| src/pages/SiteDetail.tsx | Converts detail view to nav-driven tabs (overview/tools/snapshots/logs) and updates header/actions styling with icons and SiteTile. |
| src/pages/Settings.tsx | Adds an Appearance section with Dark/Light segmented toggle; updates headings to zinc tokens. |
| src/pages/Home.tsx | New Home landing page: headline, site tile wall, attention list, environment card, and quick actions. |
| src/pages/Dashboard.tsx | Updates dashboard card/list rendering to use SiteTile + icon-only actions and refreshed empty state. |
| src/main.tsx | Applies theme to <html> before first render to avoid theme flash. |
| src/lib/commands.tsx | Adds a “Go to Home” command bound to mod+0. |
| src/lib/brandIcons.tsx | Adds offline brand icon rendering (Iconify offline) + kind-to-icon mapping helpers. |
| src/lib/brandIconData.ts | Adds committed curated icon data payload for offline brand marks (generated). |
| src/index.css | Adds theme token layer + light theme overrides + blueprint-grid utility + tokenized scrollbar colors. |
| src/components/SnapshotsPanel.tsx | Switches panel heading to shared SectionTitle with an icon. |
| src/components/SiteTile.tsx | New deterministic monogram tile component (slug-hashed hue, initials, status styling, optional brand stamp). |
| src/components/Sidebar.tsx | Replaces sidebar with collapsible live rail: Home/Sites/Terminal + per-site tile list with status dots and tab deep-links. |
| src/components/ServerKitSettings.tsx | Updates connection label styling to theme-aware zinc tokens. |
| src/components/SectionTitle.tsx | New shared iconed h2 header component used across panels. |
| src/components/SearchReplacePanel.tsx | Switches section heading to SectionTitle and keeps “view snapshots” hook wiring. |
| src/components/SaveBlueprintDialog.tsx | Updates dialog heading text color to zinc token. |
| src/components/PushPanel.tsx | Switches panel heading to SectionTitle with a sync icon. |
| src/components/NewSiteDialog.tsx | Updates dialog heading text color to zinc token. |
| src/components/KindBadge.tsx | Reworks kind badge to use offline brand glyphs and adds PHP-specific styling/labeling. |
| src/components/KeyboardShortcutsDialog.tsx | Updates heading color to theme-aware zinc token. |
| src/components/ImportSiteDialog.tsx | Updates dialog heading color to theme-aware zinc token. |
| src/components/icons.tsx | Replaces hand-rolled SVGs with lucide-react wrappers while preserving prior export names/default sizing. |
| src/components/DeleteSiteDialog.tsx | Updates dialog heading color to theme-aware zinc token. |
| src/components/DebugPanel.tsx | Switches panel heading to SectionTitle with an icon. |
| src/components/DatabasePanel.tsx | Switches panel heading to SectionTitle with an icon. |
| src/components/CopyButton.tsx | Adds icon + copied state visuals (checkmark) and transitions. |
| src/components/ConfigEditorPanel.tsx | Switches panel heading to SectionTitle with an icon. |
| src/components/CloneSiteDialog.tsx | Updates dialog heading color to theme-aware zinc token. |
| src/App.tsx | Routes the new Home page and adds the blueprint-grid background to the non-terminal content pane. |
| scripts/gen-brand-icons.mjs | Adds generator for curated offline brand icon data file. |
| scripts/capture-screenshots.mjs | Updates screenshot automation: light theme, toast clearing, element crops, and new capture paths. |
| README.md | Refreshes screenshot grid/captions to match new UI and adds new shot slots (Tools/Snapshots/Import). |
| package.json | Adds icon dependencies and the gen:brand-icons script. |
| package-lock.json | Locks new dependencies introduced by icon tooling. |
| docs/screenshots/CAPTURE.md | Updates screenshot inventory and descriptions to match new capture script outputs. |
| docs/README.zh-CN.md | Updates localized screenshots section to reflect new screenshot set and captions. |
| docs/README.pt.md | Updates localized screenshots section to reflect new screenshot set and captions. |
| docs/README.es.md | Updates localized screenshots section to reflect new screenshot set and captions. |
| docs/plans/ROADMAP.md | Marks plans 27 and 28 shipped and adds summary rows. |
| docs/plans/28_control-room.md | Adds shipped plan doc describing the control-room redesign and verification steps. |
| docs/plans/27_visual-identity-pass.md | Adds shipped plan doc describing the visual identity pass and verification steps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+231
to
+239
| <button | ||
| onClick={() => onOpen()} | ||
| title={site.name} | ||
| className={`flex justify-center rounded-lg p-1.5 transition-colors ${ | ||
| active ? "bg-zinc-800" : "hover:bg-zinc-900" | ||
| }`} | ||
| > | ||
| <SiteTile name={site.name} slug={site.slug} status={site.live_status} size="sm" /> | ||
| </button> |
Comment on lines
+48
to
+58
| return ( | ||
| <Icon | ||
| icon={data} | ||
| width={size} | ||
| height={size} | ||
| className={className} | ||
| role={title ? "img" : undefined} | ||
| aria-label={title} | ||
| aria-hidden={title ? undefined : true} | ||
| /> | ||
| ); |
| <h2 className="text-sm font-semibold uppercase tracking-wide text-zinc-500"> | ||
| Environment | ||
| </h2> | ||
| <dl className="mt-3 space-y-2.5 text-sm"> |
| : "save a site as a blueprint to reuse its stack" | ||
| } | ||
| /> | ||
| </dl> |
The test was racy: it dropped ephemeral listeners and immediately probed the ports, but a concurrent test could grab those ports before the probe finished. Now retries up to 5 times with fresh ports, treating a transient false-positive as a fluke rather than a failure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LocalKit spent its whole life as a wall of text pills, and it was starting to look like a database admin panel that wandered into the wrong app. This pass (plans 27 and 28) gives every site a face, adds a proper landing screen you walk up to and glance at, moves navigation into a live rail that answers "is anything running?" without a click, and — because not everyone codes in the dark — ships a light theme.
Highlights
Technical changes
Theme / token layer (plan 28)
src/index.cssgains a CSS-variable token layer: thezincramp is defined as RGB triplets on:root, with a:root[data-theme="light"]override that inverts the values while keeping the semantic roles stable (950 = page, 900 = surface, 800/700 = borders, 600/500 = dim/muted text, 50 = strongest text).tailwind.config.jsremaps everyzinc-*color torgb(var(--c-zinc-*) / <alpha-value>), so all existingzinc-*classes become theme-aware with no call-site edits.src/stores/settings.tsaddsTheme,getTheme()(non-hook read),applyTheme()(stampsdata-themeon<html>), and theuseTheme()hook; plususeRailCollapsed()for the sidebar state. Both persist in the settings KV.src/main.tsxcallsapplyTheme(getTheme())before first render to avoid a flash.src/pages/Settings.tsxadds anAppearancesection (ThemeSection) with a Dark/Light segmented toggle; a couple of literaltext-whiteheadings switched totext-zinc-50..bg-blueprintutility (faint accent-tinted grid) applied to the main content pane inApp.tsx.--tile-dim-bg-l/--tile-dim-fg-ltokens drive the dimmed-tile lightness so stopped tiles read correctly in both themes;--scrollbar-thumb*and--grid-lineare tokenized too.Site tiles + brand marks (plans 27/28)
src/components/SiteTile.tsx:hueFromSlug()(FNV-1a hash of the slug, folded to a hue — survives renames),initials(), and the tile itself. Running/degraded sites render saturated with a same-hue glow; others dim via the theme tokens. Optionalkindprop stamps the brand mark on the corner.creatingsites pulse.src/lib/brandIcons.tsx: offline Iconify wrapper (@iconify/react/offline) that renders curated icon data only — no network name lookups ever reachapi.iconify.design.BrandIconreturnsnullfor unknown keys so callers can fall back;kindIcon()maps a site kind to a simple-icons name (WordPress is the default/fallback).src/lib/brandIconData.ts(auto-generated) +scripts/gen-brand-icons.mjs: extracts a curated subset (wordpress, docker, php, laravel, mariadb) from@iconify-json/simple-iconsvia@iconify/utils, trims default transform fields, and writes ~1 KB of committed icon data. Run withnpm run gen:brand-icons. simple-icons is CC0-1.0.src/components/KindBadge.tsxrewritten around aMETAmap; adds the PHP kind (indigo) and renders the real brand glyph beside the label.src/components/icons.tsxfully replaced: the hand-rolled SVGs are gone, replaced by thinwrap(LucideIcon)wrappers overlucide-react, preserving the old export names and theh-4 w-4default so no call site changed. Adds the new glyphs the redesign needs (Home, Layers, Camera, Play, Square, Wrench, Trash, Bookmark, chevrons, etc.).Home screen (plan 28)
src/pages/Home.tsx: status headline derived from running/total counts, tile wall (WallTile),Needs attentionsection (incomplete / degraded / error sites),Environmentcard (EnvRowfor Docker, local domains, ServerKit, blueprints), and aQuick actionsgrid. Reads existing stores only; refreshes ServerKit connections and blueprints on mount.src/stores/nav.tsadds the{ name: "home" }page and aSiteTabtype (overview | tools | snapshots | logs);sitepages carry an optionaltab. Home is now the default landing page (wassites).src/App.tsxroutes thehomepage and threadstabintoSiteDetail.src/lib/commands.tsxadds ago-homecommand bound tomod+0.Live rail (plan 28)
src/components/Sidebar.tsxlargely rewritten: Home/Sites/Terminal nav with icons; a "running" count pill on Sites; a scrollable live list of every site (RailSite) showing tile + name + status dot; the active site expands its detail tabs (subTabs(), capability-gated ondb_gui/search_replace/wp_tools/snapshots). Collapsible to a 60px tile-only strip viauseRailCollapsed(), with the collapse/expand and settings controls in the footer. When collapsed and Docker is down, an amber dot rides the gear button.Site detail (plan 28)
src/pages/SiteDetail.tsx: the tab is now sourced from the nav store (navTab) instead of local state, so the rail can deep-link into it;setTabnavigates. Tabs expanded to Overview / Tools / Snapshots / Logs — Snapshots and Logs are now their own tabs (Logs stays mounted via a hidden wrapper so auto-scroll/polling survive switches; log pane taller at28rem). Header gains a large monogram tile; section headings use the newSectionTitle; action buttons gained icons and a sharedheaderGhostBtnclass.src/components/SectionTitle.tsx: iconedh2whosetextContentis unchanged (icon is aria-hidden), so the screenshot script and text-matching tests still work.Dashboard (plans 27/28)
src/pages/Dashboard.tsx: cards and rows renderSiteTile; the two views share a singleSiteActionscomponent (icon-only buttons —iconBtn/openIconBtn/dangerIconBtn— so grid and list never drift). New illustrated empty state; hover lift +shadow-panelon cards;stackLabel()handles the PHP kind (PHP <version>with no WP); list rows show the inline brand glyph instead of a text pill.src/components/CopyButton.tsx: icon + emerald checkmark on copy.Docs / tooling
scripts/capture-screenshots.mjs: captures in the light theme (plants the localStorage key before load); adds element-crop shots (shotElement), toast clearing, direct-dispatch clicks by aria-label / table row (survive overlays), and new captures for Home, Tools tab, Snapshots panel, and the remote-import dialog.docs/screenshots/*: regenerated all shots in the light theme; addedhome.png,import-site.png,site-tools.png,snapshots.png.docs/screenshots/CAPTURE.mdupdated to match.README.mdand thedocs/README.{es,pt,zh-CN}.mdlocales: refreshed the screenshots section (new grid, new captions, Tools / Snapshots / Import rows).docs/plans/27_visual-identity-pass.mdanddocs/plans/28_control-room.md; both rows marked shipped indocs/plans/ROADMAP.md.package.json: addslucide-reactand@iconify/react(deps),@iconify-json/simple-iconsand@iconify/utils(devDeps, generator-only), and thegen:brand-iconsscript.