> ## Documentation Index
> Fetch the complete documentation index at: https://prefab.prefect.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Playground

> Build and preview Prefab components interactively in your browser.

export const PlaygroundFrame = () => {
  const ref = React.useRef(null);
  const [src, setSrc] = React.useState(null);
  React.useEffect(function () {
    document.documentElement.setAttribute("data-page-mode", "wide");
    var isLocal = location.hostname === "localhost" || location.hostname === "127.0.0.1";
    var url = isLocal ? "/playground.html" : "https://cdn.jsdelivr.net/npm/@prefecthq/prefab-ui-playground@latest/playground.html";
    fetch(url).then(function (r) {
      return r.text();
    }).then(function (html) {
      var blob = new Blob([html], {
        type: "text/html"
      });
      setSrc(URL.createObjectURL(blob));
    });
    return function () {
      document.documentElement.removeAttribute("data-page-mode");
    };
  }, []);
  React.useEffect(function () {
    if (!src) return;
    function onMessage(e) {
      if (!e.data) return;
      if (e.data.type === "pg-ready") {
        var hash = window.location.hash.slice(1);
        if (!hash) return;
        var params = new URLSearchParams(hash);
        var encoded = params.get("code");
        var theme = params.get("theme");
        if (ref.current && ref.current.contentWindow && (encoded || theme)) {
          ref.current.contentWindow.postMessage({
            type: "pg-init-code",
            encoded: encoded || "",
            theme: theme || ""
          }, "*");
        }
      } else if (e.data.type === "pg-code-changed" || e.data.type === "pg-theme-changed") {
        window.history.replaceState(null, "", "#" + e.data.hash);
      }
    }
    window.addEventListener("message", onMessage);
    return function () {
      window.removeEventListener("message", onMessage);
    };
  }, [src]);
  if (!src) return null;
  return <iframe ref={ref} src={src} style={{
    width: "100%",
    height: "max(800px, 80vh)",
    border: "none"
  }} sandbox="allow-scripts allow-same-origin" />;
};

<PlaygroundFrame />

***

## Render Target

The playground renders whichever thing was created last: a standalone component or a `PrefabApp`. Create a `PrefabApp` after your components and it becomes the output, bringing its theme and mode along.

For explicit control, define `main()` and return whatever you want rendered:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from prefab_ui.app import PrefabApp
from prefab_ui.themes import Presentation
from prefab_ui.components import Column, Heading

def main():
    with Column() as view:
        Heading("Dashboard")
    return PrefabApp(view=view, theme=Presentation(accent="cyan"))
```

`main()` always takes priority when your code creates multiple components or apps.

## Themes

Themes from `PrefabApp` apply in the playground the same as in production. The toolbar's theme picker overrides the code-defined theme when active; selecting "Code" restores it.

See the [themes docs](/styling/themes) for `Basic`, `Minimal`, `Presentation`, and custom themes.
