Skip to content

feat(product): display product videos on the PDP#3083

Merged
jorgemoya merged 1 commit into
canaryfrom
feat/product-videos-pdp
Jul 8, 2026
Merged

feat(product): display product videos on the PDP#3083
jorgemoya merged 1 commit into
canaryfrom
feat/product-videos-pdp

Conversation

@jorgemoya

Copy link
Copy Markdown
Contributor

Recreation of #3044, rebased on current canary (c6b3b0713). Verified with pnpm -C core typecheck and eslint (clean on all changed files).

What / Why

Product videos were unsupported on the Catalyst PDP even though the Storefront
GraphQL API already exposes them on Product.videos. The API returns a
{ title, url } pair (a YouTube watch URL — YouTube is BigCommerce's supported
product-video provider), so two pieces were missing: the query never requested
the field, and there was no layer to turn a watch URL into an embeddable player.

This PR adds both and renders videos in a dedicated section below the primary
product content
— mirroring the Stencil/Cornerstone product_below_content
layout — rather than mixing them into the image gallery.

Layout

A "Videos" section sits directly below ProductDetail, before Related Products
and Reviews:

ProductDetail (gallery = images only)
→ Videos          ◄── new section
→ Related Products
→ Reviews

It renders a featured player + horizontal thumbnail strip (clicking a
thumbnail swaps the featured video) with a Hide/Show toggle. This matches the
Cornerstone PDP video structure. The featured player is full section width
(max-w-screen-2xl) as a starting point.

Changes

File Change
core/app/.../product/[slug]/page-data.ts Add videos(first: 25) { edges { node { title url } } } to the PDP product query
core/app/.../product/[slug]/page.tsx Add streamableVideos (independent of the gallery image stream); mount <ProductVideos> below ProductDetail
core/vibes/soul/sections/product-detail/product-videos.tsx New. Section component — heading + collapsible toggle, featured lite-youtube player + title, thumbnail strip that swaps the featured video
core/vibes/soul/sections/product-detail/lite-youtube.tsx New. Client-only <lite-youtube> facade wrapper (poster + play button; injects the iframe only on click)
core/vibes/soul/sections/product-detail/video-embed.ts New. getYouTubeId() (defensive watch-URL parser) + getYouTubePosterUrl()
core/vibes/soul/sections/product-detail/lite-youtube-embed.d.ts New. Ambient module declaration — lite-youtube-embed ships no types and is imported only for its custom-element side effect
core/messages/en.json i18n keys: videosTitle, hideVideos, showVideos, playVideo, viewVideo (English source)
core/next.config.ts Allow i.ytimg.com/vi/** poster thumbnails through next/image
core/package.json Add lite-youtube-embed ^0.3.4
.changeset/product-videos-pdp.md minor bump to @bigcommerce/catalyst-core

Design notes

  • Dedicated section, not the gallery: keeps the gallery purely visual
    (image-only), matches the long-standing Stencil/Cornerstone PDP convention, and
    lets videos scale without competing with image pagination / load-more.
  • lite-youtube-embed: a tiny, dependency-free third-party facade — shows a
    poster + play button and injects the youtube-nocookie iframe only on click, so
    no heavy player loads on PDP view. Registered client-side only (it subclasses
    HTMLElement at import, which breaks SSR); inert markup server-side, upgrades on
    hydration.
  • YouTube-only: getYouTubeId() validates protocol + host + id shape and
    drops anything that isn't a YouTube URL, matching BC's supported provider. The
    section renders nothing when there are no usable YouTube URLs.
  • Playback hygiene: the featured <lite-youtube> is keyed by video id, so
    swapping videos remounts the player and stops the previous one.

Accessibility

  • Collapsible toggle uses aria-expanded + aria-controls wired to the panel via
    useId().
  • Thumbnails use aria-pressed for selected state and labelled aria-labels; the
    play control has a visually-hidden label.

Testing

Verified on current canary (base c6b3b0713):

pnpm install                     # lockfile adds only lite-youtube-embed
pnpm -C core typecheck           # 0 errors on changed files
eslint <changed files>           # clean
  • PDP renders the Videos section: featured player, title, thumbnail strip;
    toggle hides/shows; thumbnails swap the featured video.
  • 0 player iframes on initial load (facade); the iframe mounts only on click.

getYouTubeId() verification matrix

core/ has no unit-test runner today (tests are Playwright e2e), so the parser is
covered by this manual matrix (a unit test is a ready follow-up — the function is
pure):

Input Expected
https://www.youtube.com/watch?v=dQw4w9WgXcQ dQw4w9WgXcQ
https://youtu.be/dQw4w9WgXcQ dQw4w9WgXcQ
https://www.youtube.com/embed/dQw4w9WgXcQ dQw4w9WgXcQ
https://www.youtube.com/shorts/dQw4w9WgXcQ dQw4w9WgXcQ
https://m.youtube.com/watch?v=dQw4w9WgXcQ dQw4w9WgXcQ
https://vimeo.com/123456 null (non-YouTube host)
https://youtube.com.evil.com/watch?v=x null (host not whitelisted)
javascript:alert(1) null (non-http(s) protocol)
not a url null (parse failure)
https://www.youtube.com/watch?v= null (empty id)

Migration / risk

Additive — the gallery, image load-more, and the review-form image consumer are
unchanged. CSP isn't affected (Catalyst sets no frame-src, so the YouTube iframe
loads). Branch is based on current canary (c6b3b0713).

🤖 Generated with Claude Code

@jorgemoya jorgemoya requested a review from a team as a code owner July 7, 2026 16:23
@changeset-bot

changeset-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 145fef5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@bigcommerce/catalyst-core Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
catalyst Ready Ready Preview, Comment Jul 7, 2026 4:26pm

Request Review

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Report

Comparing against baseline from c6b3b07 (2026-07-07).

Metric Baseline Current Delta
Total JS 435.8 kB 436.9 kB +1.1 kB (+0.3%)

Per-Route First Load JS

Route Baseline Current Delta
/(default)/product/[slug]/page 389.2 kB 390.3 kB +1.1 kB (+0.3%)

Threshold: 5% increase. Routes with ⚠️ exceed the threshold.

Original work by BC-AdamWard (#3044); recreated on a fresh branch rebased on
current canary.

Product videos were unsupported on the Catalyst PDP even though the Storefront
GraphQL API exposes them on Product.videos (a { title, url } pair — a YouTube
watch URL). This adds the query and renders videos in a dedicated "Videos"
section below the primary product content (mirroring the Stencil/Cornerstone
product_below_content layout), not inside the image gallery.

- page-data.ts: fetch videos(first: 25) on the PDP product query
- page.tsx: stream videos independently of gallery images; mount <ProductVideos>
  below ProductDetail (before related products / reviews)
- ProductVideos: featured lite-youtube player + thumbnail strip that swaps the
  featured video, with a Hide/Show toggle (YouTube-only, BC's supported provider)
- lite-youtube: client-only facade (poster + play button; injects the
  youtube-nocookie iframe only on click) — no heavy player on PDP view
- video-embed: getYouTubeId() defensive watch-URL parser + poster URL helper
- next.config: allow i.ytimg.com poster thumbnails through next/image
- i18n: videosTitle / hideVideos / showVideos / playVideo / viewVideo (en source)

Co-Authored-By: BC-AdamWard <95659751+BC-AdamWard@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jorgemoya jorgemoya force-pushed the feat/product-videos-pdp branch from 556cbac to 145fef5 Compare July 7, 2026 16:24
@jorgemoya

Copy link
Copy Markdown
Contributor Author

Attribution: the original implementation is by @BC-AdamWard in #3044. This branch recreates that work rebased on current canary; @BC-AdamWard is credited as Co-Authored-By on the commit.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Unlighthouse Performance Comparison — Vercel

Comparing PR preview deployment Unlighthouse scores vs production Unlighthouse scores.

Summary Score

Aggregate score across all categories as reported by Unlighthouse.

Prod Desktop Prod Mobile Preview Desktop Preview Mobile
Score 89 92 91 95

Category Scores

Category Prod Desktop Prod Mobile Preview Desktop Preview Mobile
Performance 75 86 74 91
Accessibility 95 98 95 92
Best Practices 100 100 100 100
SEO 88 88 88 100

Core Web Vitals

Metric Prod Desktop Prod Mobile Preview Desktop Preview Mobile
LCP 3.9 s 4.1 s 4.3 s 3.4 s
CLS 0.001 0 0.037 0
FCP 1.2 s 1.2 s 1.1 s 1.2 s
TBT 0 ms 0 ms 0 ms 0 ms
Max Potential FID 50 ms 40 ms 50 ms 50 ms
Time to Interactive 3.9 s 4.2 s 4.3 s 3.7 s

Full Unlighthouse report →

@jorgemoya jorgemoya added this pull request to the merge queue Jul 7, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 7, 2026
@jorgemoya jorgemoya added this pull request to the merge queue Jul 8, 2026
Merged via the queue into canary with commit 2b7f2cc Jul 8, 2026
25 of 26 checks passed
@jorgemoya jorgemoya deleted the feat/product-videos-pdp branch July 8, 2026 22:40
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.

2 participants