Quick Start
Copy the whole folder to your web server (or any static host). There is no build step.
The page works as-is. Open
index.htmland check the script tags before</body>:
Code snippet omitted: it ships with the download.
Lenis is optional: delete its tag and scrolling goes native. Without ScrollTrigger the scroll reveals are skipped and everything simply shows; the wire itself needs only GSAP core.
Make it yours:
- Rename the product in the nav wordmark, hero, footer,
<title>and meta description. - Swap the
WIREobject at the top ofassets/script.jsfor your own monitors and events (see The alert wire below), and rewrite the seven static rows in the#topfeed list to match. - Restate the uptime board cells (
#board) and leaderboard rows (#services) with your services and numbers. - Point the CTA buttons (nav, hero, both access cards) at your signup flow; they currently anchor within the page.
- Update the three hero counters if you change the wire's opening numbers: the script seeds itself from whatever the markup says.
- Rename the product in the nav wordmark, hero, footer,
For production, swap
assets/script.jsforassets/script.min.js.
Sections
Every section is independent: the script guards each selector, so you can delete any of these wholesale and the rest keeps working.
| Section | id | What to edit |
|---|---|---|
| Nav | - | Wordmark, anchor links, CTA target |
| Hero console | #top |
Headline, sub, CTAs, the three counters, the seven static alert rows |
| Incidents now | #incidents |
The .tick-item entries (state, service, description, figure; add is-live for an active incident) |
| The uptime board | #board |
Board cells: service, uptime %, incident count, heat-1..4 tier, aria-label |
| Noisiest services | #services |
Leaderboard rows: service, meta, alert count, and the --w bar width |
| How it works | #method |
The three steps |
| Access | #access |
Tier names, prices, feature lists, CTA targets |
| FAQ | #faq |
Native <details> items |
| Footer | - | Contact address, small print |
The alert wire
The signature. Everything it needs lives in two places in assets/script.js:
- The
WIREobject at the top: one entry per check-type channel (uptime,latency,ssl,cron), each with a label, monitor names, and event templates carrying a severity plus either a millisecond range or a literal figure. The generator composes rows from these pools, so swapping this object reskins the entire stream. The keys must match thedata-channelattributes on the channel buttons and thedata-kindattributes on the static rows. The severity mix is weighted inmakeAlert()(15% critical, 27% warning, the rest routine) so the wire reads plausibly calm; an all-critical wire reads broken. - The dials inside the feed block: the stream interval is drawn from
gsap.utils.random(2.4, 4.8)seconds inschedule(), and the DOM cap isstate.cap(8 on desktop, 6 on coarse pointers). Raise the cap and the panel scrolls internally; the list hasdata-lenis-preventso that scroll stays native.
How an arrival works: the row is built with createElement, inserted at the top, and its height tweens open, which shunts the rows below down. The row face drops in with back.out overshoot, one amber sweep crosses the panel, the counters advance through snap-rounded tweens, and rows past the cap collapse and are removed.
The counters seed themselves from the markup: whatever the [data-count-checks], [data-count-incidents] and [data-count-mta] elements contain on load is where the live values start, so the no-JS page and the live page always agree. Checks advance on every event, incidents on warnings and criticals, and the median time-to-alert recomputes when a critical fires.
Interactions: hovering or keyboard-focusing a row expands its incident card (tap toggles on touch). The open card overlays the rows beneath it rather than growing the list, so the console keeps a stable height; a row near the bottom of the window opens its card upward instead, which keeps the card inside the panel even for the last row. The channels retune the console (rows off the channel collapse out and a burst of matching arrivals refills the wire), and the pause control stops the stream and greys the live dot.
The uptime board
Each cell is a <button> whose class sets both its size and its heat:
Code snippet omitted: it ships with the download.
heat-1toheat-4set the amber wash intensity, encoding 30-day incident density; all four tiers are measured for ink text (see the stylesheet header). Match the tier to the incident count.cell-xl(3 columns by 2 rows) andcell-l(3 by 1) size the anchors; unclassed cells are 2 by 1. Nine 2x1 cells fill exactly three rows of the 6-column grid, so keep the unclassed count a multiple of three when adding services.- The incident count shows at rest; the uptime figure reveals on hover and focus, and is always visible on touch. Keep the
aria-labelcarrying the full sentence: it is what a screen reader gets.
Palette
The whole scheme is six colours in the :root block of assets/style.css, each with an RGB triple beside it:
Code snippet omitted: it ships with the download.
Change a hex, change its triple, and the site reskins: every translucent value (rules, washes, the board tiers, the sweep) derives from the triples, so nothing is left half-repainted.
Three constraints, all measured (the full table is in the stylesheet header):
- The critical terracotta never carries small text: it sits at 4.37:1 on the ground. Critical chips are ink on an alert wash (9.60:1), warning chips ink on an amber wash (8.63:1); the terracotta itself only draws dots, borders and washes.
- Text on uptime-board cells is always
--ink(6.94:1 on the hottest tier); amber and--faintboth fail there. - Amber fills (buttons, the active channel, the pro badge) carry
--groundink, never light type.
If you lighten --ground or --panel, re-measure --faint first: it is the small-print floor at 5.32:1 on the panel and the first token to fail.
Type
- Big Shoulders does the display work: wordmark, headlines, section labels, channel chips. It is a condensed signage face, so generous
letter-spacingis part of the look; if you swap it, revisit every tracking value. - Mulish does all reading text.
- Sono (in its monospaced-feeling default) does the data: timestamps, counters, hostnames, latency figures, region codes. Keeping data in one face is what makes the console read as an instrument; resist giving it to headings.
All three load from Google Fonts in the <head> of index.html and thumbnail.html.
Accessibility
- Respects
prefers-reduced-motionvia both the CSS media query and agsap.matchMediabranch: the stream starts paused (the pause control says so honestly), counters hold their final values, incident detail opens instantly, reveals never hide, and Lenis is never created. Resuming the wire under reduced motion streams rows that simply appear, without tweens. - Fully readable with JavaScript disabled: the markup ships seven real alert rows with their incident cards open, and the script only upgrades the page to the live console.
- Every alert row is a real
<button>witharia-expanded; keyboard focus expands a row exactly as hover does, and tap toggles on touch devices. Severity chips carry spokenaria-labels ("severity: critical"), so severity never relies on colour alone. - Uptime-board cells are buttons with full-sentence
aria-labels; their figures reveal on focus as well as hover and are always visible on touch. - All interactive elements have visible
:focus-visiblerings. - The alert list scrolls natively (
data-lenis-prevent) with its scrollbar hidden, so a mouse wheel works inside it even with Lenis running. The incidents ticker drifts on its own and pauses on hover and keyboard focus; without JavaScript or with reduced motion it stays a plain scrollable row with a visible scrollbar.
Browser Support
Modern browsers (ES5-compatible script, CSS grid, custom properties). Not compatible with IE11.
Dependencies
- GSAP 3.12+
- ScrollTrigger plugin (optional; without it the scroll reveals are skipped and content simply shows)
- Lenis (optional; smooth scrolling, and the site works without it)
Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.