Layouts shared by extension LiveViews.
Mirrors the host app's MishkaCmsWeb.Layouts module: one module holds the
layout templates (auto-embedded from layouts/*.html.heex) and any helper
components that belong to the chrome.
Wiring
Extension LiveViews opt in via MishkaCmsCore.ExtensionLiveView, which does
use Phoenix.LiveView, layout: {MishkaCmsCore.Layouts, :app}. The result:
every extension admin page is automatically wrapped by app.html.heex and
gets the flash group without each template repeating it.
Why not reuse MishkaCmsWeb.Layouts?
Extensions compile before MishkaCmsWeb, so calling
MishkaCmsWeb.Layouts.flash_group/1 from an extension template raises an
"undefined" warning at compile time. This module is the extension-side
counterpart and owns the flash chrome for everything under
MishkaCmsCore.ExtensionLiveView.
Summary
Functions
The years the footer's copyright line covers, from 2026 up to today's year: "2026" during
2026, "2026-2027" in 2027, and so on.
Renders both :info and :error flashes from the @flash map.
The line under every admin page: "© <years> · Powered by <name>", where the name links to the product's own page.
The admin sidebar — logo, collapsible nav groups, and the active item highlighted from
@current_path (set by MishkaCmsCore.Layouts.Nav). Groups collapse client-side via JS.toggle.
The admin topbar — search, theme toggle, notifications, and the user's menu: Account settings, the language the dashboard is read in, and Sign out.
Functions
The years the footer's copyright line covers, from 2026 up to today's year: "2026" during
2026, "2026-2027" in 2027, and so on.
Renders both :info and :error flashes from the @flash map.
Styled with classes rather than style attributes. Every surface that renders this — the admin
chrome via app.html.heex and the page builder shell — sets admin_css, so the compiled admin
stylesheet is always there to carry them; the canvas iframe, the one admin surface without it,
mounts with layout: false and never draws a flash. Keeping the colours in classes is what lets
the policy in MishkaCmsCore.Runtime.Plugs.SecurityHeaders close style-src-attr, which no nonce
can ever reopen for an attribute.
<.flash_group flash={@flash} />Whatever the inner block holds is stacked under the notices — the admin chrome puts
MishkaCmsCoreWeb.Live.Admin.Components.TranslationsRefusal there.
Attributes
flash(:map) (required)
Slots
inner_block
The admin sidebar — logo, collapsible nav groups, and the active item highlighted from
@current_path (set by MishkaCmsCore.Layouts.Nav). Groups collapse client-side via JS.toggle.
The nav itself is data, not markup: MishkaCmsCore.Sidebar.menu/1 collects it from every
extension's "sidebar:menus" plugin, drops what @current_user may not see, and orders it from
Settings. This component only paints what it is handed, so an empty section is one that was
filtered away rather than one that has to be spelled out here. version is @sidebar_version: the
sidebar is drawn again each time it changes.
Attributes
current_path(:string) - Defaults tonil.current_user(:any) - Defaults tonil.version(:integer) - Defaults to0.
The admin topbar — search, theme toggle, notifications, and the user's menu: Account settings, the language the dashboard is read in, and Sign out.
language is the admin's language and languages the ones the menu offers
(MishkaCmsCore.Layouts.Nav assigns both); picking one sends PUT /admin/language with
current_path to come back to. Two are listed, the admin's own among them, and the rest behind
"Show more".
Attributes
current_user(:any) - Defaults tonil.notification_count(:integer) - Defaults to0.notification_recent(:list) - Defaults to[].current_path(:string) - Defaults tonil.language(:string) - Defaults to"en".languages(:list) - Defaults to[].sign_out(:string) - Defaults to"/auth/sign-out".