Customizable dashboards for PhoenixKit.
Lets users compose dashboard pages from widgets contributed by any
PhoenixKit module. A widget is a self-contained Phoenix.LiveComponent; a
dashboard is a free-form 2D grid of placed widget instances, each with its own
size, position, and settings. Layouts are persisted per user (personal
dashboards) and per system/role (shared dashboards).
Architecture
PhoenixKitDashboards.Widget— the widget type struct + the plain-map provider contract (phoenix_kit_widgets/0).PhoenixKitDashboards.Registry— runtime discovery + cached catalog (the union of every module'sphoenix_kit_widgets/0, including this one's), filtered by module enablement and permissions.PhoenixKitDashboards.Widgets.*— this module's built-in widgets (note, clock, module-stats), exposed viaphoenix_kit_widgets/0like any other provider.PhoenixKitDashboards.Schemas.Dashboard+PhoenixKitDashboards.Dashboards— the dashboard schema (JSONBlayout) and its context. The backing table (phoenix_kit_dashboards) is created by core's versioned migrationV133— modules do no DDL of their own.PhoenixKitDashboards.Web.*— the manage + builder LiveViews.
Exposing widgets from another module
Any module can contribute widgets by defining a zero-arity
phoenix_kit_widgets/0 returning plain maps — no dependency on this package:
def phoenix_kit_widgets do
[%{key: "emails.deliverability", name: "Deliverability",
module_key: "emails", component: PhoenixKitEmails.Widgets.DeliverabilityLive,
default_size: %{w: 6, h: 2}}]
endSee PhoenixKitDashboards.Widget for the full contract.
Summary
Functions
This module's own widgets, exposed through the same phoenix_kit_widgets/0
contract every other module uses (see the "Exposing widgets" section above), so
the Registry discovers them uniformly — the built-ins are a live worked example
of the contract, not a special-cased internal path.
Functions
@spec phoenix_kit_widgets() :: [map()]
This module's own widgets, exposed through the same phoenix_kit_widgets/0
contract every other module uses (see the "Exposing widgets" section above), so
the Registry discovers them uniformly — the built-ins are a live worked example
of the contract, not a special-cased internal path.