Puppeteer-based image generator: render HTML templates to PNG/JPEG. Uses a shared browser instance; relaunches automatically if the browser disconnects.
npm install @azuro-org/images-generatorCreate a Generator instance, call run() to start the browser, then use generate() for each image. Call shutdown() when done to close the browser.
import { Generator } from '@azuro-org/images-generator';
import template from '@azuro-org/images-generator/lib/templates/bet-nft';
const generator = new Generator();
await generator.run();
// Single image – returns Uint8Array
const buffer = await generator.generate({
template,
props: { /* ... */ },
});
// Save to file
await generator.generate({
template,
props: { /* ... */ },
output: './dist',
filename: 'my-image',
});
await generator.shutdown();Run multiple generations in parallel and close the browser when finished:
await generator.run();
await Promise.all([
generator.generate({ template, props: props1, output: './dist', filename: 'image-1' }),
generator.generate({ template, props: props2, output: './dist', filename: 'image-2' }),
]).finally(() => {
generator.shutdown();
});If the browser process exits or crashes, the next generate() call will launch a new browser automatically. You can also call run() again after a disconnect.
Constructor
const generator = new Generator(options?: GeneratorOptions);
interface GeneratorOptions {
headless?: boolean; // default: true
timeout?: number; // default: 30000 (ms)
args?: string[]; // extra Chromium args
}Methods
run(): Promise<void>— Launches the browser. Idempotent if already running.generate<P>(props: GenerateProps<P>): Promise<Uint8Array>— Renders the template with the given props. Ensures the browser is running (callsrun()if needed).shutdown(): Promise<void>— Closes the browser and cleans up.
interface GenerateProps<P> {
template: Template<P>;
props: P;
output?: string; // folder path for the output file
filename?: string; // file name without extension (used with output)
options?: GenerateOptions;
}
interface GenerateOptions {
quality?: number; // JPEG quality, default 85
fullPage?: boolean; // default false
waitForFonts?: boolean; // default true
waitTimeout?: number; // ms, default 2000
waitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'; // default 'domcontentloaded'
skipAnimations?: boolean; // default true
}Templates are in lib/templates/<name> (or dist/templates/<name> for ESM). Each template exports a default Template and a Props type.
| Template | Import path |
|---|---|
| Bet NFT | @azuro-org/images-generator/lib/templates/bet-nft |
| Bet OG | @azuro-org/images-generator/lib/templates/bet-og |
| Combo Bet OG | @azuro-org/images-generator/lib/templates/combo-bet-og |
| Freebet | @azuro-org/images-generator/lib/templates/freebet |
| Trendle Leaderboard | @azuro-org/images-generator/lib/templates/trendle-leaderboard |
| Trendle Social | @azuro-org/images-generator/lib/templates/trendle-social |
| Trendle Trading | @azuro-org/images-generator/lib/templates/trendle-trading |
Bet Opengraph
import { Generator } from '@azuro-org/images-generator';
import template from '@azuro-org/images-generator/lib/templates/bet-og';
const generator = new Generator();
await generator.run();
await generator.generate({
template,
output: './dist',
filename: 'bet-og',
props: {
title: 'Decentralized betting is awesome!',
game: {
country: 'International Tournaments',
league: 'ESL Challenger League North America',
participants: [
{ name: 'WINDINGO', image: 'https://content.bookmaker.xyz/avatars/provider-3/4757.png' },
{ name: 'Los Grandes Academy', image: 'https://content.bookmaker.xyz/avatars/provider-3/4739.png' },
],
startsAt: Date.now(),
},
},
});
await generator.shutdown();
Combo Bet Opengraph
import { Generator } from '@azuro-org/images-generator';
import template from '@azuro-org/images-generator/lib/templates/combo-bet-og';
const generator = new Generator();
await generator.run();
await generator.generate({
template,
output: './dist',
filename: 'combo-bet-og',
props: {
title: 'Decentralized betting is awesome!',
data: {
totalOdds: 1.57,
possiblePayout: 1017.17,
asset: 'USDT',
},
},
});
await generator.shutdown();
Bet NFT
import { Generator } from '@azuro-org/images-generator';
import template from '@azuro-org/images-generator/lib/templates/bet-nft';
const generator = new Generator();
await generator.run();
await generator.generate({
template,
output: './dist',
filename: 'bet-nft',
props: {
type: 'match',
sport: 'Football',
league: 'International Tournaments · FIFA - World Cup',
team1: { img: 'https://content.bookmaker.xyz/avatars/provider-3/4757.png', name: 'Ecuador' },
team2: { img: 'https://content.bookmaker.xyz/avatars/provider-3/4739.png', name: 'Senegal' },
date: 'Dec 24, 2020',
betAmount: '100 xDAI',
outcome: 'Senegal',
betOdds: '1.7',
currentOdds: '1.2',
},
});
await generator.shutdown();
Freebet
import { Generator } from '@azuro-org/images-generator';
import template from '@azuro-org/images-generator/lib/templates/freebet';
const generator = new Generator();
await generator.run();
await generator.generate({
template,
output: './dist',
filename: 'freebet',
props: {
amount: '5 xDAI',
date: '12.01.2022',
},
});
await generator.shutdown();
- Copy
src/templates/_templatetosrc/templates/{your_template_name}. - Put layout and styles in
index.html. - Add a
imagesfolder for static assets if needed.
Use Template<Props>, getBase64Image, and downloadImage from ../../utils:
import { type Template, downloadImage } from '../../utils';
import html from './index.html';
export type Props = {
team1ImageSrc: string;
team2ImageSrc: string;
date: string;
};
const template: Template<Props> = {
width: 800,
height: 400,
type: 'jpeg',
html: async (props: Props) => {
const { team1ImageSrc, team2ImageSrc, date } = props;
const team1Img = await downloadImage(team1ImageSrc);
const team2Img = await downloadImage(team2ImageSrc);
return html
.replace('{image1}', team1Img)
.replace('{image2}', team2Img)
.replace('{date}', date);
},
};
export default template;Template shape
type Template<Props> = {
width: number;
height: number;
type: 'png' | 'jpeg';
html: (props: Props) => string | Promise<string>;
headless?: boolean;
scaleFactor?: 1 | 2;
};Publish with npm publish. For access to the @azuro-org scope, contact the maintainers.