Files
buzz/previews/invite-video
Tom Brow 2c5c8343ef fix(relay): bound invite preview host lookup (#9308)
**Context:** #9306 (merged) added link-preview tags to the invite page.
To build the media URLs, the relay looks up the community for the
request host. This fixes a problem found in our review of #9306.

**Problem:** The invite page waits for that lookup with no time limit.
When the database is slow, the lookup can take as long as the pool
acquire timeout (3 s) plus the statement timeout (120 s by default).
During that time, a person who opens an invite link gets no page. Before
#9306, this page did not use the database.

**Fix:** The lookup gets 250 ms. If it does not finish, the relay sends
the page without the preview tags. A healthy indexed host lookup
finishes well inside that, so crawlers still get the tags, and nothing
else changes: the media route, the router and the build are untouched.

### Validation

- Added test: a host whose lookup never finishes gets the plain page.
Without the timeout, this test hangs (confirmed locally; it was killed
after 30 s).
- The existing `invite_preview` and router invite tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Tom Brow <tomb@squareup.com>
Co-authored-by: Tom Brow <tomb@squareup.com>
Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz>
2026-11-10 21:15:13 -08:00
..

Invite preview media

A 16-second silent Buzz animation and wordmark-only PNG fallback, with a browser tool for reviewing motion and choosing poster frames. The animation uses the onboarding wordmark and fuzzy shader, pale-blue/lime bees, diagonal paired flights and a solo loop-de-loop.

Preview

From the repository root:

python3 -m http.server 4319 --bind 127.0.0.1 --directory previews/invite-video

Open http://127.0.0.1:4319. Scrub or choose a suggested frame, then select Use this frame. Poster choices persist only in that browser; Download poster PNG exports the choice. The committed poster is the approved wordmark-only frame at 0 seconds. The iMessage-style card is a composition simulation, not evidence of a native Messages unfurl.

Media

  • buzz-invite-loop.mp4: 960 × 540, 30 fps, H.264/yuv420p, fast-start, no audio.
  • buzz-invite-poster.png: 960 × 540, wordmark only.
  • buzz-wordmark.png and wordmark.frag: onboarding artwork and 400 ms grain/displacement shader, from the Buzz desktop onboarding implementation; bee silhouette matches the mobile welcome artwork.
  • Background: #D7D72E; bees: #D7E7F5 and #DBFA52.

Verify or regenerate

Activate the repository's Hermit environment first. Install Chrome, Python 3, and ffmpeg. Then:

cd previews/invite-video
npm ci
npm test
npm run render

Verification starts an isolated localhost server and checks poster selection, PNG export, persistence, loop continuity, mobile overflow and reduced-motion startup. Rendering also rebuilds both committed media files. Temporary captures stay in .output/. PREVIEW_BROWSER may select another installed Playwright Chromium channel.

Production invite previews

The production web build includes the approved MP4 and wordmark-only poster at /assets/invite-preview/buzz-invite-loop-v1.mp4 and /assets/invite-preview/buzz-invite-poster-v1.png. The relay adds Open Graph metadata to the initial HTML for /invite/<code> only. Previews are generic and do not validate or redeem the invite.

Deploy both the updated relay and its web bundle (the relay Docker image includes both). The media host comes from the request's resolved community, matching the invite link's host. RELAY_URL supplies only the wss/ws TLS posture, mapped to https/http. Unmapped hosts, lookup failures and slow lookups receive no preview metadata. Each community host must serve the web bundle without authentication. Use HTTPS in production.

After deployment, inspect an invite response with curl for og:video and og:image, then fetch both referenced URLs and check that they return MP4/PNG content rather than a login page. The video endpoint supports HTTP range requests. Share a fresh invite link in Messages to test actual playback; receiving apps decide whether to play video or use the poster, and may cache previews.

When replacing approved media, bump the versioned filenames in both web/vite.config.ts and crates/buzz-relay/src/invite_preview.rs to avoid stale cached media.

The receiving app chooses playback behavior. The 16-second duration is an animation choice, not an asserted platform limit.