Motion
Get Motion

DocsStudio

Web pages and web projects

Two layers put a web page in a scene. A Webpage layer shows a page that already exists: an address on the web, or an HTML page you have. A Web project layer is a page you write in Studio, in HTML, CSS and JavaScript, that moves to the music and the pointer and can talk to the scene's script.

7 min readMotion

Try it: Kelp Forest (a web project talking with its script).

Both are drawn like any other layer: you can place them, blend them, put effects on them and stack other layers over them. They're drawn on Linux and Windows; on Android they aren't drawn yet, and the rest of the scene plays without them.

The Webpage layer

Add a Webpage layer (it's under Backgrounds, and under Your own), starting from An address or a file. Its main setting is Address:

A page you bring in this way is copied into the scene's folder, under web/, so the scene carries it wherever it goes. Under the address, Studio says how loading went.

The other settings:

What a page may do

A page in a wallpaper can't wander off. Motion keeps to these rules:

Start a web project

Add a Webpage layer and, under Start from, pick Web project. Or click Add › Web page in Assets. It starts as a page, a stylesheet and a script (index.html, style.css, main.js), with motion.d.ts beside them.

Its files are written into the scene's folder, as web/page/ (or page2, page3 for the next ones). A scene that isn't saved yet keeps them in a draft folder, and they move with it when you save.

The layer's settings are much like the Webpage's, with a few differences:

Edit it in Studio

Pick the layer and click Open the editor in the inspector, or open Window › Files. The editor has three parts.

Studio writes each change half a second after you stop typing, packs the page again and reloads the preview. The line at the top says Saving…, then Saved and packed, or how many files are missing. Reload packs it again by hand.

What goes in

Studio packs the project's own files: scripts, stylesheets, pictures, fonts, sounds, videos, JSON and the rest. Everything the page refers to is put inside the packed page:

Hidden files, links out of the folder and anything past the limits are left out.

LimitMost
One file16 MB
A whole project64 MB
Files in a project2,000
A file the editor opens2 MB

The page and the scene: motion

Every page in a Webpage or Web project layer gets an object called motion. It's the scene as the page sees it.

motion.on("beat", (b) => pulse(b.pulse));
motion.on("frame", (f) => draw(f.time, f.dt));
motion.on("click", (c) => burst(c.px, c.py));

const glow = motion.prop("glow", 0.5);   // one of the scene's settings

What it holds:

NameWhat it is
motion.time, motion.runningThe scene's clock, and whether the wallpaper is playing
motion.bass, .mid, .treble, .levelWhat's playing, from 0 to about 1
motion.beat, motion.spectrum, motion.waveformThe beat, and the sound as bands and as a wave
motion.pointerx and y from 0 to 1 over the layer, and active
motion.props, motion.prop(name, fallback)The scene's settings, the ones offered in the wallpaper's settings
motion.layerThe layer: its name and the rest
motion.asset(path)A file of the project, as an address the page can use

And its events, with motion.on(name, fn), motion.once and motion.off:

EventWhen
readyThe page is loaded
frameEvery frame, at the layer's frame rate: time, dt
beatA beat: count, pulse
soundAbout 30 times a second while sound comes in
pointerThe pointer moved: x, y, active
clickA click or tap on the desktop: x, y (0 to 1), px, py (CSS pixels)
propsThe scene's settings changed
pause, resumeThe wallpaper stopped (it's covered, say) or carries on

Motion sends the page only what it reads. A page that never touches the sound or the pointer costs nothing for them. Draw on frame rather than your own requestAnimationFrame loop and the page keeps to the layer's frame rate and rests while the wallpaper is paused (Motion caps requestAnimationFrame to the frame rate too).

A page can be written in TypeScript too: a .ts file is compiled as the page is packed. motion.d.ts, in every new page, describes all of this for the editor.

Talking to the scene's script

A Web project's page can talk to the scene's script, both ways. (A Webpage layer showing a site can't.)

From the page:

motion.send({ wants: "rain" });                // to the script
motion.on("message", (data) => show(data));    // what the script sends

In the script, scene.on("page", (layer, data) => ...) hears it, and scene.sendToPage(layer, data) answers. In a graph, the nodes are On Page Message and Send to Page, under HTTP. What goes either way must be something JSON can hold, up to 64 kB at a time. See Logic as code and the scripting reference.

Asking the motes

A page can also reach the scene's motes through motion.stage. Each answer is a promise, answered by the scene's script, or refused if it doesn't come within ten seconds.

const motes = await motion.stage.motes();     // [{ id, name, class }]
const lamp = motion.stage.mote("lantern");    // by id or name
await lamp.set("brightness", 0.8);
const said = await lamp.call("glow", 3);
const where = await lamp.location();          // { x, y, z }

A page may get and set a mote's own properties and call its class's own methods. It can't call the methods every mote has, ones whose names start with _, or the ones the scene calls by itself (onTick, onClicked and the like).

When it's slow

A page is a whole browser page, and it costs about as much as one. Lower Frame rate and Resolution first. A page with nothing moving still costs a little every frame it draws, so 15 frames a second is often plenty for a clock or a calendar. Performance has more. Every setting is in the reference: Webpage and Web project.

Ask about this page on the forumAsk a question in Help

Last changed 2 November 2026. Something wrong here? Tell us.