Dev-only Plug. Mount it in your endpoint, guarded so it never reaches prod:
if Mix.env() == :dev do
plug Annotai
endFor requests under /annotai/* it serves the widget asset, the annotation API,
and the MCP endpoint (via Annotai.Router). For every other HTML response it
injects a single <script src="/annotai/app.js"> before </body> — the only
thing added to the host page; the entire widget UI is built client-side in a
Shadow DOM root.
Place plug Annotai before Plug.Parsers (the MCP endpoint needs the raw body)
and before the code-reloading block. mix annotai.install does this for you.
Disabling
Annotai is on by default. Set config :annotai, enabled: false to make the plug
fully inert — no widget injection and no /annotai/* routes. To control it via an
environment variable instead, drive the flag from one in the host app's config:
# config/dev.exs
config :annotai, enabled: System.get_env("DISABLE_ANNOTAI") != "true"Then run with DISABLE_ANNOTAI=true mix phx.server and Annotai disappears.
Summary
Functions
Whether Annotai is active. Controlled by config :annotai, enabled: bool
(default true). When false, call/2 returns the conn untouched, so the
widget is never injected and /annotai/* is never served. See the module doc
for the per-developer opt-out pattern.
The installed Annotai package version, as a string (e.g. "0.1.0"). Sourced
from the loaded application spec so it tracks mix.exs without duplication.
Functions
@spec enabled?() :: boolean()
Whether Annotai is active. Controlled by config :annotai, enabled: bool
(default true). When false, call/2 returns the conn untouched, so the
widget is never injected and /annotai/* is never served. See the module doc
for the per-developer opt-out pattern.
@spec version() :: String.t()
The installed Annotai package version, as a string (e.g. "0.1.0"). Sourced
from the loaded application spec so it tracks mix.exs without duplication.