Skip to content

Render a first windgram

The windgram package ships ESM types and requires no DOM. This example reads a profile from disk, keeping loading policy separate from rendering. This is what it produces:

The chart and key this page's code produces

Morning stability gives way to a deep midday unstable column. The boundary layer, usable lift, and cloud base follow distinct arcs beneath wind that strengthens and veers with height.

A complete fair-weather convective cycle. This windgram shows one atmospheric profile in Etc/UTC. Morning stability gives way to a deep midday unstable column. The boundary layer, usable lift, and cloud base follow distinct arcs beneath wind that strengthens and veers with height.

Pressure kPa 90.3 90 Precip mm/h 0.5 0 Cloud % 100 0 H M L Layers % w* m/s 3 0 CAPE J/kg 1500 0 900m 2953ft 1668m 5472ft 2436m 7991ft 3203m 10510ft 3971m 13029ft 4739m 15548ft 10 11 12 13 14 15 16 17 18 19 11° 16° 23° 26° 24° 17° 13° launch 1050 m G7 G9 G11 G14 G22 G29 G32 G22 G16 G13 10° 20°
Usable lift Cloud base Boundary layer Model boundary layer 0 °C Condensation LAPSE RATEVery unstableUnstableConditional strongConditionalNear neutralStableInvertedStrong inversion-3-2.5-2-1.5-1.200.5UnstableConditional instabilityStableInverted
Rendered at build time by the released package — validate, build a scene, serialize the chart, then derive the key from that final scene. Swap the committed teaching profile for your published one and the code below is the whole program.Units altitude m and ft · wind km/h · temperature °C · pressure kPa · precipitation mm/h · w* m/s
  1. Install the package:

    Terminal
    npm install windgram
  2. Validate the untrusted JSON, build a scene, and serialize the chart and its key:

    render-windgram.ts
    import { readFileSync, writeFileSync } from "node:fs";
    import { parseWindgramProfile } from "windgram/contract";
    import { buildKeySpec, buildScene } from "windgram/scene";
    import { renderKeySvg, renderSvg } from "windgram/svg";
    const raw: unknown = JSON.parse(readFileSync("./profile.json", "utf8"));
    const profile = parseWindgramProfile(raw);
    if (!profile) throw new Error("unsupported or invalid profile");
    const timeZone = profile.site.timeZone;
    if (!timeZone) throw new Error("older profile needs an explicit IANA timezone");
    const scene = buildScene(profile, {
    timeZone,
    widthPx: 960,
    hourLabel: "12h",
    });
    const svg = renderSvg(scene, { idPrefix: "club-main" });
    const keySvg = renderKeySvg(buildKeySpec(scene), { idPrefix: "club-main-key" });
    writeFileSync("./windgram.svg", svg);
    writeFileSync("./windgram-key.svg", keySvg);
  3. Place both SVGs in the consuming page or build. Each serializer returns a complete <svg> document with the same token authority. Rebuild the scene-derived key whenever controls rebuild the scene.

This example reads from disk. When the profile instead arrives from independently cached static storage, use loadProfile() from windgram/transport; the transport guide defines its consistent-pair result, stale flag, and discriminated miss.