wave-kit

View source

Design system and UI kit developed for Jay Hack's personal projects. Emphasizes simplicity, legibility and performance for technical writing.

npx skills add jayhack/wave-kit --skill build-with-wave-kit -y

Optional. This installs the agent skill for building with Wave Kit. You can also just and compose the components yourself.

Inspiration

This design system is inspired by the work of Kazumasa Nagai, a Japanese graphic designer, and other poster art from the '60s onward. Clean, abstract forms reminiscent of HAL 9000, but in a benevolent manner.

Kazumasa Nagai, primary reference
Secondary reference for radial systems and optical depth
No More War, repeated form and concentrated color

Wave motif

Waves are the recurring generative gesture across jay.ai. A simple cellular field carries energy outward from a point, turning the same cool-to-warm palette into motion.

Color

The system has four color anchors, not fourteen independent colors. Signal blue, heat red, energy orange, and light yellow carry the identity. The other values are associated shades used to give waves depth and intensity. Product UI stays neutral and usually uses only one anchor at a time.

Signal blue

wave-blue-vivid

Depth, navigation, and cool wave polarity.

Heat red

wave-red-vivid

Heat, urgency, and warm wave polarity.

Energy orange

wave-orange

The transition from heat into light.

Light yellow

wave-amber

Peaks, highlights, and maximum energy.

Canvas

#000000

Reading text

neutral-300

Navigation

sky-300

Typography

The stack is native system sans for speed and familiarity, with the platform monospace stack for tokens and small technical labels. Tight headlines meet relaxed body copy. The reading column is capped at 42rem (672px, max-w-2xl), matching the measure used by this page.

EditableTitle · Display / 48 / 800

Intelligence in motion.

EditableTitle · Heading / 24 / 800

Build the sharpest version.

EditableText · Body / 16.5 / 32 · Column / 42rem / 672px

Software should feel immediate. Structure the page so the useful thing appears first, then let detail reward attention.

Subtle / 14 / 24

Supporting context stays present without competing with the work.

Code / 12.5 / 20
wave-orange  #f97316

Back controls preserve in-app history when it exists and fall back to a known route for direct visits. Primary tabs use a simple two-pixel underline without filled pills or heavy chrome.

Companies, products, and AI systems. The active state is precise and quiet.

Progressive image

Reserve the final aspect ratio up front, paint a tiny inline placeholder immediately, then fade in a responsive WebP. The full image is lazy-loaded and asynchronously decoded, so the reading experience never waits on it.

Placeholder → responsive source set → full-resolution lightbox

Image cards

Image cards use a golden-ratio image by default, carry media all the way to the card edges, and keep one-line titles with at most two lines of supporting detail. When an href is provided, the entire card behaves as one link.

A diagram from the essay LLMs Are Not a Black Box

LLMs Are Not a Black Box

A compact image-led entry with a responsive preview and full-resolution source.
LLMs Are Not a Black Box
Intervention pipeline diagram

Intervention pipeline

A second card stays exactly aligned even when its source image and copy differ.
Intervention pipeline

Media rows

Media rows are full-surface links for editorial indexes. The preview moves to the right on wider screens and stacks below the text on mobile, with progressive loading and optional line clamping built in.

Diagrams

Treat diagrams as academic figures: use crisp SVG geometry, label every stage, axis, and series, and keep the composition minimal. Color must encode a stated meaning rather than act as decoration. Click either figure to inspect the original SVG.

Process diagram · signal blue encodes observed structure; heat red encodes the intervention.
Measurement chart · every axis, series, and annotation remains labeled without relying on color alone.

wave-paper Primary labels, titles, and high-contrast values.

wave-blue-vivid Observations, measured structure, and primary series.

wave-red-vivid Interventions, causal emphasis, and comparison series.

neutral-700 Axes, guides, borders, and secondary structure.

Dividers

Quiet rules divide long-form sections without turning every idea into a card.

Subtle
Strong

Code blocks

fibonacci.py
def fib(n: int) -> int:
    """Return the n-th Fibonacci number."""
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

print([fib(i) for i in range(8)])  # [0, 1, 1, 2, 3, 5, 8, 13]

Experiment registry

Register each run as a JSON record — slug, title, description, timestamp, optional metrics and checkpoint metadata — and render the registry with ExperimentIndex.

Live registry from the Blocket League lab.

experiments.json
[
  {
    "slug": "nano-1p5mb",
    "title": "The 1.5 MB capacity cliff",
    "description": "A width-72, four-block transformer with 10.27x fewer parameters.",
    "date": "2026-07-14",
    "metrics": [
      { "label": "12-frame error", "value": "4.98 px" },
      { "label": "64-frame error", "value": "19.10 px" }
    ],
    "meta": { "preset": "nano", "parameters": "357k" }
  }
]
Registry-driven pages
import { ExperimentIndex, ExperimentPage, parseExperiments } from "@jayhack/wave-kit";
import registry from "@/experiments.json";

const experiments = parseExperiments(registry);

// app/experiments/page.tsx — the index
export default function ExperimentsPage() {
  return <ExperimentIndex experiments={experiments} />;
}

// app/experiments/[slug]/page.tsx — one page per record
export default async function Experiment({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const experiment = experiments.find((entry) => entry.slug === slug)!;

  return (
    <ExperimentPage backHref="/experiments" experiment={experiment}>
      {/* Free-form body: figures, rollouts, experiment-specific code */}
      <RolloutViewer slug={experiment.slug} />
    </ExperimentPage>
  );
}
Built from the components already used across jay.ai. This page is the source of truth for the portable kit.