Dashboard

Featuresby Aaron Reimannupdated Oct 4, 2026#dashboard#fleet#monitoring

The home page (/) is the fleet view — of servers. One card per server, sorted with anything-needing-attention on top. If the dashboard is green and the Issues page is empty, you can close the tab.

This page is server-centric, so Pressable sites don’t appear here at all — Pressable has no server concept for a card to represent. For a fleet view that covers both hosting providers, see Features → Sites (fleet view).

Dual-Layout Architecture (Command Center vs. Modern Studio)

Clockwork Control provides two complementary layout philosophies selectable on the fly via the layout switcher in the top navigation bar:

  1. Command Center (command-center): A dense, high-information density layout tailored for mission control operations. Features a persistent left-hand navigation and operations rail (Workspaces / Operations / Configuration, plus a Modules group listing every enabled module’s nav item from ModuleRegistry::navItems() — the same list as the mobile Menu sheet. Operations, Configuration and Modules are collapsible and closed by default; a group opens automatically when the current page is inside it, each group remembers the operator’s open/closed choice in localStorage (cw_rail_group_*), and when the rail is shrunk to icons every icon is shown regardless), compact telemetry readouts, user profile & settings popover in the rail footer, quick SSH diagnostic actions, and dense status indicators.
  2. Modern Studio (modern): A spacious, card-forward, human-centric interface with floating filter chips, integrated fleet-wide search, expandable quick drawers, and modern whitespace. Its top tab strip groups Capacity, Fleet Updates, Maintenance and AiRemedy under one Operations ▾ dropdown — the same Operations group the rail and the mobile Menu sheet list — with the AiRemedy review-count badge shown on the tab. The menu is teleported to <body> (the tab strip is overflow-x-auto and would clip it) and closes on Escape or an outside click.

Layout preferences are saved locally in the browser (localStorage.getItem('cw_layout_style')) and initialized before document render via data-layout-style on <html> to ensure zero flash of unstyled content (FOUC). Both layouts operate on top of a unified Alpine.js appChrome store and share underlying live telemetric models.

On viewports below lg (1024px) there is one chrome: top bar + hamburger Menu sheet (overlay, current-route highlight, badge counts, font stepper). The Command Center / Modern Studio switcher is hidden and the toggle is a no-op — the rail only exists at lg+. Below md, the studio tab strip is also hidden so the sheet is the only primary nav.

Operators can press ⌘K (macOS) or Ctrl+K (Windows/Linux), or click the “Search fleet, commands, servers…” bar / Jump button in the top navigation header to open the unified Command Palette.

The palette serves as both an instant keyboard navigator and a dynamic global search engine across your entire fleet:

  • Unified Fleet & Site Search:
    • Typing 2 or more characters triggers an asynchronous, debounced (120ms) backend query against GET /search/global?q=....
    • Servers: Matches server display name, internal name, hostname, and IP address (e.g., searching web-01 or 203.0 immediately surfaces the matching server with live health status badges and provider metadata).
    • Sites: Matches domain names (e.g., acme or example), displaying the parent server and WordPress application badges.
  • Two-Letter Jump Codes: Typing two letters (case-insensitive, spaces optional) navigates immediately without touching the mouse:
    • GS or G S: Servers Fleet (/)
    • GT or G T: Sites Directory (/sites)
    • GI or G I: Issues Console (/issues)
    • GM or G M: Uptime Monitoring (/monitoring)
    • GU or G U: Updates Manager (/updates)
    • GX or G X: Security Scans (/security/scans)
    • GA or G A: AiRemedy Triage & Forensics (/ai-remedy)
    • GG or G G: Gatekeeper Login Protection (/settings/gatekeeper)
    • GF or G F: Feedback Backlog & Notes (/feedback)
    • GC or G C: Clients Directory (/clients)
    • GJ or G J: Scheduled Jobs & Heartbeat (/settings/scheduled-jobs)
    • GQ or G Q: Security Review Queue (/review-queue)
    • GD or G D: Documentation & Runbooks (/docs)
  • Rich Synonym & Keyword Matching: Destinations match common aliases, operations, and modules in real-time. For example:
    • Searching airemedy, shadow mode, spike, or auto-heal matches AiRemedy.
    • Searching openrouter, claude, or api key surfaces AiRemedy Settings.
    • Searching lockouts, brute force, or ip bans surfaces Gatekeeper.
    • Searching cron, scheduler, or heartbeat surfaces Scheduled Jobs.
    • Searching crm or accounts surfaces Clients Directory.
  • Keyboard Navigation & Feedback:
    • Pressing ↑ / ↓ cycles selection highlight with active ring styling.
    • Pressing Enter navigates to the highlighted destination, server, or site.
    • An inline spin-loader indicates active background search requests.
    • Pressing Esc or clicking the backdrop dismisses the palette and resets the query.

What you see

Each server gets a card with:

  • A health pill — green (fine), yellow (needs attention), red (something’s wrong now), gray (ignored or unreachable).
  • A 3-tier status-tinted card border and metric badge hierarchy:
    • Yellow border & badge (≥ 70%): Caution / Watch threshold.
    • Orange border & badge (≥ 80%): Elevated resource pressure.
    • Red border & badge (≥ 90%): Critical threshold / alert status.
    • Healthy servers (< 70%) maintain neutral borders so operator attention is immediately drawn to pressured nodes.
  • Three sparklines and numeric telemetry readouts: CPU %, memory %, disk %, and load averages, plus a “Stale” indicator if recent metrics have timed out.
  • A site count and top sites by PHP-FPM / CPU utilization.
  • Cloud and control panel provider badges (DigitalOcean, Hetzner, Vultr, Azure, GridPane, SpinupWP).
  • Inline status pills for SSL state, Cloudflare state, and recent ban activity.
  • Gray tag pills for whatever tags the server carries (color comes from the tag itself, rendered low-contrast so it doesn’t compete with the health pill). A server tagged staging additionally gets a “Not monitored” pill — see below.
  • Per-server action buttons: View detail, Test SSH, Provision fail2ban (when not yet provisioned), Toggle ignore.

Sort order is “worst first” — red cards float to the top, then yellow, then green. Within each color tier, more-recent transitions sort higher.

Tag filter

A chip strip above the grid lists every tag that has at least one server, each showing the server count and rendered in the tag’s own color (Tag::color). Click a chip to filter the grid to ?tag=<slug> — DashboardController::index() resolves the slug via Tag::where('slug', ...)->first() and constrains the server query with whereHas('tags', ...). An unknown or empty slug is silently ignored (falls back to “all servers”), so a stale bookmark never 404s. Click the “All” chip (or drop the query string) to clear the filter. Tags themselves are managed on the Settings → Tags page and assigned per-server from the server detail page — see Features → Server updates + reboots → Tags for how tagging (in particular the staging tag) is used.

A server tagged staging shows a gray italic “Not monitored” pill next to its tag chip, with a tooltip explaining why: staging servers are excluded from uptime probes, security scans, plugin checks, fail2ban, and the update/reboot pipeline via Server::scopeMonitored(), but they’re deliberately still shown on the dashboard (and countable via is_ignored) so operators know they exist.

Dynamic per-site navigation

On per-site views (/sites/{id}), navigation tabs respect both site tier and module enablement:

  • Performance: visible only for care-plan enabled sites.
  • Updates: visible only when the site’s host supports remote WP updates.
  • Forms: visible only when the site is on a care plan AND the contact-forms module is enabled (ModuleStateResolver::isEnabled('contact-forms')). When disabled via /settings/modules, the Forms tab is omitted cleanly.

How a server becomes red or yellow

CPU drives most of it. The thresholds are tunable in .env (CLOCKWORK_CPU_RED_THRESHOLD / _YELLOW_THRESHOLD, defaults 90 / 70). Memory and disk add yellow flags above their own thresholds — when the cloud provider exposes those series. The exact rules live in App\Services\Monitoring\CpuStatusClassifier — provider-agnostic, applied the same way regardless of which cloud a server is on.

Polling runs every 5 minutes via whichever cloud-provider API owns each server. DigitalOcean droplets get the full suite (CPU, memory, disk, load); Azure VMs get CPU and memory (disk requires the Azure Monitor Agent, not yet wired up); Hetzner Cloud servers get CPU only and the secondary panels show “no data.” See Integrations → DigitalOcean, Integrations → Azure, and Integrations → Hetzner Cloud for what each reads, and Architecture → System overview for how it gets surfaced.

Sections

The dashboard is divided:

  1. Active servers — sorted by health, worst on top.
  2. Ignored servers — is_ignored=true, kept visible (muted) so you remember they exist.

A server flips to ignored either manually (the Toggle ignore button) or auto-flagged on first import via CLOCKWORK_AUTO_IGNORE_PATTERNS (empty by default — comma-separated substrings, case-insensitive; set your own per-operator). Auto-flag only sets the bit on first creation — manual changes survive subsequent imports.

Search & Discovery

Clockwork Control provides two integrated search flows:

  1. Global Fleet Search (⌘K or Ctrl+K):
    • The primary command bar in the top navigation header (GET /search/global?q=...).
    • Searches across servers (by name, hostname, IP address), WordPress sites (by domain name), feature modules (AiRemedy, Gatekeeper, Scheduled Jobs), system settings, and jump codes in real time.
  2. Dedicated Sites Quick-Search (/):
    • Pressing / from anywhere in the application immediately focuses the site search field at the top right (GET /search/sites?q=...), allowing fast one-keystroke site navigation.

What’s NOT on the dashboard

  • Detailed metric charts — go to the per-server page (/servers/{id}/stats).
  • The review queue — that’s /bans/queue.
  • Site-level health — sites surface on the per-server page or via Search.
  • Anything historical beyond the sparklines — see /maintenance-history for the long view.

Issues page additions

Several feature areas surface on the /issues page rather than the main dashboard:

  • WordPress-Style Screen Options Drawer: A pull-down drawer accessible via the top-right header actions bar allows operators to customize which category sections to display on screen. Grouped into 3 columns (Critical & Security, Infrastructure & Health, Routine Maintenance) with quick presets (Show All, Critical Only, Hide Routine, Reset), persisted in browser localStorage.
  • Compact “Jump to Issue” Dropdown: Replaces multiple rows of header status pills with a single jump menu showing all active issue categories and counts, featuring smooth scrolling and an animated brand ring highlight.
  • 3-Tier Priority Hierarchy & Fleet Defaults: Alert categories support three granular urgency tiers: Emergency (Critical alerts), Pressing (Urgent alerts), and Not Pressing (Routine maintenance), plus the ability to turn a category Off fleet-wide.
  • Unified Control Strip: Tier filter tabs (All Issues, Critical & Security, Infrastructure, Routine) and Urgency filter pills (All Active, Emergency, Pressing, Routine, Muted) are organized in a balanced, single toolbar row alongside global section collapse/expand controls.
  • Patches Available rows now include a Reboot now button. Clicking it triggers the same confirm-then-POST reboot flow as the server detail page without needing to scroll down to the Reboot Required section. Useful when reboot_required hasn’t flipped on the row yet but you know an apt upgrade just ran.
  • Orphaned sites (sites with no SpinupWP record and not archived) now have a Remove button with an “Are you sure” confirmation — archives the site row rather than hard-deleting it.
  • SSH credentials — servers missing SSH credentials surface on the Issues page. Each row has an inline action: Test SSH (AJAX, fires POST /servers/{id}/test, shows pass/fail inline without a page reload) if a password is already stored, or Add password (links to the credentials edit page) if none is on record yet.
  • Ignored issues workflow — operators can suppress a specific alert (e.g. an intentional noindex flagged by SEO Indexability) by clicking Ignore and optionally recording a reason in a modal. The card moves to an Ignored tab with a one-click Resume monitoring action, and the suppressed site is excluded from IssueCounter’s total so it stops inflating the header nav badge. See Architecture → Data model for the ignored_issues table this is backed by.

Capacity Dashboard & Per-site CPU collection toggle

The /capacity dashboard provides multi-host capacity management across both shared servers and Pressable plans:

  • Navigation & Fleet Filtering: Quick-jump anchor pills, fleet filter tabs (All, Over Quota, Approaching, Healthy), and a floating scroll pill for fast navigation through large server lists.
  • Leaderboard CPU Collection: The leaderboard section has a Pause collection / Resume collection button per site. When paused, clockwork:pull-site-metrics skips that site’s Companion sampler polling. Historical rows are kept, so the 7-day leaderboard stays visible while paused. A yellow “Collection paused” banner makes the state obvious on the site’s capacity row.

Use this once you’ve identified the hot-CPU offenders and no longer need the overhead of per-request DB writes that Companion’s sampler produces.

When the dashboard lies

A few cases where the dashboard can mislead:

  • Scheduler not running → cards stay green even as data goes stale. The layout banner (“Scheduler has not ticked…”) and /monitoring last-tick timestamp are the first-class signal; last_polled_at on the card is the second-order one. See Runbooks → Scheduler stuck.
  • Ignored server is actually broken — by design, ignored servers don’t count in headline status. Don’t ignore a box you actually need to monitor.
  • CF cache masks origin death — a CF-cached homepage can serve 200 even when the origin has imploded. The uptime probe sees up, but the real site is down. Pair the dashboard with /monitoring.
  • Provider-deleted server still showing green — if a server is removed at the provider (DO/Hetzner) without being decommissioned in Clockwork Control, PollServers marks it status=unknown on the next cycle. Cards stuck green with a stale last_polled_at are a sign the scheduler is down; cards showing “unknown” are a sign the server is gone at the provider.
Clockwork Web Dev
Brought to you by Clockwork Web Dev

A real WordPress development agency building battle-tested operational tooling to run client fleets with zero bloat and total control.

Visit Clockwork Web Dev→