# Load a scene — Five SDK

Parse Work, mount a sized viewer, observe loading, and release its browser resources.

Canonical: https://developer.realsee.ai/docs/five-sdk/load-a-scene
Source: https://developer.realsee.ai/docs/five-sdk/load-a-scene.md
Language: en

[Download examples](https://developer.realsee.ai/starters/react-five/1.3.0/starter.zip)

Use this task when you already have Work data and need to display it safely.

## Run the example

[Run the starter](https://developer.realsee.ai/docs/five-sdk/quickstart), then open **SDK examples**. A real public scene should reach Ready. Resize the browser and check that the canvas stays aligned with its container.

Work describes a scene; it is not a gateway token, a Team VR identifier, or arbitrary metadata. Public JSON and Team API responses must reach `parseWork` before `load`.

## Mount and dispose

Give the host a visible width and height. Mount the renderer before loading Work. Keep the returned cleanup and call it when leaving this task or replacing the scene.

```ts title="starters/react-five/src/recipes/mountScene.ts"
import type { Five as FiveInstance } from "@realsee/five";

export type MountedScene = {
  five: FiveInstance;
  dispose: () => void;
};

/** Browser only. Give host an explicit height before calling this function. */
export async function mountScene(
  host: HTMLElement,
  rawWork: unknown,
  signal?: AbortSignal
): Promise<MountedScene> {
  const { Five, parseWork } = await import("@realsee/five");
  signal?.throwIfAborted();
  const five = new Five({ imageOptions: { size: 512 } });
  const layer = document.createElement("div");
  layer.style.cssText = "width:100%;height:100%";
  host.append(layer);
  let disposed = false;
  const resize = new ResizeObserver(() => five.refresh());
  const dispose = () => {
    if (disposed) return;
    disposed = true;
    signal?.removeEventListener("abort", dispose);
    resize.disconnect();
    five.dispose();
    layer.remove();
  };
  signal?.addEventListener("abort", dispose, { once: true });
  try {
    five.appendTo(layer);
    resize.observe(layer);
    await five.load(parseWork(rawWork), "initial");
    signal?.throwIfAborted();
    five.refresh();
    return { five, dispose };
  } catch (error) {
    dispose();
    throw error;
  }
}
```

Pass an `AbortSignal` when the host belongs to a component or route. Cancellation releases the instance and its own layer; it does not promise that every SDK-owned asset request stops immediately.

## Observe the relevant loading stage

A Work-ready event, panorama texture, model load, and refined model represent different stages. Attach listeners before the load you want to observe; unsubscribe when the viewer is disposed.

```ts title="starters/react-five/src/recipes/loadingFeedback.ts"
import type { Five } from "@realsee/five";

export type LoadingFeedback =
  | { stage: "work"; state: "ready" }
  | { stage: "panorama"; state: "loading"; progress: number }
  | { stage: "panorama"; state: "ready" | "error" }
  | { stage: "model"; state: "ready" | "refined" | "error" };

/** Attach before load. Progress describes an asset, not the entire app/API. */
export function watchLoading(
  five: Five,
  onChange: (value: LoadingFeedback) => void
): () => void {
  const stop = [
    five.on("works.ready", () => onChange({ stage: "work", state: "ready" })),
    five.on("pano.texture.progress", ({ progress }) =>
      onChange({ stage: "panorama", state: "loading", progress })
    ),
    five.on("pano.texture.success", () =>
      onChange({ stage: "panorama", state: "ready" })
    ),
    five.on("pano.texture.error", () =>
      onChange({ stage: "panorama", state: "error" })
    ),
    five.on("models.load", () => onChange({ stage: "model", state: "ready" })),
    five.on("models.refined", () =>
      onChange({ stage: "model", state: "refined" })
    ),
    five.on("model.error", () => onChange({ stage: "model", state: "error" })),
  ];
  return () => stop.forEach((unsubscribe) => unsubscribe());
}
```

A panorama progress value describes that asset. Do not display it as a fabricated percentage for authentication, all scene assets, or the complete app.

## Check the result

- The panorama or model is visible and responds to interaction.
- The canvas follows its container after resize.
- Changing route or scene removes the old canvas and listeners.
- Missing assets show an error; the app does not substitute a synthetic image.

For Team-owned Work, keep [authorization on the server](https://developer.realsee.ai/docs/open-api/quickstart). Continue with [Camera and modes](https://developer.realsee.ai/docs/five-sdk/camera-and-modes).
