Dynamically generated thumbnails!
Thats right, its a blog update.
I now generate og/meta images using satori + Resvg based on a html template, in node!
Setup
(this is using ESM, not commonjs - I recently ported my project to ESM as part of this so thought i should mention)
install the modules
npm i satori npm i satori-html npm i @resvg/resvg-js
we create our main file and import our modules
import satori from "satori"; import { html } from "satori-html"; import { Resvg } from "@resvg/resvg-js"; import {fileURLToPath} from 'url'; import path from 'path';
basically, I take a template from a html template existing in the filesystem, and replace certain tags.
make template.html in the root of your project (or wherever you want it- really)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { width: 1200px; height: 628px; display: flex; align-items: center; justify-content: center; background-color: black; background-image: radial-gradient(circle, #ffffff 1px, black 1px); background-size: 40px 40px; color: white; font-family: sans-serif; margin: 0 auto; } .container { display: flex; width: 100%; height: 100%; padding: 50px; } .container img { width: 500px; height: 500px; flex-shrink: 0; } .text { display: flex; flex-direction: column; padding-left: 50px; flex-grow: 1; justify-content: center; } .text h1 { font-size: 48px; margin-bottom: 20px; } .text p { font-size: 24px; } </style> </head> <body> <div class="container"> <img src="https://cataas.com/cat?type=square" alt="Random Cat"> <div class="text"> <h1>{{title}}</h1> <hr> <p>{{headline}}</p> </div> </div> </body> </html>
Fonts: you need a font to render text. I used Victor Mono, but as long as its a .ttf or .otf it should work
and finally, some code in our main file.
const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); async function generateImage(title, headline){ const templatePath = path.join(__dirname, 'template.html'); let template = await fs.readFile(templatePath, 'utf8'); template = template .replaceAll('{{title}}', title) .replaceAll('{{headline}}', headline) const markup = html(template); const fontData = await fs.readFile( "VictorMono-Regular.ttf" ); const svg = await satori(markup, { width: 1200, height: 628, fonts: [ { name: "Arial", data: fontData, weight: "auto", style: "normal", }, ], }); const resvg = new Resvg(svg, { background: "rgba(255, 255, 255, 1)", }); const pngData = resvg.render(); const pngBuffer = pngData.asPng(); fs.writeFile("./generated/" + title + ".png", pngBuffer) }
finally, we can generate images with a simple function call
generateImage('awesome', 'sauce');
Conclusion
Satori + resvg is a powerful combination, with the code I provided, you should be able to make any type of image you want from html!
I really need to make a comment section, but if you need anything / just want to tell me something, feel free to email me
vesania at exonauto.me
Thanks for reading, have a wonderful day :)