How To Make A Dynamic Image Generator For Your Website (Obsidian Digital Garden Example)

When you share links to your digital garden notes, you want them to stand out. Generic previews are easily missed. This guide details how to create dynamic, custom preview images (like Open Graph images) for each note, automatically showing its title and even an image from the note itself. We'll build this for a Netlify-hosted Eleventy site, but the core ideas are adaptable for other hosting providers (e.g., Vercel is used at the end).

Video Walkthrough that accompanies this guide:

The Goal: When a link to any note is shared (on Farcaster, Twitter, Discord, etc.), a unique, informative image is automatically generated and displayed in the link preview, making your content more engaging.

Note: I have made a copy of this guide with more details, along with the exact code I generated during this tutorial, available to my paying YouTube members. If you would like to have these assets, please consider joining my paid membership.

My Approach: An On-Demand Image Generation Service with Netlify Edge Functions

The core of our solution is a small "image generation service" that runs as a Netlify Edge Function. Edge Functions are pieces of code that run on Netlify's global network, close to the user requesting the image, making them fast. This service will take details about a specific note (like its title) and create a custom preview image on the fly.

Let's Build It, Step-by-Step:

Step 1: Crafting the Image Generation Function (The "Generator")

This JavaScript file is where the magic happens. It will live in your project and tell Netlify how to create the images.

Step 2: Configuring Netlify to Run the Generator (netlify.toml)

This file at the root of your project gives Netlify build and deployment instructions.

Step 3: Preparing Your Eleventy Website for Dynamic Previews

Your Eleventy site (the static site generator) needs a few helpers to provide the right information to the image generator.

  1. Making Font Files Available:

    • Action: Create a folder in your Eleventy source, for example, src/site/assets/fonts/.
    • Action: Place your .ttf font files (e.g., B612-Bold.ttf, OpenSans-Regular.ttf) into this new folder.
    • Eleventy Config (.eleventy.js or .eleventy.cjs): Add an instruction to copy this entire fonts folder to your final built site (e.g., into dist/assets/fonts/). This is done with:
      eleventyConfig.addPassthroughCopy("src/site/assets/fonts");
      
      (This step also makes the fonts available for the image generator to fetch if using the public URL method, but with included_files and Deno.readFile, it's mainly for site consistency).
  2. Finding the First Image in a Note (Eleventy Filter):

    • Goal: If a note contains images, we want to use the first one as the background for our preview.
    • Eleventy Config: Create a custom filter (e.g., getFirstImageURL). This filter takes the HTML content of a note, parses it to find the web address (src) of the first <img> tag, and returns its full URL. If no image is found, it returns nothing.
  3. Making Titles URL-Safe (Eleventy Filter):

    • Goal: Note titles can have spaces or special characters. These need to be "encoded" to be safely included in a web address.
    • Eleventy Config: Add a filter named urlencode that performs this encoding (e.g., spaces become %20).

Step 4: Updating Your Note Page Template (note.njk)

This is where you instruct each note page to use the dynamic image generator.

The Result:

With these pieces in place, every note page on your Eleventy site will now have meta tags pointing to your dynamic image generator. When a link to a note is shared:

  1. The sharing platform (Farcaster, Twitter, etc.) reads these meta tags.
  2. It calls the unique URL in the imageUrl or og:image tag.
  3. Your Netlify Edge Function (og-image-generator.js) receives the request, sees the title (and possibly background image URL) in the parameters, loads the fonts, and generates a custom image.
  4. This custom image is sent back and displayed in the link preview.

A Note on Image Positioning (The Tricky Part I Solved):

When I first tried using a background image from the note, I faced a challenge: the image appeared extremely zoomed-in and stuck to the top-left corner, not nicely centered and covering the whole area.


Adapting for Other Platforms (like Vercel):

The beauty of this approach is its portability. If you were using Vercel:

The core logic for generating the image is the same; only the platform-specific function deployment and asset serving details change.