Guide · Industry demonstration · IT & MSP

How Greenlight IT was made

A fictional managed-IT provider in Subiaco, built as a single conversion-focused landing page: the calm NOC at 9am, a wall of green status tiles, and per-user pricing with nothing hidden in it.

Concept

Greenlight IT is the status LED every business wants to see: all systems green. The audience is the practice manager whose server closet nobody understands, the 12-person engineering firm sick of pay-by-the-hour surprises, the accountant who cannot afford a down day in tax season. The page has one job — book a free IT health check — and it sells uptime, not dread: zero hoodie-hacker clichés, zero fear-mongering, competence as quiet as a well-run network.

Conversion decisions

Palette — NOC-morning green

Argued from a monitoring wall in an office with actual windows. The bright uptime green is a LINE/MARK token only — LEDs, spark-lines, the CTA surface — never body text; two darker greens were derived for type and buttons per the collection's ink/line split.

Console daylight#F5F6F2

Ground — the lit monitoring wall at 9am, not gallery cream.

Graphite bezel#20282B

Structure and primary ink — monitor bezels and rack rails; the builder card's dark surface.

Uptime green#2E9E5B

LINE/MARK — the all-clear LED. ~3.2:1 on daylight, so never body text.

Green ink (derived)#1E6B3E

Body-safe green for eyebrows, prices, links on daylight — 7+:1.

Green deep (derived)#1F7A45

CTA surface — white button text clears 4.5:1, which raw uptime green doesn't.

Green bright (derived)#5FCE92

Green type on the dark bezel card — ~7:1 on graphite.

Signal blue#3D6FA8

Secondary — the info-level tick: links, focus rings, VoIP tiles, the backup ring.

Type

Techniques — the Plan Builder status wall

Everything is procedural: no raster images, no canvas, no rAF loop — the page is SVG, CSS gradients and CSS animation only, calm on a 4G phone. The status wall is a single SVG rebuilt from state on every interaction: the tile grid's column count is computed from the device total (seats + VoIP handsets) to roughly fill a 16:9 field, each seat tile gets a green LED and a CPU spark-line whose points are seeded deterministically from the tile index (so the wall is stable frame to frame), and handset tiles render in signal blue. The spark-line flow is a CSS stroke-dashoffset animation applied to an inner <polyline> whose geometry lives in attributes the CSS never touches — positions stay on outer <g transform> groups, per the collection's SVG-attribute-vs-CSS rule. The nightly-backup toggle draws a marching dashed ring around the wall; the security bundle raises a pulsing shield whose opacity floors at 0.6, so the signature never reads dead at any capture instant. Reduced motion stops every loop and leaves the wall fully rendered and priced.

The Perth service-area map is hand-drawn SVG: coastline, Swan River, and fourteen named suburbs rendered as status nodes linked back to the Subiaco hub — the NOC metaphor carried into geography.

Pricing model — shape and derivations

The model is deliberately flat: a per-user rate that does not taper with seat count. That flatness is the product ("one flat line, every month") — volume pricing at 50+ seats is a real-client conversation, and the stepper says so at its ceiling. All anchors below are the spec's pinned figures; the builder computes seats × rate + add-ons and nothing else.

ItemAnchor
Essentials — helpdesk, patching, monitoring, AV (min 5 seats)$65/user/mo
Managed — + EDR, M365 management, quarterly vCIO (min 5 seats)$110/user/mo
Microsoft 365 backup+$6/user/mo
Security bundle — MFA, phishing sim, dark-web monitoring+$18/user/mo
Managed VoIP (own handset count, defaults to seats)$30/handset/mo
Ad-hoc support (min 1 hr)$150/hr
Microsoft 365 migrationfrom $1,600
Security audit & baselinefrom $950

Measured worked examples (from the running page, verified against an independently reimplemented oracle in the QA harness):

Spec correction, documented honestly

The wave spec pinned the rest state as "12 users, Managed, backup ON, $1,320/month showing" while also deriving the worked example as "12 × $110 = $1,320, no add-ons". Those two can't both be the headline: with backup ON the honest total is 12 × ($110 + $6) = $1,392. Per the collection's honest-numbers rule (measure, then ship the measured figure), the card shows $1,392/month as the total, with the $1,320 Managed plan line and the $110/user rate itemised directly above it — every pinned figure is on the card, and the arithmetic never argues with itself. The no-add-ons example is verified in QA by toggling backup off (displayed total drops to exactly $1,320).

Local SEO we'd implement for the real business

This demo page carries only WebPage schema naming it a demonstration — fictional structured data in a real index is dishonest markup. For a real client we'd ship LocalBusiness + Review schema fed by their actual details and live review stream:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "name": "Greenlight IT",
  "description": "Managed IT support for small business — Subiaco and Perth metro.",
  "telephone": "+61-8-XXXX-XXXX",
  "url": "https://www.example.com.au",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Suite X, XX Example St",
    "addressLocality": "Subiaco",
    "addressRegion": "WA",
    "postalCode": "6008",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.95, "longitude": 115.82 },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "07:30", "closes": "18:00"
  }],
  "areaServed": ["Subiaco","West Perth","Perth","Leederville","Nedlands","Osborne Park"],
  "priceRange": "$$",
  "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "87" },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "Real client name" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "Pulled from the live review feed, never hand-typed."
  }]
}
</script>

What would change for the real client

Iteration log

Pass 1 · Craft

Rest state, arithmetic, first real look

Headless drive at 1200×750: zero console errors, exactly one h1, builder bounding box top at 128px (signature shares the thumbnail viewport). Rest probe measured 12 seats / Managed / backup ON → $1,392 total against the independent oracle, with the $1,320 plan line and $110/user rate both rendered on the card; 12 tiles, 12 spark-lines, backup ring present, shield correctly absent. Screenshot review: masthead clean, wall reads instantly, tile grid sits slightly high in its field at 12 seats — accepted as headroom (the wall grows to 50), noted rather than tuned. JSON-LD parsed valid; inline script passed node --check.

Pass 2 · Depth

Every control driven against the oracle

31 asserts, all green. Cheapest path: stepped to 5 seats on Essentials, toggles off → $325 displayed, equal to the grid floor 5 × $65, minus button disabled with the ad-hoc reason on-page, wall at 5 tiles, ring gone. Scenario drive: 20 seats Managed + all add-ons → $3,280 (oracle match); handsets stepped 20 → 8 → $2,920; wall showed 28 tiles (20 green + 8 blue), shield up, ring back; touched handsets correctly stop syncing to seat count. Max clamp at 50 swaps in its own honest note (a second-read detail). Prefill handoff verified: scenario box, seat field and drafted message land in the form, probe reports prefilled. Filled submit produced the local confirmation naming the visitor's suburb, inside the "we'd call / received / be in touch" lexicon. FAQ driven open; its 12 × $110 = $1,320 worked example greps consistent with the card and this guide. Screenshot review of the driven wall: handset tiles read as phones, shield and ring both visible, caption "20 SEATS + 8 HANDSETS · 28 DEVICES, ALL GREEN".

Pass 3 · Hardening

375px masthead first, fresh-load validation, reduced motion

Masthead screenshot at 375px FIRST, per the wave rule — wordmark and phone link co-exist without overlap, tel target 44px. Two real defects found by looking, invisible to every geometry assert: the eyebrow's LED dot floated mid-height when the kick wrapped to two lines (now anchored to the first line), and the sticky bar's call button wrapped "Call (08) 9000 0256" onto two lines (label simplified to icon + number — also this build's Chanel-rule removal). Fresh-load empty submit flagged all five fields with visible messages, aria-invalid and focus moved to the first offender; letters in the phone field rejected. Above the fold at 375: h1, primary CTA (51px tall) and trust chips all inside 667px. Sticky bar fixed within the bottom 140px, 48px targets, drives to the form. Reduced-motion emulation: spark-flow, LED pulse and hub pulse all report animation: none while the wall renders settled and fully priced. [hidden] guard verified collapsing the handset row, scenario box and confirmation. No horizontal overflow at 375/1440; zero console errors across every run.