Load Abbod
Skip to the write-up

Projects Signalformcase 08 / 10

Signalformselling software with software

An observability platform that puts metrics, traces and logs on one surface — and a marketing site with not a single photograph in it.

Sector
Developer tools · SaaS
Art direction
Precision dark, Linear-adjacent
Photography
None — 0 inline SVGs
JavaScript
0 lines, 10 modules
Project type
Self-initiated concept
Date
January 2026
01 / 03The full Signalform page from hero to footer 02 / 03 03 / 03
The finished page in full — signalform · January 2026

01 · Overview

Selling software with software

Observability tools are bought by people who will judge your product by your marketing site's p95. So Signalform's site is not a page about a dashboard — it contains one. The hero panel is a hand-built SVG: browser chrome, a throughput chart, an error-rate sparkline, a p95 latency readout and a log tail that scrolls. No screenshot, no stock render, no product video.

That decision cascades. With zero photography the entire page weight is markup, and the visual language has to come from structure — a 14-pixel radius, one violet, a very dark neutral ramp, and a great deal of restraint about when anything glows.

02 · The idea

Answer in milliseconds, say so in milliseconds

The product promise is every signal, one surface, zero guesswork. The site had to demonstrate that rather than assert it, which meant the interface had to be reachable the way engineers actually reach for things: a command palette on ⌘K, tabs that switch without a page load, and a pricing toggle that answers a question instead of opening a sales form.

Keyboard first

A real command palette with a focus trap, arrow navigation, number shortcuts and scroll lock — not a search box in a modal.

Show the product

Fourteen inline SVGs carry the dashboard, the charts and every customer logo. Nothing is rasterised.

Dark that stays legible

A three-step neutral ramp with the dim text token pinned at 5.72:1 on the background — recorded in the stylesheet.

03 · Goals

The brief, as constraints

  1. Look like the product

    Same radius, same panel shadow, same type scale as the app it advertises, so the jump from site to trial is invisible.

  2. Ship no images

    Zero photography and zero raster assets, so the page is fast on a conference-wifi connection and sharp on any display.

  3. Be operable without a mouse

    Palette, tabs, accordion and pricing toggle all driven from the keyboard with correct ARIA state.

  4. Never trap anyone

    The overlay locks scroll and cycles focus while open, and returns focus to the trigger when it closes.

04 · Build order

Built in ten numbered modules

The script is organised as ten numbered blocks in one IIFE, each self-contained and each guarded so a missing element is a no-op rather than a thrown error. The page works with any subset of them present.

  1. Tokens and the neutral ramp

    Twenty-two custom properties: background, two surfaces, a sunken tint, three text weights, three violets and four status colours.

  2. The SVG dashboard

    Drawn by hand in the markup — chrome, axes, series, a live log tail — so it scales, themes and costs nothing to download.

  3. Layout at five breakpoints

    Only five media queries in 46 KB of CSS; the bento and pricing grids are auto-fit and need no help.

  4. Interaction modules

    Header state, mobile nav, offset anchors, reveals, bento glow, count-ups, deep-dive tabs, pricing toggle, FAQ accordion, CTA form.

  5. The command palette, last

    Built only once everything it needs to navigate to already existed — so its index is the real page, not a hard-coded list.

05 · Architecture

The shape of the thing

The site models the product's own pipeline, and says so out loud in the platform section. That diagram is inline SVG: every connector carries pathLength="100", so a single scroll-driven custom property draws all four of them through calc() windows. One write, one diagram.

signalform/
├── index.html 52.4 KB — 7 sections, 14 inline SVG, 0 images
├── styles.css 46.1 KB — 22 custom properties, 5 media queries
└── script.js 18.5 KB — 608 lines, 10 numbered modules

06 · What fought back

Problems, and what beat them

Challenge

Locking background scroll for the palette with overflow: hidden removes the scrollbar, which reflows the entire page sideways the instant the overlay opens.

Solution

Measure the scrollbar width before locking and pay it back as padding on the same element. The page does not move by a pixel.

Challenge

A hand-drawn SVG dashboard has to stay readable from 360 px to 2560 px, where a fixed viewBox makes 7-pixel labels either illegible or enormous.

Solution

The panel is composed of several small SVGs inside a CSS grid rather than one big one, so the chrome scales and the type does not — each chart keeps its own aspect and the labels stay in document type.

Challenge

Count-up statistics are a cliché that also breaks accessibility: the number animates on every scroll pass, and screen readers announce every intermediate value.

Solution

Each counter fires once, from an observer that unobserves itself, and under prefers-reduced-motion it prints the final value immediately rather than animating to it.

Challenge

Anchored navigation lands the target underneath the sticky header, so the heading you clicked is the one thing you cannot see.

Solution

A shared scrollToTarget() subtracts the measured header height and moves focus to the destination, so keyboard and mouse users arrive in the same place.

07 · Worth keeping

The parts worth keeping

⌘K everywhere

Jump to any service, trace or dashboard from anywhere on the page, with a real focus trap and number shortcuts.

The drawn dashboard

Throughput, error rate, p95 latency, ingest and a live log tail — all markup, all themeable, all sharp at any density.

Deep-dive tabs

Traces, alerts and boards swap in place with correct aria-selected and roving tabindex.

Pricing that answers

A monthly/annual toggle with aria-pressed that rewrites the figures rather than opening a contact form.

Cursor light

One pointer listener and two custom properties light six cards. Disabled on coarse pointers and under reduced motion.

Status colour, sparingly

Cyan, green, amber and red exist only where a state is being reported. Nothing decorative is ever a status colour.

Command palette

The palette is the only genuinely hard component on the page. It has to lock the background scroll without shifting layout, cycle Tab within itself in both directions, restore focus to whatever opened it, filter a list live, and accept number keys as shortcuts — all while remaining announceable, which means role="dialog", aria-modal and a labelled input rather than a styled div.

  • aria-modal
  • Focus trap
  • Scroll lock
  • Live filter
  • Number shortcuts
  • Focus restore

Bento glow

Six feature cards share one cursor-tracked glow. The naive version attaches a pointermove listener to each card and writes each card's gradient position — six listeners, six writes a frame. Instead, one listener on the grid writes two custom properties, and all six cards read them in a radial-gradient. The cost is identical whether there are six cards or sixty.

  • One listener
  • Two properties
  • radial-gradient
  • pointer: fine only

The ramp

Dark interfaces fail on the third grey. Signalform uses exactly three text weights — #E6E8EE, #9CA1B2 and #868B9C — and the faintest one is annotated in the stylesheet with the ratios it was chosen for: 5.72:1 on the background and 5.23:1 on the raised surface. Nothing dimmer than that exists in the file, so there is no dimmer thing to reach for later.

  • 3 text weights
  • 2 surfaces
  • 4 status colours
  • WCAG AA verified

08 · Run it live

Run it here

The real build, embedded and running — try ⌘K once it loads. Nothing is fetched until you ask for it.

Skip the live preview
Signalform as it appears on load

The real build, running in the page. The live preview is an embedded page; press Escape to leave it.

Open full screen ↗