Stop Hardcoding HTML for Every Image — Use Template Variables Instead

Most developers generate images like this:

const html = `
  <div style="...">
    <h1>${post.title}</h1>
    <p>${post.author} · ${post.date}</p>
  </div>
`;

This works — until it doesn’t.

  • Special characters break the HTML (&, <, > in titles)
  • The template grows and the string becomes harder to maintain
  • Reusing the same template across environments gets messy
  • No clear separation between design and data

A cleaner approach: template variables

Instead of interpolating values into HTML strings, pass them separately:

const response = await fetch('https://renderpix.dev/v1/render', {
  method: 'POST',
  headers: {
    'X-API-Key': 'rpx_your_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    html: `
      <div style="width:1200px;height:630px;background:#0f172a;
        display:flex;flex-direction:column;justify-content:center;
        padding:80px;font-family:sans-serif">
        <div style="color:#22d3ee;font-size:18px">{{domain}}</div>
        <div style="color:white;font-size:52px;font-weight:bold;line-height:1.2">
          {{title}}
        </div>
        <div style="color:#94a3b8;font-size:20px;margin-top:24px">
          {{author}} · {{date}}
        </div>
      </div>
    `,
    vars: {
      title: post.title,
      author: post.author,
      date: post.publishedAt,
      domain: 'myblog.com'
    },
    width: 1200,
    height: 630,
    format: 'png'
  })
});

The HTML template stays clean. Values are injected at render time — no string interpolation, no escaping issues.

How it works

RenderPix does a find-and-replace before rendering the page:

  • {{title}} → value of vars.title
  • {{author}} → value of vars.author
  • Missing key? The placeholder stays as-is — no errors thrown.

This means you can store your HTML template as a file, an environment variable, or a database field, and just swap the vars object per request.

The real power: combine with batch rendering

Template variables get interesting when you need multiple images at once.

One HTML template + N different vars objects = N unique images, one API request:

const OG_TEMPLATE = `
  <div style="width:1200px;height:630px;background:#0f172a;
    display:flex;flex-direction:column;justify-content:center;padding:80px">
    <div style="color:#22d3ee;font-size:18px;margin-bottom:16px">{{domain}}</div>
    <div style="color:white;font-size:52px;font-weight:bold;line-height:1.2">{{title}}</div>
    <div style="color:#94a3b8;font-size:20px;margin-top:24px">{{author}} · {{date}}</div>
  </div>
`;

const response = await fetch('https://renderpix.dev/v1/batch', {
  method: 'POST',
  headers: {
    'X-API-Key': 'rpx_your_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    items: blogPosts.map(post => ({
      html: OG_TEMPLATE,
      vars: {
        title: post.title,
        author: post.author,
        date: post.date,
        domain: 'myblog.com'
      },
      width: 1200,
      height: 630,
      format: 'png'
    }))
  })
});

const { results } = await response.json();
// results[0].url, results[1].url, ...
// 50 unique OG images. One request.

Without template variables, this would be 50 different HTML strings to maintain. With them, it’s one.

Use cases

This pattern works well anywhere you have a fixed design and variable data:

  • OG images — one template per blog, dynamic per post
  • Certificates — one template per course, dynamic per student
  • Invoices — one template per company, dynamic per transaction
  • Social cards — one brand template, different content daily

Available on all plans

Template variables work on free, starter, pro, and scale — no upgrade needed to try it.

If you want to test it: renderpix.dev gives you 100 free renders/month, no credit card required.

Leave a Reply