self-host og:image thumbnails for link cards
Created by: jedmund
Summary
- download og:images at post save time and store them as
Mediarows (cloudinary in prod, local disk in dev), then point theurlEmbednode at the self-hosted url - new
isLinkCardImageflag onMediakeeps these auto-downloaded thumbnails out of the media library - extend rich-text media walker to pick up
urlEmbed.imageMediaIdso link-card assets show up inmedia.usedInand don't look orphaned
Why
after #81 the editor was saving og:image hotlink urls directly in the post json. hotlinking is fragile: hosts block based on referer, CSPs trip, images get removed or renamed, and we leak reader ip to third parties. self-hosting eliminates link rot and makes link cards behave like any other image asset in the app.
Migration
adds Media.isLinkCardImage (boolean, default false) + index. run npm run db:migrate in dev, npm run db:deploy in prod.
Existing posts
re-saving a post with a foreign image url will trigger the download and swap in the hosted url automatically — no backfill script needed. posts with cloudinary/local image urls already are treated as locally hosted and skipped.
Test plan
-
paste a url with a valid og:image and save — the saved contenthas a cloudinary //local-uploads/url, not the origin url -
confirm the new Mediarow hasisLinkCardImage = true -
GET /api/mediadoes not return link-card rows -
source url with broken/403 og:image — save succeeds; attrs keep the original hotlink as fallback -
image > 10MB or non-image content-type — download is skipped, hotlink is kept -
open an existing post saved under #81 with a hotlink image, save it again, confirm the image attr becomes a hosted url -
deleting a post decrements media.usedInvia existingMediaUsagetracking for the link-card row