# `MishkaCmsCore.Sidebar.Item`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/sidebar.ex#L181)

One link in the admin sidebar.

`path` is absolute (`/admin/dashboard/blog`) because that is what the browser navigates to —
extension route tuples are scope-relative, so a menu item spells the prefix out.

`permissions` decides who SEES this link: holding ANY entry grants — a name, or
`{:under, prefix}` for anyone holding anything under `prefix` — and `[]` means "any signed-in
admin". It does not decide who may open the page — the LiveView behind the link declares that
for itself.

`group` names the `MishkaCmsCore.Sidebar.Group` this link belongs under, or `nil` for a top-level
link such as Home. `position` is `:main` or `:footer`.

`module` is the LiveView this entry gates — the module Phoenix mounted, which is how
`MishkaCmsCore.Sidebar.PageGuard` finds an entry. It is deliberately not the `path`: a path is a
string the client spells, a module is what the router already resolved.

`nav: false` declares a PAGE that is not a link. An extension usually shows one entry but owns
many pages — the blog shows "Blog" and owns nine — and those pages do not share one answer to
"who may open this": Comments is `admin:dashboard:blog:comment`, Posts is
`admin:dashboard:blog:post`. Declaring each page
here, hidden from the nav, is what lets them be gated apart while the sidebar still renders the
single link it renders today.

See `MishkaCmsCore.Sidebar` for the event contract.

# `t`

```elixir
@type t() :: %MishkaCmsCore.Sidebar.Item{
  credit_name: String.t() | nil,
  credit_url: String.t() | nil,
  extension: atom() | nil,
  group: String.t() | nil,
  icon: String.t() | nil,
  key: String.t(),
  label: String.t(),
  module: atom() | nil,
  nav: boolean() | nil,
  order: integer() | nil,
  path: String.t(),
  permissions: list() | nil,
  position: atom() | nil
}
```

# `builder`

# `enforce_keys`

# `enforce_keys`

# `example`

A sample %MishkaCmsCore.Sidebar.Item{} populated from defaults + type-based fallbacks.

# `keys`

# `keys`

# `new!`

```elixir
@spec new!(map()) :: t()
```

Builds an item, raising on an invalid declaration.

Menus are declared in module attributes so a descriptor is built once at compile time rather than
on every admin mount; that also means a malformed item fails the build instead of a page render.

---

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