Plugin

joycelights.js

A Christmas-lights alphabet wall as a drop-in CSS + JS plugin. Inspired by Joyce Byers' wall in Stranger Things Season 1.

npm install @goboldlyforward/joycelights

Demo

Type a message, watch it light up

The wall paints letters one bulb at a time. Three built-in themes — original Stranger Things, classic Christmas, Fourth of July — show how the plugin adapts.

joycelights

type a message — the wall spells it for you, one bulb at a time

Try:

Install & usage

Drop it in

One stylesheet, one script. No framework, no build step.

<link rel="stylesheet" href="path/to/joycelights.css">
<script src="path/to/joycelights.js"></script>

<div id="wall"></div>

<script>
  const wall = new JoyceLights('#wall');
  wall.spell('RIGHT HERE');
</script>

Themes

Built-in and custom

Swap themes at runtime with setOptions. The built-ins (christmas, july4) ship as counter-examples so the API doesn't end up shrink-wrapped to one aesthetic.

wall.setOptions({
  theme: 'christmas',
  palette: ['red', 'green'],
  drips: false,
  letterTilt: 0, letterShift: 0, letterScale: false,
});

wall.setOptions({
  theme: 'july4',
  palette: ['red', 'white', 'blue'],
  drips: false, randomColors: true,
  letterTilt: 0, letterShift: 0, letterScale: false,
});

Palette colors: red · green · blue · yellow · orange · white. For a custom theme, add a modifier class (.joycelights--mygame) and override the CSS variables — see Theming below.

Full-bleed wallpaper

Promote the wallpaper from the wall element to the surrounding container so a whole section reads as one canvas:

<header class="stage joycelights--july4">
  <h1>Independence Day</h1>
  <div id="wall"></div>
</header>

<style>
  .stage {
    background-color: var(--joycelights-wallpaper-base);
    background-image:  var(--joycelights-wallpaper-image);
    background-repeat: repeat;
    background-size: 160px 160px;
  }
</style>

<script>
  new JoyceLights('#wall', { flat: true });
</script>

API

Options & methods

Everything's configurable — rows, palette, per-letter colors, timing, flicker, drips, theme. Methods cover the typical lifecycle plus a few extras.

Options

new JoyceLights('#wall', {
  rows: ['ABCDEFGH', 'IJKLMNOPQ', 'RSTUVWXYZ'],
  palette: ['red', 'green', 'blue', 'yellow', 'orange'],
  colorMap: { H: 'red', E: 'red', L: 'red', O: 'red' },
  randomColors: false,
  flicker: true,
  speed: 600,
  onTimeRatio: 0.7,
  drips: true,
  wallpaper: true,
  flat: false,
  theme: null,         // 'christmas' | 'july4' | null
  letterTilt: 14,
  letterShift: 6,
  letterScale: true,
  wireSag: 10,
  onLetter: (letter, color, index) => { /* sfx, etc. */ },
});

Methods

wall.spell('HELLO');
wall.spell('RUN', { speed: 900 });
wall.light('A', 'red');
wall.unlight('A');
wall.clear();
wall.cancel();
wall.setOptions({ theme: 'july4' });
wall.destroy();

Theming

CSS custom properties

The wall, the paint-drip letters, the wallpaper, and the bulbs all read from CSS variables. Override them in a modifier class to roll your own theme.

.joycelights {
  --joycelights-paint: #1a1612;
  --joycelights-wallpaper-base: #dec59b;
  --joycelights-wallpaper-image: url("…SVG data URI…");
  --joycelights-wire: #1a2a14;
  --joycelights-letter-font: 'Permanent Marker', cursive;
  --joycelights-letter-shadow: 0 1px 0 rgba(0,0,0,0.5), 1px 0 0 rgba(0,0,0,0.3);
  --joycelights-vignette: radial-gradient(/* … */);
  --joycelights-shadow: inset 0 0 60px rgba(60,30,10,0.35), 0 6px 30px rgba(0,0,0,0.6);
  --joycelights-radius: 4px;
}

HTML, CSS, and a smidge of JavaScript — no framework, no build step.