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

What a component should SAY the moment it is placed.

Dropping `chelekom-banner` used to put `<.component component_name="chelekom-banner" … />` on the
canvas — a component with nothing inside it. A banner with no message is a blank strip, an alert
with no text is an empty rounded box, and a card with no content is a border. The author drags
something, sees almost nothing, and has to open the inspector to discover what they placed.

So a placed component arrives furnished. The text is deliberately ordinary and obviously
replaceable — the point is that the shape is visible and the words are already selected for
editing, which is what a page builder is for.

## Why a table and not the component's own examples

The examples are better copy, but curating them costs a parse of every example the component
ships — 7.8 seconds across the palette, to answer a question asked once per drag. The palette
builds its drop template for all 177 entries on every render, so this has to be a lookup.

## What gets nothing

A component with no `inner_block` has nowhere to put content, and one that composes its own
children — a table row, an accordion — would only be given text in the wrong place. Those stay
self-closing, which is what `MishkaCmsCore.Builder.PaletteEntry.template/2` emits.

# `attrs`

```elixir
@spec attrs(map()) :: %{optional(String.t()) =&gt; String.t()}
```

The attributes a freshly dropped component arrives SET to, or `%{}` when it declares none.

A body says what goes inside; this says what the thing itself is. Only a declaration — there is
nothing to infer here, and a component that says nothing keeps its own defaults.

# `body`

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

The markup to place inside a freshly dropped component, or `""` when it takes no content.

Accepts anything shaped like a palette entry — the component's `name` and its `slots` are all this
reads.

# `furnished?`

```elixir
@spec furnished?(map()) :: boolean()
```

Whether a freshly dropped component arrives with something to look at — content between its tags,
sample slot entries, or both.

The predicate the kit-wide contract is written against: `chelekom-accordion` has nothing to say
between its tags and is furnished all the same, by two `<:item>` entries.

# `slot_samples`

```elixir
@spec slot_samples(map()) :: [{String.t(), map(), String.t()}]
```

Sample entries for a component's named slots: `[{slot_name, attrs, body}]`.

The COPY only — writing it as HEEx belongs to `MishkaCmsCore.Builder.PaletteEntry`, which already
owns how a slot's own required attributes are seeded. `attrs` carries the values the sample needs
to make sense of itself: an `<:option>` without a `value` is a choice that cannot be chosen.

Entries are dropped for slots the component does not declare, so a composite's `<:header>` is only
written where there is one to write.

# `takes_content?`

```elixir
@spec takes_content?(map()) :: boolean()
```

Whether the component has somewhere to put content at all.

`inner_block` is the only slot an author's text can land in. A component without one is not
incomplete — a spinner has nothing to say — so it is left alone rather than given a body that
Phoenix would refuse.

---

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