▶ Live demo — the interactive playground, in your browser. ⚡ Try it now: Svelte · React · Vue — editable StackBlitz starters, no install.
Glowing retro display components: a generic 3D LED-grid display — an nx×ny×nz lattice of glowing "LEDs" you draw on like a tiny 3D canvas, rendered in WebGL and orbitable (auto-spin + drag + zoom) — plus seven 2D-canvas cores: a nixie tube, a seven-segment digit, an electromechanical flip-dot board (discs physically rotate, and click), a split-flap (Solari) display (flap cards fall from a drum, and clack), a neon sign (text bent into glass tubes that strike, flicker, hum and age), a vacuum- fluorescent panel (a whole stereo faceplate in one envelope, phosphor smear and dimmer included), and a character LCD module (the 16×2 — slow liquid crystals that smear, a contrast pot you can overdrive, boot boxes: the family's first reflective display). All ship as framework-agnostic cores plus thin framework wrappers you install into any SPA.
Live demos: https://eetu.github.io/glowbox/ — a spinning torus, a strange
attractor, a voxelized X-wing model, a wave field, a GIF billboard, a text
ticker, rain, a wormhole fly-through, and a self-playing 3D Pac-Man, plus a
nixie-tube clock — flat 2D tubes or a 3D wire-cathode-in-glass scene — on the
/nixie route, an ageing seven-segment clock on /seven, a flip-dot board with
a solenoid rattle on /flipdot, a split-flap departures board — with chroma
image drums, matrix rain, snake and pong — on /splitflap, and a neon sign —
cursive glass power-cycling through its strike sequence, a worn NO / VACANCY,
a gas tour, the tired transformer — on /neon, a mini-system VFD
faceplate — tuner, CD and tape cycling behind a green filter, with a real
DIMMER and a spectrum analyser that smears — on /vfd, and a 16×2 character
LCD — typing under a blinking cursor, a CGRAM bar meter, crystal-speed
scrolling and a power cycle through the boot boxes, on a light stage where
reflective glass belongs — on /lcd.
| package | install | what it is |
|---|---|---|
@glowbox/led-grid |
yarn add @glowbox/led-grid |
plain-TS WebGL display + voxel API (zero deps) |
@glowbox/nixie |
yarn add @glowbox/nixie |
nixie-tube display core: glowing vector numerals (2D canvas) |
@glowbox/seven-segment |
yarn add @glowbox/seven-segment |
seven-segment display core: per-segment dynamics, ageing, LED/VFD |
@glowbox/flip-dot |
yarn add @glowbox/flip-dot |
flip-dot board core: physical disc flips, dithering, solenoid click |
@glowbox/split-flap |
yarn add @glowbox/split-flap |
split-flap (Solari) core: drum cascades, chroma image drums, card slap |
@glowbox/neon |
yarn add @glowbox/neon |
neon-sign core: glass tubes, strike sequences, wear, hum, light-theme ink |
@glowbox/vfd |
yarn add @glowbox/vfd |
VFD panel core: a stereo faceplate in one envelope, persistence, dimmer |
@glowbox/lcd |
yarn add @glowbox/lcd |
character LCD core: slow crystals, contrast pot, CGRAM glyphs, boot boxes |
@glowbox/crt |
yarn add @glowbox/crt |
composable CRT screen over any canvas: curvature, phosphor persistence |
@glowbox/svelte |
yarn add @glowbox/svelte |
Svelte 5 components, one per core (<LedGrid> … <LcdModule>) |
@glowbox/react |
yarn add @glowbox/react |
React components: one per core (^18 || ^19) |
@glowbox/vue |
yarn add @glowbox/vue |
Vue 3 components: one per core |
@glowbox/extras |
yarn add @glowbox/extras |
content: GIF/image players, 5×7 LED font text + scroller |
The rendering cores — the 3D LED grid (@glowbox/led-grid), the nixie tube
(@glowbox/nixie), the seven-segment display (@glowbox/seven-segment), the
flip-dot board (@glowbox/flip-dot), the split-flap display
(@glowbox/split-flap), the neon sign (@glowbox/neon), the VFD panel
(@glowbox/vfd) and the character LCD (@glowbox/lcd) — and each framework
package (svelte/react/vue) ships a thin component for all of them
(<LedGrid> + <NixieTube> + <SevenSegment> + <FlipDots> +
<SplitFlap> + <NeonSign> + <VfdPanel> + <LcdModule>).
@glowbox/extras layers content (GIF/image animation, text, audio bands) on the core's
draw API, and @glowbox/crt is the first effects layer — slap a curved phosphor
screen over any of them (or any canvas at all).
Every core takes theme: 'dark' | 'light' | 'auto' — a bundle of colour defaults
(never a render path), with 'auto' following the page's prefers-color-scheme. Any
colour you set yourself stays yours when the theme moves. What "light" means is the
core's own answer, and it is only sometimes an inversion:
A disc is painted on both faces, so flip-dot and split-flap invert honestly: black discs on a bone panel, or a bone strip printed in near-black.
neon cannot — a bloom has nothing to read against on white — so it switches to
polarity: 'absorb': the tubes ink a pale wall instead of lighting a dark one,
halation, hot core and all. It is the one invented element in the family. Each gas
carries its own ink, and a colour you name is the pigment — so a pale tube inks
faintly and a saturated one deeply, the same way round as it reads lit.
The emissive cores stay dark objects in both themes, because a phosphor anode or a
lit filament needs a dark window: for vfd the theme is the faceplate — the brushed
silver of a 70s receiver — and for nixie and seven-segment it is a heavier drop
shadow and a brighter rim, so the module sits on a pale page instead of floating on it.
led-grid switches the look instead (comic's opaque ink-outlined LEDs), and lcd
was light-native all along: a reflective pane is dark ink on a lit surface, so only its
plastic moves.
<script lang="ts">
import { LedGrid } from '@glowbox/svelte';
import type { LedDisplay } from '@glowbox/led-grid';
const draw = (d: LedDisplay) => {
d.clear();
d.sphere([4, 4, 4], 3, '#00aaff'); // Color: CSS string or [r,g,b] 0..1 (>1 blooms)
};
</script>
<LedGrid
size={[8, 8, 8]}
{draw}
led={{ glow: 3, offColor: '#0a0a12' }}
camera={{ autoOrbit: true, projection: 'perspective' }}
color={{ background: '#000', gain: 1.1 }}
interaction={{ zoom: true }}
/>The same component ships for React and Vue with the
same props (instance access follows each framework's idiom: an oncreate callback in
Svelte, a forwarded ref in React, an expose()d handle in Vue). Colours, glow, LED size, stagger (brick lattice), camera,
projection, zoom, pause and more are all customizable via grouped options (led
color camera interaction quality) that update live, and the voxel API draws
line / box / sphere / torus / cylinder primitives — see
@glowbox/led-grid for the full list and defaults, or use the core
directly on a canvas. LEDs render as real emitters (bright cores + glow halos,
tone-mapped) so they read on any background. The display resizes in place and recovers
from WebGL context loss on its own.
A Yarn-workspaces monorepo. Yarn is vendored (.yarn/releases/*.cjs,
invoked via node — no corepack).
packages/led-grid @glowbox/led-grid — the framework-agnostic library
packages/svelte @glowbox/svelte — the Svelte wrapper
packages/react @glowbox/react — the React wrapper
packages/vue @glowbox/vue — the Vue 3 wrapper
packages/extras @glowbox/extras — content helpers (GIF/image/text)
packages/nixie @glowbox/nixie — nixie-tube rendering core (2D canvas)
packages/seven-segment @glowbox/seven-segment — seven-segment rendering core (2D canvas)
packages/flip-dot @glowbox/flip-dot — flip-dot board rendering core (2D canvas)
packages/split-flap @glowbox/split-flap — split-flap rendering core (2D canvas)
packages/neon @glowbox/neon — neon-sign rendering core (2D canvas)
packages/vfd @glowbox/vfd — VFD panel rendering core (2D canvas)
packages/lcd @glowbox/lcd — character LCD rendering core (2D canvas)
packages/crt @glowbox/crt — composable CRT screen effect (WebGL pass)
examples/svelte-gallery the demo SPA (LED gallery + nixie/seven/flipdot/splitflap/neon/vfd/lcd) → GitHub Pages
node .yarn/releases/yarn-*.cjs install # or: yarn install (if yarn is on PATH)
yarn dev # run the demo gallery (Vite, :5173) against the library source
yarn build # build all packages (cores → wrappers/extras) + the demo
yarn test # vitest (node + headless-chromium browser) + Playwright e2e
yarn validate # lint + format + typecheck + test
yarn size # bundle-size budgets (size-limit; minified + brotli) on the shipped bundlesThe demo resolves @glowbox/* to package source (via kit.alias), so dev
and typecheck need no prior build; the packages are validated independently by
their own build/test.
Every package publishes to the public npm registry under the @glowbox scope. Tag
a release (vX.Y.Z) and the release workflow publishes each via npm trusted
publishing (OIDC) with provenance — no NPM_TOKEN secret (the cores first, then
the wrappers + extras). Each package needs a trusted publisher configured on npm.
MIT — see LICENSE.







