1// async data fetching with full type safety
2import { createContext, useContext } from 'react'
3 
4interface ApiResponse<T> {
5 data: T
6 status: number
7 ok: boolean
8}
9 
10async function request<T>(
11 url: string,
12 options?: RequestInit
13): Promise<ApiResponse<T>> {
14 const res = await fetch(url, options)
15 const data = await res.json() as T
16 return { data, status: res.status, ok: res.ok }
17}
18 
19const BASE = 'https://api.vesper.dev'
20const TIMEOUT = 5_000

Theme cockpit

HearthCode

Pick Ember or Moss, preview the shipped theme live, then install it where you already work.

Forge your own primary color

Every surface

One color language, everywhere you work

There is exactly one semantic system: comments always recede, control flow always leans forward. Changing surfaces never changes meaning.

VS Code & VSX editors

directions × modes2 × 2
1// async data fetching with full type safety
2import { createContext, useContext } from 'react'
3 
4interface ApiResponse<T> {
5 data: T
6 status: number
7 ok: boolean
8}
9 
10async function request<T>(
11 url: string,
12 options?: RequestInit
13): Promise<ApiResponse<T>> {
14 const res = await fetch(url, options)
15 const data = await res.json() as T
16 return { data, status: res.status, ok: res.ok }
17}
18 
19const BASE = 'https://api.vesper.dev'
20const TIMEOUT = 5_000

Ember and Moss each ship dark and light builds on the VS Code Marketplace and Open VSX, generated by the same pipeline.

Install in VS Code

Obsidian

directionMoss

Design note · Moss

Color as reading order

Quiet body text holds a steady rhythm; links, emphasis, and code step forward only when needed.

Comments recede. Structure leads.
#color-language

The Obsidian theme ships the Moss direction in dark and light, so notes and long-form reading use the same semantic system.

Get the Obsidian theme

This site itself

body-text budget≥ 4.5:1
HEARTH / TOKEN LABAUDIT PASS

Color contract

Every semantic has a place

Body text stays steady while key actions move forward; one token set governs interface and code.

Every color on this site derives from the theme tokens, and the body-text contrast budget is enforced by an audit on each commit — what you're reading is the calibrated output.

Ember currently ships for the VS Code ecosystem and this site; the Obsidian theme is the Moss direction.

Calibration pipeline

Colors aren't picked. They're calibrated.

Every shipped theme goes through the same pipeline: an explicit color contract, joint solving in perceptual space, per-item audits, and a sweep of the entire Forge input space.

  1. Declare the contract

    Each direction states its rules up front: minimum ΔE for critical pairs, allowed hue bands per signal lane.

    7critical pairs

    ΔE floor≥ 8–10signal lanes14
  2. Solve jointly

    Neighboring roles are solved together for separation in perceptual color space; light variants also meet per-role contrast floors.

    1.28median separation target · light

    dark median1.05per-role contrast floor≥ 2.2–5
  3. Gate on audits

    Shipped themes are re-measured against the contract item by item — a failing audit blocks the commit.

    4shipped themes

    issues0warnings0
  4. Sweep the input space

    The entire Forge input space is swept on a hue × saturation grid; every point must pass the same quality gates as the shipped themes.

    48grid points

    hue step15°saturation band60–100

These figures are read directly from the contract and audit source files and update with every recalibration.