Editing scenes
Build scenes visually with the node-based editor - events, apps, data sources and state.
A scene is what a frame shows: a graph of connected nodes that runs on the device. Scenes are built in a visual editor, then deployed onto the frame, where it runs.
Self-hosted backend, FrameOS Cloud and standalone frames
The same editor ships in the self-hosted backend, in FrameOS Cloud, and on a standalone frame's own admin page. Everything here works in all three, except compiled scenes, which need the self-hosted backend.
Create a scene
Click + Add new scene, give it a name, and open the editor.

The four node colors
- 🟥 Red - events. Entry points that trigger execution. The most important one is
render, which fires at a set interval (every 60 seconds, every hour, whatever you choose). Others react to button presses, schedules, or custom events. - 🟦 Blue - render apps. Draw things: images, text, calendars, gradients, split layouts.
- 🟩 Green - data apps. Fetch and transform data: download an image, query Home Assistant, parse an iCal feed, generate an image with OpenAI, take a screenshot of a web page.
- 🟨 Yellow - state fields. User-editable values (text, numbers, options) that can be changed live from the control page without redeploying.
Drag from the render event's connector to add a blue Render image app:

Then drag its image field out and pick a green data app to feed it - use FrameOS Gallery if unsure. Press deploy:

Caching
Every data app has cache controls. A scene might re-render every minute while its data app only fetches a new image every 15 minutes - the cached value is reused in between. And if a re-render produces the same image as before, an e-ink display won't refresh at all: no unnecessary flashing.

State fields
Add a yellow state field under the scene's "State" tab, then drag it onto the canvas and wire it into any app input. Deploy once, and from then on you can change the value live - from the frame's control page, the backend, or the HTTP API.


Fields are typed, and the type decides what the control page shows: text, long text, numbers, booleans, a colour picker, a date picker, a select box, raw JSON, a font picker, an image, a scene picker - or a path, which is a file and folder browser over the frame's own assets. "Which photo folder should this play?" becomes a picker instead of a typed-in string.
Code nodes
For quick data plumbing there are inline code nodes (green when not selected): single JavaScript or TypeScript expressions that combine or transform values mid-graph - string concatenation, math, formatting. (In an older compiled scene they are Nim expressions instead.)

How scenes run
Scenes are interpreted: the frame runs the graph as you drew it. New scenes are created that way, every scene FrameOS ships is built that way, and it's the only way ESP32 and Pico frames can work at all. What you get:
- Deploys are near-instant - nothing is recompiled, so a change is on the frame in seconds.
- Code nodes are JavaScript, TypeScript or JSX, and apps can be customised in JavaScript.
- It costs a little more per render, which matters very little on a display that takes 20 seconds to refresh anyway.
There is a second, older mode - compiled - which turns the scene into native code inside the frame's binary. It's faster per render and it's the only mode that can run custom Nim app source and Nim code nodes, but every change needs a full rebuild and redeploy, and it only works on a Raspberry Pi deployed from a self-hosted backend - the cloud only pushes interpreted scenes.
Compiled scenes are on the way out
Scenes made before the switch may still be set to compiled, and you can still choose it under a scene's settings on a Pi frame. It is not where FrameOS is heading, though - build new scenes interpreted unless you specifically need Nim. If you switch an existing scene between modes, do a full deploy afterwards; the editor warns you when a scene still contains Nim source that interpreted mode can't run.
On the frame side there are two ways a binary gets built: precompiled (the release binary plus
its driver libraries, scenes interpreted - the default) and static (everything compiled into
one binary, which is what a compiled scene forces). Frames still configured with the retired
shared or shared-scenes modes are moved to static automatically.
Preview before you deploy
Two ways to see a scene without committing to it:
- Preview in browser runs the scene in your browser. The frame's renderer is compiled to WebAssembly, so you get the real thing - same apps, same layout engine, same resolution - without deploying to a device, or before you own one.
- Preview on frame temporarily shows the scene on the actual frame without saving or deploying it. Good for checking how a colour dithers on real e-ink.
How to learn
FrameOS ships with many sample scenes. The fastest way to learn is to install them, open them in the editor, and poke around.

When the visual editor isn't enough, write your own apps - in Nim or JavaScript. Editing apps is next.