# `MishkaCmsCore.Runtime.PageBuilder.PageStarter`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/page_builder/page_starter.ex#L5)

How a blank document begins — the few shapes offered on a page with nothing on it yet.

## Why this exists

A page had to arrive with markup already in it. The "Add Page" form demanded a template before it
would save, so the only way to reach the visual editor was to first write HEEx by hand — which is
the one thing the visual editor is for not having to do. `blank/0` is what a page is created with
instead: one centred container, wide enough to be a target, empty enough to be nothing.

From there the canvas offers these structures. Picking one inserts it and the author is building.

## Why it is not called a layout

Runtime already has Layouts: templates that wrap a page and declare which components they use.
Borrowing the word here would mean two unrelated things called the same thing in the same editor.
A **starter** is the first thing in an empty document and is thrown away the moment it is edited;
a layout outlives every page that uses it.

## Why the structures are plain HTML

Same reason as `MishkaCmsCore.Runtime.PageBuilder.Blocks`: a starter that reached for a kit
component would fail on an install without that kit. Every structure here is `div` and utility
classes, so it renders anywhere and every node inside it is an ordinary element the Inspector
already knows how to style.

These are deliberately emptier than Blocks. A block is a finished section with real copy in it; a
starter is scaffolding — columns to drop things into, no words to delete first.

# `structure`

```elixir
@type structure() :: %{
  id: String.t(),
  title: String.t(),
  description: String.t(),
  columns: pos_integer(),
  template: String.t()
}
```

# `all`

```elixir
@spec all() :: [structure()]
```

Every starter structure, in the order the chooser lists them.

# `blank`

```elixir
@spec blank(:page | :layout) :: String.t()
```

The markup a document is created with when the author gave none.

One centred container — somewhere to put the first thing, and nothing else. A `:layout` gets the
same container with `@inner_content` inside it, because a layout that does not render the page it
wraps is not empty, it is broken.

# `empty?`

```elixir
@spec empty?(MishkaCmsCore.Runtime.PageBuilder.Tree.t() | nil) :: boolean()
```

Whether a document is empty enough to be offered a starter.

Two ways to be empty, and both have to count:

  * nothing at all — a document whose content was removed;
  * ONE container with nothing in it — which is what a page created with no markup arrives as,
    because `pages.template` is NOT NULL with a length check and a truly empty string would fail
    at the database. A page whose only content is the container it was born with has not been
    started, whatever the row says.

A page with anything else on it is a page someone is already working on, and dropping a chooser
over it would be an interruption rather than a help.

# `fetch`

```elixir
@spec fetch(String.t()) :: structure() | nil
```

One structure by id, or `nil` — an unknown id is a no-op, never a crash.

# `scratch`

```elixir
@spec scratch() :: String.t()
```

The one element a page started from scratch begins with.

---

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