FYI.Sink.Boop (FYI v1.1.0)

View Source

Boop sink: a push notification on your phone for every routed event.

Boop is a tiny self-hosted notification inbox. This sink POSTs each event to its /api/v1/events endpoint with the project API key; nothing else is needed.

Configuration

{FYI.Sink.Boop, %{
  url: System.get_env("BOOP_URL"),          # https://boop.example.com
  api_key: System.get_env("BOOP_API_KEY"),  # boop_proj_...
  source: "my_app",                         # optional, shown next to the event
  level: "info",                            # optional default level
  levels: %{"user.*" => "success", "purchase.*" => "success", "*.failed" => "error"},
  dashboard_url: "https://my-app.com/admin/fyi"  # optional: adds an "Open in FYI" button
}}

Options

  • :url (required) - base URL of your Boop server
  • :api_key (required) - a Boop project API key (boop_proj_...)
  • :source - Boop source for every event (default: the FYI app name, downcased, or "fyi")
  • :level - default Boop level: "info", "success", "warning", "error", "critical" (default "info")
  • :levels - map of event-name glob to level, first match wins (same globs as routes)
  • :dashboard_url - where the FYI inbox is mounted; each push gets an "Open in FYI" button that opens the event
  • :actions - extra buttons: a list of %{label, url} or fn event -> [...] end. Boop shows at most three in total
  • :req_options - keyword merged into the request (e.g. plug: {Req.Test, FYI.Sink.Boop} in tests)

What the push looks like

The title is the event name made readable ("User created"), prefixed with the emoji FYI picks for it; the body is the payload on one line (email: x · method: google). The event name is the Boop fingerprint, so repeats of the same event group into one inbox row with a count. The full payload, tags, actor and source travel in data.