Introduction
Pue JS is a zero-dependency, strictly typed acoustic feedback layer for the web. It observes the kinematics of a scroll container and translates them, in real time, into organic gaseous emissions — pitched, shaped and scheduled on the Web Audio clock.
It is designed for teams who believe that interfaces should be felt, not merely seen.
What Pue JS does
Every scroll interaction carries information: direction, distance, velocity, acceleration. Most applications discard it. Pue JS captures this signal and renders it as audible feedback through a deterministic pipeline:
- Sampling — scroll position is sampled once per animation frame through passive listeners.
- Kinematics — instantaneous velocity is derived and smoothed with a low-pass filter.
- Tonnage — velocity is mapped to intensity through a configurable tonnage curve.
- Selection — an odor, a pre-decoded sample, is chosen according to tonnage.
- Playback — the sample is played through Web Audio with per-emission pitch, resonance and gain.
Samples are inlined in tree-shakable modules: there are no assets to host and no network requests. The full library, odors included, weighs 7.7 kB gzip.
Design principles
- Determinism. Identical scroll input produces identical acoustic output. Emissions can be snapshot-tested.
- The main thread is sacred. Scroll listeners are passive, sampling happens once per frame and audio is rendered on the Web Audio thread.
- Pay for what you use. Odors are isolated ES modules. Unused odors are eliminated at build time.
- Consent first. Pue JS never produces sound before an explicit user gesture and honours
prefers-reduced-motionby default.
These principles are expanded in the Manifesto.
Browser support
Pue JS requires the Web Audio API and ships ES2022 syntax, both available in every evergreen browser.
| Browser | Minimum version |
|---|---|
| Chrome | 80 |
| Edge | 80 |
| Firefox | 74 |
| Safari | 14.1 |
In unsupported environments — including server-side rendering — createEmitter returns an inert emitter. Your application keeps working; it simply remains silent. Use isSupported() to detect this ahead of time.
Next steps
- Install Pue JS in your project.
- Ship your first emission with the Quick Start.
- Understand the runtime in Architecture.