Rendering HTML¶
A payload can render itself to HTML. This is the fastest way to get SEO tags
into a <head> block, and it is safe by construction: user data is escaped,
and the JSON-LD script is escaped so a value cannot break out of the tag.
Full head block¶
Output:
<title>Introducing easeo - Example</title>
<meta name="description" content="Deterministic SEO payloads for content platforms.">
<link rel="canonical" href="https://example.com/blog/introducing-easeo">
<meta name="robots" content="index,follow">
<meta property="og:type" content="article">
<meta property="og:title" content="Introducing easeo - Example">
...
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
...
}
</script>
Escape before injecting
render_html() returns an HTML string. In a template engine, mark it as
safe (Jinja2 |safe, Django mark_safe, Svelte {@html}) only because
the payload has already escaped the values it renders. Do not
hand-interpolate raw entity fields into your own <head>.
Granular rendering¶
When you need to place sections separately, render them individually.
| Python | JavaScript | Output |
|---|---|---|
render_html() |
renderHtml() |
full <head> block |
render_opengraph() |
renderOpengraph() |
og:* tags only |
render_twitter() |
renderTwitter() |
twitter:* tags only |
render_jsonld() |
renderJsonld() |
JSON-LD <script> only |
Using it in a template¶
Why rendering lives in the core¶
The HTML is generated by the Rust core, not by a template. That means the same payload produces the same markup in Python and JavaScript, and the escaping rules are identical everywhere. See Payload Model for the exact tag order.
Recap¶
render_html()produces a complete, escaped<head>block.- Granular renderers are available for custom layouts.
- Framework adapters call these for you.
Next: Contracts.