Repository navigation
feat: add a Photo template that uses the page's image - #97
Merged
Merged
Conversation
template=8 fills the Open Graph image with a photo and sets the title over a dark fade. The photo is the first that loads of: 1. The new `image` query parameter. 2. The page's og:image or twitter:image. 3. The first large image in the page's <article> or <main>, then anywhere on the page, including lazy-loaded data-src and srcset. Images under 200 pixels, SVGs, and fiimage's own /og images are skipped. The photo is fetched with the same SSRF protection as icons, alongside the icon, and shrunk to cover 1200x630 before rendering. Without a photo, the background stays dark. Other templates do not fetch photos. fiimage now marks its icon and photo requests with an x-fiimage-fetch header. A request that carries it skips icons and photos, so a page whose icon or image points back at fiimage cannot make it request itself over and over. The photo is drawn as a cover background, because resvg cuts off an <img> that Satori crops with object-fit when the image is much taller or wider than the card.
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
On Vercel, /og receives a plain Node request, which has no Express req.get(), so every template=8 request failed with "Unable to generate the image.". Read the header from req.headers instead, and test the check with a request that has no get().
Remote fetches now send "fiimage (+https://github.com/feri-irawan/fiimage)" as the User-Agent unless the caller sets one, instead of Bun's default "Bun/1.4.2". Some sites, such as Wikimedia, ask automated clients to identify themselves and may block generic library agents. The README's Photo template section shows two examples side by side: a photo passed with image, and the photo fiimage finds on a Wikipedia article, credited under CC BY-SA.
Remote fetches go back to Bun's default User-Agent. fiimage is a public service that fetches any URL for anyone, so an identifying User-Agent would point other people's traffic at the project.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/og?template=8fills the image with a photo and sets the title over a dark fade at the bottom, with the site's icon and address at the top. It suits blog posts and news articles that have a cover image.The photo is the first of these that loads:
imageparameter, for example&image=https://example.com/cover.jpg.og:imageortwitter:image.<article>or<main>, then anywhere on the page. Lazy-loaded images are found throughdata-srcandsrcset.Images under 200 pixels, SVGs, and fiimage's own
/ogimages are skipped. Without a photo, the background stays dark. Other templates don't fetch photos, so they are no slower.Avoiding self-requests
A page's
og:imageis often a fiimage/ogURL, because that's the main way fiimage is used. If fiimage fetched it, it would render another OG image, which could fetch the same URL again, and so on./ogURLs are never used as a photo or an icon.x-fiimage-fetchheader. A request that arrives with it skips icons and photos. This also stops a loop that reaches fiimage through a redirect, including the same loop through icons, which could already happen before this change. The header is read fromreq.headers, because Vercel passes a plain Node request without Express'sreq.get().Details
background-size: coverbackground. An<img>withobject-fit: coverwas cut off by resvg when the photo was much taller or wider than the card.imageand the photo found on a Wikipedia article (credited under CC BY-SA), and theimageparameter in the query table.Testing
og:imageandtwitter:imagefirst, then article images./ogURLs, SVGs, small images, and data URIs are skipped.data-srcand the firstsrcsetentry are used, and there are at most 3 candidates.imageis tried first, a failed photo falls through to the next candidate, and photo requests carry the header. Icons can be skipped.req.get(). Running the handler with such a request failed with "Unable to generate the image." before the fix and gets past the check after it.imagereturns 400./ogskip or the request header makes the tests fail.bun test: 162 pass.bun run typecheck: clean.Try it on this PR's Vercel preview:
/og?template=8&url=https://en.wikipedia.org/wiki/Komodo_dragon, or/og?template=8&url=https://github.com/feri-irawan/fiimage&image=https://images.unsplash.com/photo-1518791841217-8f162f1e1131?w=1200.