# `PhoenixKitOG`
[🔗](https://github.com/BeamLabEU/phoenix_kit_og/blob/0.4.0/lib/phoenix_kit_og.ex#L1)

OpenGraph template + hierarchical assignment plugin for PhoenixKit.

See `AGENTS.md` for the high-level architecture. The integration seam
with `phoenix_kit_publishing` is `refine_og/4` — publishing's
`Web.Controller.build_og_data/4` calls it when this module is loaded.

## Module callbacks

Implements `PhoenixKit.Module` so the host app's discovery picks this
up automatically — no config line. Settings key: `phoenix_kit_og_enabled`.

# `clear_assignment`

# `create_template`

# `delete_template`

# `expected_schema`

The manifest of this module's tables, for `mix phoenix_kit.repair` and
`mix phoenix_kit.doctor`; see `PhoenixKitOG.ExpectedSchema`.

# `get_template`

# `list_assignments`

# `list_templates`

# `og_image_url`

```elixir
@spec og_image_url(
  String.t(),
  [{String.t(), binary() | nil}],
  map(),
  Plug.Conn.t() | nil,
  keyword()
) ::
  {:ok, String.t()} | :none
```

Renders the OG image for ANY module's resource, or `:none`.

The publishing-shaped `refine_og/4` above is one consumer of this; it is
not the only kind there can be. A module supplies its own scope
hierarchy — most specific first, `{"default", nil}` trailing — and gets
back an absolute URL to a cached PNG, or `:none` when no template is
assigned, the module is off, or rendering fails.

    PhoenixKitOG.og_image_url("projects", [
      {"project", project.uuid},
      {"default", nil}
    ], project, conn)

Never raises: an OG image is decoration, and decoration must not be able
to take down the page it decorates.

# `preview_og_image_url`

```elixir
@spec preview_og_image_url(map(), Plug.Conn.t() | nil, String.t() | nil) ::
  {:ok, String.t()} | :none
```

Returns `{:ok, url}` with the OG-plugin-generated image for a post,
or `:none` when no template resolves. Used by publishing's editor to
render a "what the plugin will produce" preview alongside the manual
OG-image override.

# `refine_og`

```elixir
@spec refine_og(map(), Plug.Conn.t() | nil, map(), String.t() | nil) :: map()
```

The seam `phoenix_kit_publishing` calls. Walks the consumer's scope
hierarchy, picks the winning template, renders it to a PNG, and swaps
the rendered image URL into `og[:image]` (also setting `:image_width`,
`:image_height`, and `:image_type`).

Returns `og` unchanged when the module is disabled, no template
resolves, or rendering fails — so the consumer keeps its own per-post
OG image (featured image + override). Any raised exception is
swallowed the same way: OG resolution must never crash a public post
page render.

The seam contract: return a map carrying at least the keys the
consumer passed in (`:title`, `:description`, `:image`, `:url`,
`:locale`, `:type`); this function may additionally set
`:image_width`, `:image_height`, and `:image_type`.

# `resolve_template`

# `set_assignment`

# `update_template`

---

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