# `MishkaCmsCoreWeb.Live.Admin.Builder.BuilderLive`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core_web/live/admin/builder/builder_live.ex#L5)

The page builder's chrome: top bar, the two side panels, the crumb bar, the code drawer and the
overlays — everything around the canvas, which is its own LiveView inside an iframe
(`MishkaCmsCoreWeb.Live.Admin.Builder.CanvasLive`).

Both LiveViews share one `MishkaCmsCore.Runtime.PageBuilder.EditorSession`, keyed by a token in
the canvas URL, and stay in step over that session's PubSub topic. This module owns the *editing
context* — what is selected, which breakpoint is being edited, what the palette shows — and the
canvas owns the document's pixels.

## Sections

One editor, four resources: `page`, `layout`, `error_page` and `component`. They differ in which
Ash actions load and save them and in a handful of panels; everything else — tree, canvas,
inspector, history — is identical, which is the point of modelling the document as a tree rather
than as four bespoke forms.

## Extension points

Every panel region is a `MishkaCmsCore.Builder.Events` registry, seeded with the core's own
entries. The rails, the inspector's sections, the command palette and the canvas toolbar are all
collected the same way a plugin's contribution would be, so the seam is exercised on every mount
rather than being a promise.

# `devices`

The device options the top bar offers, with their canvas widths.

# `examples_entry`

The palette entry the examples modal is open for, or `nil`.

Exposed so the panel components can read it without threading another assign through every render.

# `frame_widths`

The three frame widths the all-breakpoints view renders side by side.

# `handle_event`

Drops the selection, so the code pane goes back to the whole document.

The same two calls `shortcut("escape", …)` makes, reachable by clicking rather than only by a key
nothing advertises — the code pane's scope chip is the button. A picked component is dropped with
it: the author asking for the whole document back is not mid-placement.

# `share_url`

```elixir
@spec share_url(map()) :: String.t()
```

The URL that invites someone else into THIS editing session — the same page plus the session
token, so both browsers drive one document and each sees the other in the avatar row.

It names the status as well, for the one section that has several. The token answers which entry
is open only while the session lives, and a link pasted into a chat is followed later — without
the status that reader lands on the 404 when the invitation was written on the 500. The two agree
by construction, which is what `resume_or_open/5` asks of an address naming both.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
