# Render HTML to a PNG file at build time

**URL:** <https://discourse.gohugo.io/t/render-html-to-a-png-file-at-build-time/54097>\
**Category:** support\
**Created:** [March 26, 2025, 6:40am UTC](https://discourse.gohugo.io/t/render-html-to-a-png-file-at-build-time/54097 "2025-03-26T06:40:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![theRookieCoder](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/therookiecoder/32/24203_2.png) [@theRookieCoder](https://discourse.gohugo.io/u/theRookieCoder)\
**Post date:** [March 26, 2025, 6:40am UTC](https://discourse.gohugo.io/t/render-html-to-a-png-file-at-build-time/54097/1 "2025-03-26T06:40:50Z")

</div>

I recently added build-time dynamic `og:image` creation to my website ([commit](https://github.com/theRookieCoder/theRookieCoder.github.io/commit/c67c1120e37cfb935ec72d1d5a632a69bde7e67f)). I had to replicate distinctive elements of my website in an SVG drawing program, export it to a PNG, and make Hugo overlay the post title and date using `image.Filter`. [Here](https://github.com/theRookieCoder/theRookieCoder.github.io/blob/main/layouts/partials/opengraph.html#L51-L87) is the relevant code.

But I’m sure there’s a better way, I wasn’t able to perfectly replicate the website’s elements in the SVG image. So I thought, why not just render the HTML to PNG directly? That way the styles can be shared and it will be identical. I searched quite a lot but I wasn’t able to find any way for Hugo to render HTML to images. Is there a way to achieve this, maybe by calling a locally installed program, or using some Go library?

---

<div class="post-metadata">

**Author:** ![chrillek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/chrillek/32/19797_2.png) [@chrillek](https://discourse.gohugo.io/u/chrillek)\
**Post date:** [March 26, 2025, 8:19am UTC](https://discourse.gohugo.io/t/render-html-to-a-png-file-at-build-time/54097/2 "2025-03-26T08:19:24Z")

</div>

What is the _point_ of that exercise? The OpenGraph site appears to be pretty clear that `og:image` is not meant to be an image of your web document, but an image that _illustrates_ said document.

> **[Open Graph protocol](https://ogp.me/)**
>
> The Open Graph protocol enables any web page to become a rich object in a social graph.

> [@theRookieCoder](#):
>
> So I thought, why not just render the HTML to PNG directly?

Because that is beyond the point. `og:image` should refer to an image _in the web page_.

> [@theRookieCoder](#):
>
> I wasn’t able to find any way for Hugo to render HTML to images

Which is also beyond the point. Hugo is a static site generator, not a HTML user agent. You’re trying to solve an imaginary problem. Just set your `og:image` to the featured image of your page(s).

---

<div class="post-metadata">

**Author:** ![davidsneighbour](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/davidsneighbour/32/24507_2.png) [@davidsneighbour](https://discourse.gohugo.io/u/davidsneighbour)\
**Post date:** [March 26, 2025, 9:33am UTC](https://discourse.gohugo.io/t/render-html-to-a-png-file-at-build-time/54097/3 "2025-03-26T09:33:47Z")

</div>

Not sure why you want to render a HTML page then transform into SVG then do some resizing and cutting out to get a sized preview. That sounds like a lot of work to “just” get a screenshot.

We “normally” do things like this with a [screenshot tool like the one Zach Leat created for 11ty](https://github.com/11ty/api-screenshot). Deploy a screenshot server (or use any API for that, when it came out he deployed a public server you could use), retrieve the screenshot at build time (handing over url, width and height and some other parameters), use the image for your preview as a layer and then put stuff on top of it (that’s where image.Filter comes into play I guess). No need to reinvent the wheel 🙂

---

<div class="post-metadata">

**Author:** ![theRookieCoder](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/therookiecoder/32/24203_2.png) [@theRookieCoder](https://discourse.gohugo.io/u/theRookieCoder)\
**Post date:** [March 26, 2025, 10:03am UTC](https://discourse.gohugo.io/t/render-html-to-a-png-file-at-build-time/54097/4 "2025-03-26T10:03:30Z")

</div>

> [@chrillek](#):
>
> `og:image` is not meant to be an image of your web document, but an image that _illustrates_ said document

> [@davidsneighbour](#):
>
> That sounds like a lot of work to “just” get a screenshot.

Hmm I think people are misunderstanding me, I don’t intend to use a screenshot of my website. I want to use HTML to draw the [image template](https://github.com/theRookieCoder/theRookieCoder.github.io/blob/main/assets/og-image-source.svg) with the title and date, instead of using SVG and Hugo image filters.

I would prefer this because

1. Using HTML and CSS will allow me to share code with the website’s, and
2. It would allow text rendering to be more consistent with the website itself, because Hugo’s `image.Text` filter does not support options like letter spacing.

* * *

> [@chrillek](#):
>
> The OpenGraph site appears to be pretty clear that `og:image` is not meant to be an image of your web document

I’ve based my design off of popular websites like GitHub, where the image shows metadata about the page such as a title, date, likes/shares statistics, and some decoration. I believe that is a valid and popular implementation for pages that don’t have a relevant image to feature.

* * *

> [@chrillek](#):
>
> Hugo is a static site generator, not a HTML user agent

Yes I understand that functionality like this is not in the scope of Hugo, and I do not expect Hugo to have any sort of functionality like this in the future either. I intended to get inspiration from other users who dynamically generate these images, since I haven’t found a de facto way to do this.
