> ## 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.

# PrefabApp

> The application object that ties together view, state, theme, and assets.

Every Prefab UI is wrapped in a `PrefabApp`. It holds your component tree, state, theme, and external assets together as a single unit.

## Creating an App

### Context manager

The natural way to build an app. Components inside the `with` block become the view:

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

with PrefabApp(state={"volume": 75}, theme=Presentation(accent="blue")) as app:
    Heading("Dashboard")
    slider = Slider(value=75, name="volume")
    Text(f"Volume: {slider.rx}%")
```

The context manager creates an implicit root Column, so children stack vertically. State, theme, and styling are declared upfront — by the time the first component renders, the app envelope is established.

The root Column gets a `pf-app-root` CSS class that themes target for default padding. Add your own classes via `css_class`:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
with PrefabApp(css_class="max-w-3xl mx-auto") as app:
    Heading("Centered and constrained")
```

### Passing a view

If you build the tree separately, pass it via `view=`:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
with Column(css_class="p-6") as view:
    Heading("Hello")

app = PrefabApp(view=view, state={"greeting": "Hello"})
```

### From wire data

`PrefabApp.from_json()` wraps pre-serialized wire protocol data, for example from sandboxed execution. Keyword arguments override values from the wire:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
wire = await sandbox.run(code)
app = PrefabApp.from_json(wire, state={"extra": "value"})
```

## Fields

| Field             | Type                     | Description                                                                             |
| ----------------- | ------------------------ | --------------------------------------------------------------------------------------- |
| `view`            | `Component \| dict`      | Component tree to render (set automatically in context manager mode)                    |
| `state`           | `dict`                   | Initial client-side state                                                               |
| `theme`           | `Theme`                  | Theme to apply — see [Themes](/styling/themes)                                          |
| `css_class`       | `str`                    | Additional CSS/Tailwind classes for the root container. Stacks on top of `pf-app-root`. |
| `defs`            | `list[Define]`           | Reusable component definitions                                                          |
| `stylesheets`     | `list[str]`              | External CSS URLs to load as `<link>` tags                                              |
| `css`             | `list[str]`              | Inline CSS strings to load as `<style>` tags                                            |
| `mode`            | `"light" \| "dark"`      | Force light or dark mode                                                                |
| `scripts`         | `list[str]`              | External JS URLs to load in `<head>`                                                    |
| `connect_domains` | `list[str]`              | Domains to allow in CSP `connect-src` (for Fetch actions)                               |
| `on_mount`        | `Action \| list[Action]` | Action(s) to run when the app loads                                                     |
| `key_bindings`    | `dict[str, Action]`      | Keyboard shortcuts mapping key names to actions                                         |
| `title`           | `str`                    | HTML page title (default: `"Prefab"`)                                                   |

## Methods

**`app.html()`** returns a complete, self-contained HTML page with the Prefab renderer and all data baked in.

**`app.to_json()`** returns the wire-format envelope — a dict with `$prefab`, `view`, `state`, `defs`, `css`, `stylesheets`, and `mode` as needed.

**`app.csp()`** computes Content Security Policy domains from the app's asset configuration.

## State

`state` sets the initial values that template expressions like `{{ count }}` resolve against:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
with PrefabApp(state={"count": 0, "items": []}) as app:
    Text("Count: {{ count }}")
```

Pass state directly to the `PrefabApp` constructor:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
with PrefabApp(state={"count": 0, "items": []}) as app:
    Text("Count: {{ count }}")
```

## on\_mount

Run actions when the app loads. This is the place to start polling intervals, fetch initial data, or perform any setup that depends on the renderer being ready:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from prefab_ui.actions import SetState
from prefab_ui.actions.mcp import CallTool
from prefab_ui.actions.timing import SetInterval
from prefab_ui.rx import RESULT

with PrefabApp(
    state={"stats": {}},
    on_mount=SetInterval(
        duration=3000,
        on_tick=CallTool(
            "get_stats",
            on_success=SetState("stats", RESULT),
        ),
    ),
) as app:
    Metric(label="CPU", value=STATE.stats.cpu + "%")
```

`on_mount` is actually a universal component property — every component supports it, not just PrefabApp. For most components it fires immediately since the entire tree renders at once. But for components inside `Condition`, `Pages`, or `ForEach`, it fires when they actually enter the DOM — useful for lazy data loading when a tab activates or a conditional branch becomes true.

## Keyboard Shortcuts

`key_bindings` maps keyboard shortcuts to actions. When a user presses a matching key combination, the action fires, same as `on_click` or `on_mount`. Keys are standard DOM `KeyboardEvent.key` values, with optional modifier prefixes:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from prefab_ui.actions import SetState, ShowToast
from prefab_ui.rx import Rx

slide = Rx("slide")

with PrefabApp(
    state={"slide": 0},
    key_bindings={
        "ArrowRight": SetState("slide", slide + 1),
        "ArrowLeft": SetState("slide", slide - 1),
        "Shift+?": ShowToast("Help!"),
    },
) as app:
    ...
```

Modifier prefixes are `Ctrl+`, `Shift+`, `Alt+`, and `Meta+` (⌘ on Mac). They combine naturally: `"Ctrl+Shift+S"` matches Ctrl+Shift+S. The key portion uses the standard [KeyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) names: `ArrowRight`, `ArrowLeft`, `Enter`, `Escape`, `Tab`, letter keys, etc.

Key bindings are suppressed when the user is typing in an input, textarea, or select, so shortcuts never interfere with form entry.

### Keyboard Shortcuts Dialog

The `KeyboardShortcutsDialog` helper builds a dialog that lists your shortcuts with styled [Kbd](/components/kbd) key indicators. It returns a `SetState` action you can wire directly into `key_bindings`:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from prefab_ui.shortcuts import KeyboardShortcutsDialog

help_action = KeyboardShortcutsDialog({
    "ArrowRight": "Next slide",
    "ArrowLeft": "Previous slide",
    "Shift+?": "Show shortcuts",
})

with PrefabApp(
    key_bindings={
        "ArrowRight": SetState("slide", slide + 1),
        "ArrowLeft": SetState("slide", slide - 1),
        "Shift+?": help_action,
    },
) as app:
    ...
    # Place the dialog trigger somewhere in your layout
    KeyboardShortcutsDialog({
        "ArrowRight": "Next slide",
        "ArrowLeft": "Previous slide",
        "Shift+?": "Show shortcuts",
    })
```

The dialog binds its open state to a state variable (default `_show_shortcuts`), so the `SetState` action from `key_bindings` opens it programmatically. The trigger button also works for mouse users. No initial state setup is needed; the dialog defaults to closed.

The helper uses the state-controlled [Dialog](/components/dialog#state-controlled-dialog) `name` prop under the hood.

## Stylesheets

Use `stylesheets` for external CSS URLs. They render as `<link>` tags and contribute style origins to `app.csp()`.

Use `css` for inline CSS strings. They render as `<style>` tags and are included in the wire format so JSON-based renderers can apply them.
