Golden dunes stretch wide
Shadows braid through dusk's thin light
Stars forget the dark
A hourglass animation rendered in Pixi.js. Built with LiquidJS templating and a Vite-powered dev pipeline.
The hourglass is drawn entirely on a Pixi.js canvas, with a glass container, wooden caps, and pouring sand. The canvas has a transparent background so the configurable CSS backdrop shows through. The Liquid template build system generates the static page and injects settings as CSS custom properties.
- LiquidJS — template rendering
- Pixi.js — 2D canvas rendering for the hourglass vessel, sand, and falling stream
- Vite — dev server with live reload and asset bundling
- PostCSS — CSS processing with
postcss-preset-envandautoprefixer - Node.js — build tooling
- Node.js (v18+)
- pnpm (or npm)
pnpm installGenerate the static site to dist/:
pnpm run buildStart the dev server with auto-rebuild and live reload:
pnpm run devThen open http://localhost:3000.
.
├── dist/ # Build output (ignored in git)
├── sections/
│ └── hourglass.liquid # Section template: container + Pixi.js script tag
├── scripts/
│ ├── build.js # LiquidJS renderer + asset copier
│ ├── sand.js # Pixi.js hourglass rendering module
│ └── data/
│ └── sections/
│ └── hourglass.json # Local default settings
├── style.css # Source CSS: background, font, vessel canvas styling
├── templates/
│ └── desert.liquid # Page wrapper template
├── postcss.config.cjs # PostCSS configuration
└── package.json
Section settings are defined in scripts/data/sections/hourglass.json and injected as CSS custom properties at build time:
| Setting | Description | Default |
|---|---|---|
bg_color |
Background color | #f5f3ef |
The sections/hourglass.liquid file also contains a {% schema %} block.
- Dunes-of-Sand: The hourglass shape is defined by cubic Bézier curves sampled into a lookup table (LUT) that gives the glass interior half-width at every y pixel.
- Glass layers: Pixi.js draws a translucent glass body fill, edge shadow, specular highlights, and wooden caps on top and bottom.
- Sand mask: A
PIXI.Graphicsmask clips all sand rendering to the glass interior, so sand never spills outside the vessel. - Sand fill: Each frame, the upper and lower sand bodies are drawn as polygons that conform to the LUT boundary. Highlights and depth shadows give the dunes dimension.
- Falling stream: A tapered polygon between the waist and lower dune surface represents the grain cascade, with a centre thread highlight.
- Animation: A Pixi.js ticker advances time
tfrom0 → 1over 12 seconds. The upper sand surface drops and the lower dune rises accordingly. - Background: The canvas uses
backgroundAlpha: 0so the CSSvar(--bg)color shows through, making the backdrop configurable via Liquid settings.
| Script | Description |
|---|---|
pnpm run build |
Build HTML, copy assets, and bundle with Vite to dist/ |
pnpm run build:html |
Build HTML only |
pnpm run dev |
Build HTML and start Vite dev server with live reload |
pnpm run preview |
Preview the production build locally |
pnpm run clean |
Remove dist/ |