MeridianObservatory

Field guide · how this page was built

The sky is the dataset. Everything else stays quiet.

Meridian Observatory is a fictional mountain-top observatory whose page has one job: schedule and wonder. There is not a single image file on the site — the hero is 632 stars from the Yale Bright Star Catalog, projected for the ridge's coordinates at the minute you load the page, drifting at sidereal rate. The program times are computed from the Sun's real altitude. The flex is that none of it is decoration; all of it is true.

01 · Palette

Deep indigo, never black — a moonless sky has colour in it. Moonlight silver for text, star white for emphasis, and one warm red taken from a dome's night-vision lamps. The red is behavioural, not decorative: it marks solar anchors, transit times, and powers the site-wide red-light mode.

#070B1D
indigo, deep
#121838
indigo, panel
#AEB7D4
moonlight silver
#F2F4FF
star white
#D84A32
dome red

Try the red light toggle in the header of the main page: the whole palette collapses to reds and near-black, the way an observatory lights its interiors so your eyes stay dark-adapted. The star chart re-renders monochrome red too.

02 · Type

Cormorant

Headings. A light, high-contrast garalde whose hairline strokes read like starlight at display sizes. Its italic labels the constellations on the canvas itself.

Spline Sans Mono 21:04:37

All data: sidereal clock, ephemeris, transit tables. Tabular numerals so times align like an almanac column.

Albert Sans

Body copy at weight 300 — quiet, geometric, and happy to disappear behind the two character faces.

03 · The signature: a truthful star chart

At build time, the Yale Bright Star Catalog (via the d3-celestial dataset) is filtered to magnitude ≤ 4.2 and compressed to a 32 KB literal: [ra, dec, mag, b−v] per star, plus polylines for all 88 constellations. At runtime, three short functions do the astronomy:

// Julian date → Greenwich mean sidereal time (degrees)
const gmst = j => (280.46061837 + 360.98564736629 * (j - 2451545)) % 360;

// equatorial → horizontal, via the rotation to NEU components
const H  = (lst - ra) * D2R;                     // hour angle
const xh = -cos(H) * cosDec * sinLat + sinDec * cosLat;  // north
const yh = -sin(H) * cosDec;                             // east
const zh =  cos(H) * cosDec * cosLat + sinDec * sinLat;  // up
const alt = asin(zh), az = atan2(yh, xh);

// azimuthal equidistant projection, east on the LEFT —
// a chart you could hold overhead and match to the sky
const r = R * (90 - alt) / 90;
const x = cx - r * sin(az), y = cy - r * cos(az);

Each frame recomputes every star from a simulated clock running at 60× real time, so the sky visibly turns — one hour of rotation each minute. Star size and alpha come from magnitude; colour from the B−V index (blue-white giants to amber supergiants). Stars brighter than magnitude 1.2 get a soft radial-gradient halo, and stars brighter than 1.9 twinkle on individual sine phases.

Hover detection is point-to-segment distance against every projected constellation polyline; the nearest figure within 15 px animates its lines drawing on, with its Latin name set in Cormorant italic at its centroid. When no pointer is around, an attract loop quietly cycles through whichever constellations are currently high in the sky.

The same math powers the schedule: the Sun's altitude is scanned minute-by-minute to find sunset and the three twilights, which anchor the program timeline and the sun-path diagram. Transit times in the targets table solve LST = RA for each object. Load the page tomorrow and every number will have moved.

04 · Three passes

  1. Pass 1 — correctness & composition. Verified the projection against the real July sky (Vega near the zenith, Scorpius low in the south), moved the chart so the east cardinal cleared the hero copy, decluttered the sun-path diagram — civil and nautical crossings became bare dots since their times live in the program — and fixed the guide inheriting the main page's section padding.
  2. Pass 2 — elevate. Replaced the header's fading gradient with a blurred glass bar after a mid-scroll screenshot showed nav colliding with content, choreographed the page-load rise, added a live NEXT tag to whichever target crosses the meridian soonest, and screenshot-tested the constellation hover and full red-light mode.
  3. Pass 3 — taste. Chanel rule: dropped the Bortle readout from the hero (it repeated what sky quality already said) and moved the cardinal letters inside the rim like a printed planisphere. Re-checked 390 px layouts and confirmed reduced-motion serves a still, real-time sky with instant constellation lines.

05 · Do this yourself

  1. Pick a subject with verifiable data at its heart — a tide table, a train timetable, a star catalog. Truth is the best art direction.
  2. Ask Claude for a compact build-time script that filters a public dataset down to a few kilobytes of literal JSON you can ship inline.
  3. Have it write the domain math from first principles (here: sidereal time, alt-az transforms, solar altitude) — and check one value against reality before styling anything.
  4. Commit to a palette of four colours where one is behavioural, not decorative. Give it a mode, a meaning, or a job.
  5. Choose one display face that could only belong to this subject, one mono for data with tabular numerals, and one invisible body face.
  6. Make the signature element respond to attention — hover, in our case — and let it demonstrate the data is live rather than saying so.
  7. Screenshot at 1440 and 390, critique brutally, and iterate three times. Remove one thing on the last pass.
  8. Write copy like a brand voice, not a spec: plain verbs, specific numbers, no filler.