Skip to content

feat(head): a post's share video (og:video), with the share image kept - #6

Merged
arjunpredev merged 1 commit into
mainfrom
feat/og-video
Oct 27, 2026
Merged

arjunpredev merged 1 commit into
mainfrom
feat/og-video

Conversation

@arjunpredev

Copy link
Copy Markdown
Contributor

What

A post can now have a share video (ogVideo): a looping MP4 that link previews play in iMessage and Discord.

When a post has one, its page gets:

  • og:video, og:video:secure_url, og:video:type (video/mp4), and og:video:width/og:video:height (the share image's size)
  • og:type set to video.other, which Discord needs before it plays the video

The share image stays

  • og:image, its size and alt text, twitter:image and twitter:card=summary_large_image are all still written. Every app that doesn't play video shows the image.
  • The video tags are written only when the page also has a share image.
  • LinkedIn shows no image at all for a page with og:video. So for LinkedInBot, serveSite removes the og:video* tags and sets og:type back to article. This happens on the response, so the cached page is unchanged.

I checked headTags and the strip with Bun's HTMLRewriter for three cases:

Case og:type og:video og:image twitter:card
video + image video.other yes yes summary_large_image
video, no image article no no summary
LinkedInBot article no yes summary_large_image

Data

  • Schema v13: ALTER TABLE posts ADD COLUMN og_video TEXT. Posts only; pages don't take a video.
  • The field is mapped through toPost, POST_FIELDS, the list query and the snapshot columns. You set it with PUT admin/api/posts/:id {"ogVideo": "https://..."}.
  • A snapshot import leaves it alone, since the import INSERT doesn't list it.
  • rewriteUrls moves it along with the other media columns.
  • The preview host moves its address the same way it moves og:image.

bun run typecheck and the leak guard (with the denylist) pass.

🤖 Generated with Claude Code

A post can carry ogVideo, a looping MP4 the size of its share image. Its
page then gets og:video, og:video:secure_url, og:video:type and the size,
and og:type video.other, which Discord needs to play it; iMessage plays it
too. The share image, twitter:image and summary_large_image all stay, and
the video goes out only with a share image, since every other app shows
that instead.

LinkedIn shows no image for a page with og:video, so LinkedInBot gets the
post without the video tags and as an article (public.ts). The preview
host moves the video's address with the image's, and a media move rewrites
it like the other image columns.

Schema v13 adds posts.og_video. Set it through the admin API
(PUT admin/api/posts/:id with {"ogVideo": "https://..."}).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@arjunpredev
arjunpredev merged commit b72316e into main Oct 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant