Drawing with DOM
Generating dynamic images on the web has traditionally been a choice between two evils.
It usually starts with a simple requirement: "We need dynamic Open Graph images for our blog posts." You want every shared link on Twitter/X to have a custom image with the title and author.
You have two options, and they both hurt:
- The Heavyweight (Puppeteer): Spawning a headless Chrome browser just to take a screenshot. This is slow, expensive, and crashes serverless functions like a house of cards.
- The Hard Way (Canvas API): Writing imperative, low-level drawing instructions like
ctx.moveTo(10, 10). It is painful, unreadable, and impossible to debug.
I wanted Option C: Write HTML/CSS, and get a vector image.
I didn't want a screenshot. I wanted a Compiler.
The "Photographer" Fallacy
To understand why Azhn exists, you have to understand why Puppeteer is the wrong tool for this job.
Using a headless browser to generate an image is like hiring a professional photographer to take a picture of a blueprint.
- You have to build the physical studio (spin up Chrome / Chromium).
- You have to paint the wall (render HTML/CSS).
- You have to set up lighting and take the photo (screenshot).
- You tear down the studio.
It is wasteful. It is heavy. It is entropy.
Azhn is different. Azhn doesn't take a photo. Azhn reads the blueprint. It reads your HTML instructions and translates them directly into mathematical SVG code.
Enter Azhn
Azhn is a TypeScript engine that tricks the browser (or Node.js) into thinking it's rendering a webpage, but captures the render tree as an SVG.
It allows you to build Open Graph images, dynamic charts, and generative art using the same <div> and flex semantics you use every day.
The "Aha" Moment
I realized that the DOM (Document Object Model) is actually just a very complex Vector Graphics Instruction Set.
If you can traverse the DOM tree, calculate the Computed Styles of every node, and map them to SVG attributes, you can "compile" HTML to SVG without ever rendering a pixel.
<div style="background: red">becomes<rect fill="#ff0000" />border-radius: 50%becomes<circle />Textbecomes<text />
// The Azhn Experience
import { render } from 'azhn';
// We write React/HTML...
const svg = await render(
<div style={{
display: 'flex',
background: '#000',
alignItems: 'center'
}}>
<h1 style={{
color: '#00FFFF', // Cyan
fontFamily: 'Geist Mono'
}}>
Hello World
</h1>
</div>
);
// ...and we get a pure SVG string back.
Why Vectors?
Unlike Puppeteer, which gives you a rasterized PNG (a grid of pixels), Azhn gives you a crisp, infinite-resolution SVG (mathematical shapes).
File Size
5kb vs 500kb. SVG text is just text, not thousands of pixels.
Speed
<10ms generation time. No browser boot-up time.
Scalability
Perfect for Edge Functions. No Chromium binary required.
It is the engine running the dynamic visualizations you see on my personal site. It turns the "heavy" task of image generation into a lightweight, deterministic function.