Fix fluid worker, colour, alignment and reader problems
Start with fluid.stats(): it says which pipeline runs ("worker" or "main"), the encoding, the frame cap, the grid and how many vsyncs were skipped.
console.log(fluid.stats());// { fps: 60, pipeline: "worker", encoding: "atlas", cols: 144, rows: 66, frames: 812, stalls: 3, stepMs: 3.5, lit: 4210 }It runs on the main thread
Section titled “It runs on the main thread”pipeline: "main" means the worker never started or failed.
- Your bundler did not emit
worker.jsnext to the package’sdist/index.js. Pass a factory: in Vite,import FluidWorker from "@glyphcss/fluid/worker?worker"andworker: () => new FluidWorker(). - A Content Security Policy blocks workers: allow
worker-srcfor your bundle’s origin (orblob:if your bundler inlines workers). prefers-reduced-motion: reduceis set: reduced motion always runs on the main thread (it draws only settled stills).worker: falsewas passed.
Everything is one colour
Section titled “Everything is one colour”encoding: "plain" means the atlas font did not load or the browser lacks font-palette (Chrome 101+, Safari 15.4+, Firefox 107+). The fluid then draws real braille in one colour. Check the network panel for the atlas font request and any CSP font-src rule. encoding: "mono" is one colour by choice.
Targets land in the wrong place
Section titled “Targets land in the wrong place”- The element moved without a resize the fluid could see (an animation, a collapsing sibling, a late image): call
fluid.relayout(). - With
glue: "document"the host must be a fixed, viewport-sized layer (position: fixed; inset: 0); the fluid follows the page scroll by whole rows. - Web fonts: targets re-measure when
document.fonts.readyresolves. A font loaded later by other means needsrelayout(). - The grid shears or columns drift: the
<pre>must use the fluid’s own font settings; don’t override itsfont-family,letter-spacingorline-heightfrom page CSS.
It dropped to 30 fps
Section titled “It dropped to 30 fps”The governor drops to 30 for the session after a 60-frame window with more than 20 % missed vsyncs. That usually means the main-thread pipeline on a slow device (measured: about 20 % misses at a ×4 CPU throttle). Make sure the worker runs, reduce grid.targetCols, or set fps: 30 up front. fpsFallback: false keeps 60 regardless.
The reader is hard to read
Section titled “The reader is hard to read”- Use the default
look: "plain": real letters, legible at 600 wpm. Inlook: "glyph"each word is a target the ink has to flow into; at highwpmshort words leave before they settle, and long words are drawn smaller (each word is sized to fit the host). - Plain letters still scrambling (
.:-=): the ink under them has not arrived yet. It pools in a band shared by consecutive words, so this only shows at a sentence start or on a much longer word; lowerwpmif it bothers. - Give the host room: the letters scale with the host’s width; a host under about 240 px wide makes them small (glyph look: few cells tall). Plain letters need at least 3 rows of height (about 40 px at 416 px wide): the fluid never inks its border rows, so a thinner host has nowhere to pool.
- Keep the default 52-column grid: denser grids make smaller dots, not sharper letters.
- Under reduced motion each word is a single settled still, by design.
Nothing draws
Section titled “Nothing draws”- The host has no size: the grid comes from its box (
glue: "host"). Give it a width and height. clock: "manual"draws only onfluid.step(dt).- The reader’s
textis empty or whitespace: the clock has no words and never starts.