# `SquatchMail.Web.AssetController`
[🔗](https://github.com/Axio-Intelligence/Squatch-Mail/blob/v0.1.0/lib/squatch_mail/web/controllers/asset_controller.ex#L1)

Serves SquatchMail's self-contained CSS/JS bundle (plus the logo PNG) with
content-hashed, immutable-cached paths.

This follows the same pattern as Phoenix LiveDashboard's and Oban Web's
asset plugs: the built `priv/static/squatch_mail.{css,js}` files (and the
committed `squatch_mail_logo.png`) are read
once at compile time into module attributes, an MD5 hash of each is
computed as a compile-time constant, and that hash is embedded in the
asset's URL (`/assets/css-<md5>`, `/assets/js-<md5>`). Because the path
itself changes whenever the content changes, the response can be marked
`cache-control: public, max-age=31536000, immutable` — the browser never
needs to revalidate, and a fresh deploy naturally busts the cache by
generating a new path.

This is a plain `Plug`, not a `Phoenix.Controller` — serving two static
blobs doesn't need view/format negotiation, and Phoenix routers dispatch to
either kind of module identically (`get "/path", Module, :action`).

The `:md5` route parameter is not read by this plug; it exists only so a
new build produces a new URL. The real, current hash used to build links
is `asset_path/1`, computed from the actual file contents.

## Missing build

`priv/static/squatch_mail.{css,js}` are generated by `mix assets.build`
(see the alias in `mix.exs`) and are committed so hosts installing the hex
package get them for free — they should always be present in a checkout of
this repo or a published package. But reading them with `File.read!/1`
directly in module attributes would mean a missing build breaks
`mix compile` for the *entire* dependent application, not just the
dashboard — an unacceptable failure mode for a library. Instead, this
module reads with `File.read/2` at compile time and tolerates a `nil`
result; `asset_path/1` and `call/2` both raise a descriptive
`RuntimeError` only when the missing asset is actually requested, pointing
at `mix assets.build` as the fix.

# `asset_path`

```elixir
@spec asset_path(:css | :js | :logo) :: String.t()
```

Returns the current asset path segment for `asset` (`:css`, `:js`, or
`:logo`), e.g. `"css-3f9c2a..."`. Used by `SquatchMail.Web.Layouts` to
build the `<link>`/`<script>`/`<img>` src.

Raises if the asset hasn't been built yet — run `mix assets.build`.

---

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