Skip to content

Scenery Application vs. Standalone Library

SceneryStack can be used two very different ways, and picking the right one up front saves you from unpicking a Sim later. The rule of thumb: if you need multiple screens, a navigation bar, a home screen, PhET-iO instrumentation, or the Preferences dialog, use a Sim application. If you just need an interactive scene graph inside a page you already control, use scenery standalone.

Full application: Sim + Screen + ScreenView

This is the shape of every PhET simulation: a Sim owns one or more Screens, each with a ScreenView, and joist/sim supplies the navigation bar, home screen, keyboard help, and Preferences dialog for free. See Your First Simulation for the full wiring — you don't manage a Display yourself, Sim does it internally via SimDisplay.

Reach for this when your project is a self-contained, full-window interactive experience — especially if you want the accessibility, internationalization, and PhET-iO scaffolding that come with joist "for free."

Standalone: scenery without joist

If you only need a scene graph embedded in a larger page (a widget, a figure, an existing web app), skip Sim/Screen entirely and drive a Display yourself:

html
<div id="app" style="width: 600px; height: 400px;"></div>
ts
import { Display, Node, Rectangle, Text } from 'scenerystack/scenery';

const container = document.getElementById( 'app' )!;

const rootNode = new Node();
const display = new Display( rootNode, {
  width: container.clientWidth,
  height: container.clientHeight
} );
container.appendChild( display.domElement );

// Example content
const rotatingRectangle = new Rectangle( -150, -20, 300, 40, { fill: '#ccc' } );
const contentText = new Text( 'Content goes here', { font: '24px sans-serif' } );
rootNode.children = [ rotatingRectangle, contentText ];

contentText.center = display.bounds.center;
rotatingRectangle.translation = display.bounds.center;

display.initializeEvents(); // enable pointer/touch input
display.updateOnRequestAnimationFrame( dt => {
  rotatingRectangle.rotation += 2 * dt; // radians per second
} );

Key differences from a Sim:

Full application (Sim)Standalone (scenery only)
Owns the DisplayYes, internally (SimDisplay)You create and size it
Multi-screen / navigation bar / home screenBuilt inNot applicable — build your own UI
Preferences dialog, PhET-iOBuilt inOpt in manually if needed
SizingFills the browser windowYou size the container and Display
Render/animation loopManaged by SimYou call display.updateOnRequestAnimationFrame(...)
Input eventsEnabled automaticallyYou call display.initializeEvents()

Both ways to get the npm package are the same

npm create scenerystack@latest scaffolds either shape — it asks what kind of project you want. For an existing project, npm install scenerystack and importing scenerystack/scenery directly works identically whether you build a Sim or go standalone; the two paths diverge in application code, not installation.

Where to go next

  • Scenery Basics — the Node tree, coordinate frames, and Display fundamentals used by both approaches
  • Your First Simulation — the full-application path in detail
  • Scenery Layout — laying out content inside either a ScreenView or a standalone root Node