This guide is the canonical adoption path for composing Chimeway with the optional chimeway_inbox package. Follow it when you want one credible vertical slice: add Chimeway and the inbox package, configure recipient auth, mount the bell dropdown LiveView, and verify list → mark_read → badge updates.
There is no separate inbox blueprint recipe in v1.9 — this guide owns the end-to-end path from dependency to verification.
Responsibility split (SEED-003)
Chimeway orchestrates the when and why: durable notification lifecycle, suppression and preference gates, idempotency, scheduling, and operator traces you can search at /admin/chimeway via chimeway_admin.
The host owns end-user identity and styling: session → recipient identity resolution through ChimewayInbox.Auth, CSS for data-cw-inbox-* hooks, and optional headless inbox calls via public Chimeway.* delegates.
Product boundary: chimeway_inbox is a mountable LiveView package — not a Chimeway.Adapter seam. Operator admin (chimeway_admin) and end-user bell UI (chimeway_inbox) are separate surfaces with distinct auth behaviours.
1. Dependencies
chimeway_inbox is an in-repo preview/path package: it lives in the Chimeway monorepo and is not published on Hex yet. Add Chimeway and chimeway_inbox to your host mix.exs, keeping chimeway_inbox as a path dependency for repository/demo usage:
def deps do
[
{:chimeway, "~> 1.0"},
{:chimeway_inbox, path: "../chimeway_inbox"}
]
endKeep the {:chimeway_inbox, path: "../chimeway_inbox"} path dependency for repository/demo usage until an explicit package-promotion milestone defines package metadata, SemVer policy, publish automation, and a clean install smoke. Both packages live in the Chimeway monorepo today — no sibling checkout is required (unlike Accrue integration).
Then fetch dependencies:
mix deps.get
2. Database / migrations
Chimeway stores the durable lifecycle spine (event → notification → delivery → attempt) in your database. Generate and run Chimeway migrations:
mix chimeway.gen.migrations
mix ecto.migrate
For Chimeway install depth — repo config, supervisor setup, and migration idempotency — see Installation.
The chimeway_inbox package has no separate schema — it reads notification rows through Chimeway's headless API. No Accrue-style sibling migrations are required.
3. Runtime config
Register your host auth module for recipient resolution:
config :chimeway_inbox, auth_module: MyApp.InboxAuthReplace MyApp.InboxAuth with a module that implements ChimewayInbox.Auth. The package invokes auth_module on every LiveView mount to resolve the current recipient identity.
For the full Chimeway runtime setup (installer repo, Chimeway.Repo, supervisor), see Installation §3–§4.
4. Auth behaviour
Implement ChimewayInbox.Auth to map host session (or connection assigns) to a Chimeway recipient identity string:
defmodule MyApp.InboxAuth do
@behaviour ChimewayInbox.Auth
@impl true
def current_recipient(session, _context) do
with email when is_binary(email) and email != "" <- session["current_user_email"] do
{:ok, "user:#{email}"}
else
_ -> {:error, :unauthorized}
end
end
endThe @callback current_recipient/2 receives the Phoenix session map and a context keyword list. Return {:ok, recipient_identity} on success or {:error, :unauthorized} when the user is not signed in.
Do not reuse operator admin identity ("demo:operator") for end-user inbox — that is ChimewayAdmin.Auth territory. End-user bell UI resolves per-user identities such as "user:alex@teampulse.test".
Runnable reference: DemoHost.InboxAuth in the demo host reads "demo_user_email" from the session and maps via DemoHost.Seeds.recipient_identity/1.
5. Router mount
Mount inbox routes in a browser scope, matching the package router moduledoc:
# lib/my_app_web/router.ex
scope "/inbox" do
pipe_through [:browser]
import ChimewayInbox.Router
chimeway_inbox_routes()
endThe macro registers a LiveView session with ChimewayInbox.LiveAuth on_mount and serves ChimewayInbox.Live.BellDropdownLive at /inbox (scope path + /).
Runnable reference: examples/chimeway_demo_host/lib/demo_host_web/router.ex mounts under /inbox with chimeway_inbox_routes/0.
6. Bell UI surface
The package ships BellDropdownLive — an unstyled bell dropdown with semantic data-cw-inbox-* hooks for host CSS:
| Hook | Purpose |
|---|---|
data-cw-inbox-bell | Bell trigger button |
data-cw-inbox-badge | Unread count badge (hidden when zero) |
data-cw-inbox-items | Notification list container (ul#chimeway-inbox-items) |
Contractual LiveView events:
| Event | Effect |
|---|---|
toggle_panel | Open/close dropdown; update aria-expanded |
mark_read | Chimeway.mark_read/3 on item; refresh count and row |
mark_all_read | Batch mark visible unread items |
load_more | Next page via paginated Chimeway.list_for_recipient/2 |
Deferred in v1.9: mark_seen is not wired in BellDropdownLive — hosts call Chimeway.mark_seen/3 via the headless API when seen-state matters for workflow signals (see Mention escalation for cancel_signals on chimeway.notification.read).
Wrap the root element with .chimeway-inbox and style via host CSS using the hooks above. The package does not ship Tailwind or shadcn — hosts own visual design.
7. Headless API
When building custom inbox UI or calling lifecycle methods outside the bell dropdown, use public Chimeway delegates only — do not call internal inbox implementation modules directly:
# Unread badge count
Chimeway.unread_count("user:alex@teampulse.test")
# Paginated list (cursor/limit opts per API docs)
Chimeway.list_for_recipient("user:alex@teampulse.test", limit: 20)
# Mark read (emits chimeway.notification.read signal on first transition)
Chimeway.mark_read(notification_id, "user:alex@teampulse.test")
# Mark seen (headless — not exposed in bell UI v1.9)
Chimeway.mark_seen(notification_id, "user:alex@teampulse.test")These delegates wrap the durable inbox lifecycle spine — read/seen transitions emit signals that workflow steps can listen for via cancel_signals.
8. Verification
After wiring dependencies, config, auth, and router mount, run the named proof command:
mix verify.inbox --warnings-as-errors
This exercises the chimeway_inbox package test suite and the DEMO-08 demo host proof lane (--only inbox). No sibling repo checkout is required.
Seed the demo host inbox scenario:
DemoHost.Seeds.seed_inbox/0Then visit /inbox in the demo host (session must include "demo_user_email") to inspect the bell badge, open the dropdown, and mark notifications read.
The selective proof module DemoHostWeb.InboxBellProofTest is tagged @moduletag :inbox — it asserts list → phx-click="mark_read" → badge count update and Chimeway.mark_seen/3 via the headless API. Journey suite tests keep default Logger adapter isolation (D-06).
Search /admin/chimeway by recipient identity to inspect delivery attempts for seeded notifications alongside operator traces.
Related guides
- Golden Path — Chimeway-only first integration
- Getting Started — inbox lifecycle overview
- Mention escalation — workflow recipe with
mark_read/cancel_signals - Mailglass Integration Guide — optional email delivery for the same notifiers
- Accrue Dunning Integration Guide — billing workflow vertical slice
- Installation — Chimeway install and migration depth