# Selmer template conventions

> **Status: STUB — validated in Phase 2.** This file describes the target. The Selmer
> dependency, render helper, and interop bridge are added in Phase 2 (Transaction Edit);
> rewrite this file from the *real, verified* example once that lands, and record each
> converted component in `component-cookbook.md`.

## Why Selmer for interactive components

In Hiccup the same Alpine/HTMX attribute is sometimes a keyword and sometimes a string in
the same file — there's no rule a reader (or an LLM) can rely on:

```clojure
;; All of these appear in one component today:
:x-ref  "input"      "x-ref" "hidden"
:x-model "value.value"   "x-model" "search"
"@keydown.down.prevent.stop" "tippy.show();"   ; handlers MUST be strings
:x-init "..."                                  ; structural attrs are keywords
```

In a Selmer template the same markup is unambiguous plain HTML:

```html
{# templates/components/typeahead.html #}
<div class="relative" x-data="{{ x_data|safe }}" x-model="{{ x_model }}">
  <a class="{{ classes }}" x-ref="input" tabindex="0"
     @keydown.down.prevent.stop="tippy?.show()"
     @keydown.backspace="tippy?.hide(); value = {value:'', label:''}">
    <span x-text="value.label"></span>
  </a>
  ...
</div>
```

Note the `tippy?.` null-guard carried over from the swap doctrine — Selmer doesn't change
the Alpine-survives-swap requirement.

## Render helper + interop bridge (the Phase 2 foundation)

```clojure
(defn render [tpl ctx] (selmer/render-file tpl ctx))
(defn hiccup->html [h] (hiccup/html h))    ; embed hiccup inside selmer via {{ frag|safe }}
;; selmer fragment inside hiccup: [:div (hiccup/raw (render "..." ctx))]
```

The bridge must work **both ways** during the strangler transition: a Hiccup component
renders inside a Selmer template (pass `(hiccup->html h)` into the context, render with
`|safe`), and a Selmer fragment renders inside a Hiccup tree (`(hiccup/raw (render ...))`).
Prove both in Phase 2 before broad use.

## Composition

Selmer composes via `{% include %}` and `{% block %}`. Prefer small per-component
templates that the cookbook references by path. Keep `|safe` to values the server fully
controls (rendered Hiccup, JSON for `x-data`), never raw user input.

## Scope (Open decision 2)

Hybrid: convert interactive/attribute-heavy components first; static markup may stay
Hiccup. Revisit a fuller sweep in Phase 11.

## Attribute-consistency scorecard (heuristic 8)

```bash
grep -cE '"x-[a-z]|"hx-[a-z]|"@' <migrated-template>   # → 0 mixed encodings in Selmer
```
A migrated Selmer template has no mixed `:x-`/`"x-"` encodings because everything is plain
HTML.
