Skip to content

refactor: videos page revamp#17870

Merged
wackerow merged 65 commits intostagingfrom
videos-refactor
Apr 13, 2026
Merged

refactor: videos page revamp#17870
wackerow merged 65 commits intostagingfrom
videos-refactor

Conversation

@wackerow
Copy link
Copy Markdown
Member

@wackerow wackerow commented Mar 27, 2026

Note: This is a draft preview PR with intent to extend PR:

Summary

Refactors the video data architecture and page structure to align with site conventions.

Data layer

  • Moved all video metadata from videos.json into markdown frontmatter (index.md)
  • Renamed transcript.md to index.md for each video
  • Rewrote data layer to read from filesystem instead of JSON
  • Added VideoFrontmatter type, replaced old Video/VideoMeta/VideoWithMeta types
  • Deleted videos.json and videoTranscripts.ts (merged into videos.ts)
  • Added breadcrumb frontmatter to all 42 videos
  • Used shared stripMarkdown instead of duplicate stripMdx

Components and organization

  • Moved page-scoped components out of src/components/ into app/[locale]/videos/_components/
  • Inlined transcript accordion and markdown rendering directly into page.tsx
  • Moved VIDEO_CATEGORIES to colocated constants.ts, getVideosByCategory to utils.ts
  • Updated VideoWatch shared component for new data layer
  • Cleaned up unused i18n keys
  • Removed PR-added unit and e2e tests

SEO preserved

  • JSON-LD VideoObject schema on every video detail page
  • Transcript text stays in DOM when accordion is closed via forceMount
  • generateStaticParams pre-renders all video pages at build time
  • Per-video generateMetadata for title and description meta tags
  • Breadcrumbs with translatable labels
  • Sitemap inclusion for video pages
  • Semantic HTML structure

Preview links

Schema Markup Validator

mnelsonBT and others added 30 commits March 26, 2026 15:37
Add VideoFrontmatter interface extending SharedFrontmatter with video-specific fields (youtubeId, uploadDate, duration, topic as string[], etc). Replace Video/VideoMeta/VideoWithMeta with VideoData and VideoCardData types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename transcript.md to index.md for all 42 videos. Merge metadata from videos.json into YAML frontmatter (youtubeId, uploadDate, duration, educationLevel, topic as array, format, author, lang, breadcrumb). This consolidates the split data model into a single source of truth per video.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite videos.ts to read video data from index.md frontmatter via readdir + gray-matter instead of videos.json. Delete videos.json and videoTranscripts.ts (logic merged into videos.ts).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional boolean parameter to preserve paragraph structure instead of collapsing all whitespace. Used by video JSON-LD transcript output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update VideoWatch to use getVideoData and conditionally hide transcript link. Delete Transcript, TranscriptContent (inlined into page.tsx), VideoGalleryFilter (moved to _components/), and barrel export from src/components/Videos/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add VideoGalleryFilter, constants.ts (VIDEO_CATEGORIES), and utils.ts (getVideosByCategory) under the /videos route. Update listing page to use filesystem-based getVideos() and colocated imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite video detail page to use getVideoData with frontmatter, SimpleHero, Breadcrumbs, formatDate, renderSimpleMarkdown for transcript, and forceMount accordion for SEO. Update JSON-LD to accept VideoFrontmatter and use shared stripMarkdown. Update translation keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove PR-added Playwright test files for video utilities. These tested the old JSON-based data layer and are not needed for production.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unused CSS classes from VideoWatch, delete e2e video tests from PR, and remove 5 unused i18n keys from page-videos.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mnelsonBT and others added 15 commits April 7, 2026 18:18
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Extract escapeHeadingIds to shared module and add remark-heading-id plugin to renderSimpleMarkdown so video transcripts can use {#custom-header-ids}.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Replaces `sddefault` (640x480) which is not guaranteed to exist

Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
@@ -1,8 +1,10 @@
import { compileMDX, type MDXRemoteProps } from "next-mdx-remote/rsc"
import remarkGfm from "remark-gfm"
import remarkHeadingId from "remark-heading-id"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

markdownlint enforcing header ID's on all content -- This enables proper parsing when using renderSimple approach. Compatible for even simpler markdown where these ID's won't be present (e.g., externally fetched data)

Comment on lines +113 to +114
label: t("nav-videos-label"),
description: t("nav-videos-description"),
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder note: These need translations

Comment thread src/lib/utils/videos.ts
Comment on lines +31 to +37
/**
* Default YouTube thumbnail URL derived from a video ID.
* Returns hqdefault (480x360) which is guaranteed to exist.
*/
export function getDefaultThumbnailUrl(youtubeId: string): string {
return `https://img.youtube.com/vi/${youtubeId}/hqdefault.jpg`
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • sddefault.jpg not always available (higher resolution)
  • Using hq version for now which is guaranteed to be available from YT
  • Conditionally rendering sd if available requires several sequential fetches during build -- avoided
  • Future Trigger.dev task could load highest-quality image to s3 bucket so we can point to that instead

{
variants: {
variant: {
semibold: "text-lg font-semibold",
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small addition here in lieu of hard-coding this styling into where the card is consumed

Comment thread src/lib/md/compile.ts
Comment on lines -19 to -25
// Preprocess the markdown content
function preprocessMarkdown(content: string) {
// Replace heading IDs without escaping to escaped version
// TODO: move to a separate file and test it more
return content.replace(/^(#{1,6}.*?)\{(#[\w-]+)\}/gm, "$1\\{$2\\}")
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shared -- abstracted to @/lib/md/escapeHeadingIds and renamed

Comment thread src/lib/interfaces.ts
youtubeId: string
uploadDate: string
duration: string
educationLevel: "beginner" | "intermediate" | "advanced"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Some of these are used for JSONLD and not rendered)

Comment thread next.config.js
{ protocol: "https", hostname: "cdn.charmverse.io" },
{ protocol: "https", hostname: "ethwingman.com" },
{ protocol: "https", hostname: "eth-mcp.dev" },
{ protocol: "https", hostname: "img.youtube.com", pathname: "/vi/**" },
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If/when we implement Trigger.dev/s3 bucket handling for these, we could remove this

pettinarip
pettinarip previously approved these changes Apr 13, 2026
Copy link
Copy Markdown
Member

@pettinarip pettinarip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wackerow great job overall 💪🏼 feel free to target staging and go live today

Comment thread src/lib/utils/videos.ts
* Get all video slugs by scanning the content/videos directory.
* Results are cached for the duration of the build.
*/
export async function getVideoSlugs(): Promise<string[]> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could reuse getPostSlugs, or rename it to getSlugs, we are basically doing the same.

"@type": "Person",
name: frontmatter.author,
},
publisher: ethereumFoundationOrganization,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use the reference. Check #17955

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have a lib/utils/videos.ts, maybe we put it there?

locale,
slug,
baseComponents: mdComponents,
baseComponents: { ...mdComponents, VideoWatch },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we put this into mdComponents intead? just to not create the precedent to add more here in the future

@wackerow wackerow changed the base branch from dev to staging April 13, 2026 18:04
@wackerow wackerow dismissed pettinarip’s stale review April 13, 2026 18:04

The base branch was changed.

@wackerow wackerow merged commit 7ee9468 into staging Apr 13, 2026
10 of 14 checks passed
@wackerow wackerow deleted the videos-refactor branch April 13, 2026 18:20
wackerow added a commit that referenced this pull request Apr 13, 2026
This reverts commit 7ee9468, reversing
changes made to 2dd260d.
wackerow added a commit that referenced this pull request Apr 13, 2026
@wackerow wackerow mentioned this pull request Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config ⚙️ Changes to configuration files content 🖋️ This involves copy additions or edits documentation 📖 Change or add documentation tooling 🔧 Changes related to tooling of the project translation 🌍 This is related to our Translation Program

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants