Recipe

htmx

htmx swaps HTML from the server, and every glyphfox format is HTML: inline SVG rendered on the server, <glyph-fox> elements, or data-glyph placeholders.

Render SVG on the server

server.js
import express from 'express';
import { toSvg } from 'glyphfox';

const app = express();
let liked = false;

app.post('/like', (req, res) => {
  liked = !liked;
  const icon = toSvg(liked ? 'heart/solid' : 'heart', { size: 20, animate: 'pop', title: liked ? 'Liked' : 'Like' });
  res.send(`<button hx-post="/like" hx-swap="outerHTML">${icon}</button>`);
});

toSvg returns the icon as markup with every prop, and the animation styles travel inside it, so the swapped fragment plays the pop as soon as it lands. Any Node server or edge function works the same way.

Web components in swapped content

index.html
<script src="https://cdn.jsdelivr.net/npm/glyphfox@1"></script>

<div hx-get="/notifications" hx-trigger="every 30s">
  <glyph-fox name="bell" animate="shake" trigger="state" active></glyph-fox>
</div>

Custom elements upgrade by themselves when htmx inserts them, so fragments can return <glyph-fox> tags. With a swap that keeps elements and updates their attributes, such as the idiomorph extension, a <glyph-fox morph> element animates when the server changes its name.

The data-glyph runtime

index.html
<script type="module">import 'https://cdn.jsdelivr.net/npm/glyphfox@1/dist/runtime/auto.js';</script>

<ul hx-get="/files" hx-trigger="load">
  <li><i data-glyph="file" data-modifier="check"></i> report.pdf</li>
</ul>
app.js
import { replaceGlyphs } from 'glyphfox';

document.body.addEventListener('htmx:afterSwap', (event) => replaceGlyphs(event.detail.target));

The runtime replaces every data-glyph element with inline SVG and keeps watching, so placeholders in swapped content are replaced too. With a bundler, call replaceGlyphs after each swap instead.