🤖 FIGH(7) Overview FIGH(7)

NAME

figh — figh interpolates guarded HTML

The name is a recursive acronym. It is the only recursion in the language. See figh(5) for the complete manual.

WHAT IT IS

figh is a template language for templates you didn't write: a customer uploads a theme, and it renders on your infrastructure, next to everybody else's data. It looks like the templating you already know —

<h1>{{ event.name }}</h1>

<figh-if test="tickets">
  <ul>
    <figh-for each="t in tickets">
      <li>{{ t.holder | default: 'unclaimed' }}
          — {{ t.price | money: 'eur' }}</li>
    </figh-for>
  </ul>
<figh-else/>
  <p>{{ 'public.event.sold_out' | t }}</p>
</figh-if>

figh's own surface is lit; the host HTML is dim. That is the whole parser story: figh scans for {{ }} and <figh-…> and copies everything else through untouched. It never parses your markup.

WHY YOU'D USE IT

Because the author of the template is not the operator of the server. Every design decision follows from that one assumption: figh is defined by what it refuses to do:

  • Emit raw HTML by accident {{ }} always escapes, with no off switch. The only unescaped output is one greppable element that cannot hide inside an attribute.
  • Run forever no while, no user functions, no recursion; the include graph is static and cycles are a compile error. Termination is grammar, not a timeout.
  • Reach anything no filesystem, no network, no clock, no randomness, no host objects. A template is a pure function of the data you hand it.
  • Disagree with itself implemented twice, in Go and JavaScript, with a golden corpus asserting byte-identical output, error columns included. The browser preview cannot drift from production.

HOW TO USE IT

Bind plain data, hand figh a loader, render inside the rails. The same template, the same data and the same output on both sides:

server — Go
data, err := figh.BindMap(map[string]any{
  "event": map[string]any{
    "name": "Vector Fest",
  },
  "tickets": []map[string]any{
    {
      "holder": "Ada",
      "price":  int64(24900),
    },
  },
})

env := &figh.Env{
  Data: data, Locale: "en",
}
out, err := figh.RenderGuarded(
  "event.figh", loader, env,
  figh.Limits{})
browser — JavaScript
const env = {
  data: {
    event: { name: "Vector Fest" },
    tickets: [
      { holder: "Ada", price: 24900 },
    ],
  },
  locale: "en",
};

const res = figh.renderToResult(
  "event.figh", loader, env);
if (res.ok) preview.srcdoc = res.output;

Everything else (all eight directives, the expression grammar, all fifteen filters, the value model, errors, limits, conformance) is in the manual:

figh(5) — the complete manual →

SEE ALSO

figh(5) — the complete language reference.
fighdev/figh — source and extraction notes. figh runs in production at Tito; extraction into a standalone module is in progress, so treat the repo as where the work happens, not yet a dependency you can add.

🤖 Written by an LLM (Claude), on the ideas, instruction, and editing of humans; see factor X.