Presence — baki.io

Presence

[SCAFFOLD - Baki to revise] Five states, one modifier layer, the room remembering you

Domain
tools
Archetype
build
Audience
builder
Date

Visitor presence

Second axis beside platform-recency. Platform-recency asks “how new is this content?”; visitor-presence asks “has this person been here, and how deeply?”. One storage schema, one state machine, two tiers of consent, one visualization layer.

The state machine has five states, computed from a per-node record in src/lib/presence.ts:

The thresholds live as named tokens (THRESHOLDS in presence.ts) so they can be retuned against real content without touching the classifier.

Storage routes by consent tier: ambient writes to sessionStorage and dies with the tab; local writes to localStorage under the baki.visitor.v1.<slug> keyspace and survives across visits; telemetry piggy-backs on localStorage and opts into an aggregate echo (server POST reserved for a later pass). Visitors switch tiers in one click via the VoidStamp - a section inside the Preferences page (system rail → preferences). The forget-me action flushes every baki.visitor.v1.* key in both stores and resets the tier back to ambient, so one interaction is a true “start fresh”.

Energy visualization

Eight fields run atop the substrate. Each one takes one semantic signal (tone, echoes, signals, recency, focus, presence) and translates it into motion or light:

Energy Viz obeys the Charter: resonance/transit/reaction motions suppress under prefers-reduced-motion; semantic channels (focus state, recency, presence state) survive as static end-states.

The location indicator

A small warm pill on the rail’s left edge tracks where focus currently lives. It targets the scroll-active subrail heading (or the active rail item when no heading has been reached), anchoring to the target’s left edge so it respects subrail indent flush with whatever row it points to.

Y position interpolates smoothly between the current rail target and the next one based on scroll progress within the active section - the pill slides down continuously as a section is read, arriving at the next heading just as the focus line crosses it. Per-frame ticker write; no CSS transition fights the continuous flow.

When the pill lands on a subrail heading, that heading picks up an immediate warm tan (via PresenceOverlay §4) so indicator and target reinforce each other visually. Baki’s persistent dwell-tan (HeadingPresenceHalo) builds up separately - headings you’ve spent time in stay warm; the indicator’s live glow tells you where you are right now.

The modifier layer

Presence is a modifier on platform-recency, not a new visual layer of its own. PresenceOverlay writes data-presence-state on every [data-rail-id] and [data-page-id] element, plus a data-presence-focus-state on <html> so fixed-position overlays (SubstrateTone lives outside the page subtree) can compose off it. Its shipped rules modulate three of the Energy Viz fields:

Reactivity: the overlay repaints on presence:change, presence:forget, tier changes, and canvas:focus-changed. A 2s poll catches late-mounted rail items when the spine filter flips (pages → tags → system).