Skip to main content

scenography

scenography is a library for building declarative 3D art galleries on top of a three.js engine. You describe a space as plain data — walls, artworks, a camera — and the engine materializes it and runs it.

It was born to power virtual galleries like jllizaur.art, but it is designed to be reusable anywhere.

Core principle: data vs. runtime

The single most important rule. Two layers, never mixed:

  • Definition = pure data. Fully serializable to JSON. No three.js, no closures, no functions. This is what an editor produces, what a database stores, what travels over the network. It lives in @scenography/core.
  • Behavior = code. Triggers, scripts, render logic. Registered by reference and connected to the data by id — never embedded inside the definition. It lives in @scenography/engine.

A scene definition must always survive a JSON.parse(JSON.stringify(scene)) round-trip unchanged.

import { defineScene } from '@scenography/core';

// Layer 1 — DATA. Serializable.
const scene = defineScene({
walls: [
{
id: 'room',
path: [
[300, -300],
[-300, -300],
[-300, 300],
],
edges: [{ segment: 0, name: 'north' }],
},
],
artworks: [
{
id: 'lucho',
location: { type: 'wall', edge: 'north', position: '50%' },
src: '/lucho.jpg',
size: [120, 160],
},
],
camera: { start: { position: [0, 170, 0] } },
});
import { createGallery } from '@scenography/engine';

// Layer 2 — CODE. Wired by id, uses the runtime.
const gallery = createGallery(scene, { canvas });
gallery.start();

The packages

PackageWhat it is
@scenography/coreThe scene language: serializable data + validation. Zero three.js.
@scenography/engineThe runtime: materializes a scene with three.js and runs it.
@scenography/propsOptional, tree-shakeable catalog of set-dressing objects.
@scenography/overlayA framework-agnostic DOM overlay (HUD) layered over the canvas.
@scenography/reactReact bindings: a declarative <Gallery> component.

Continue with Installation and the Quick start.