Skip to content

refactor(skin): cut internal consumers over to VJSC - #2548

Merged
mihar-22 merged 6 commits into
feat/vjsc-html-cdn-templatesfrom
feat/vjsc-consumer-cutover
Sep 3, 2026
Merged

refactor(skin): cut internal consumers over to VJSC#2548
mihar-22 merged 6 commits into
feat/vjsc-html-cdn-templatesfrom
feat/vjsc-consumer-cutover

Conversation

@mihar-22

@mihar-22 mihar-22 commented Aug 29, 2026

Copy link
Copy Markdown
Member

Summary

  • move Sandbox and E2E consumers to the public React and HTML skin packages
  • install React and HTML Tailwind skin variants from the hosted registry into an ignored Sandbox tree
  • use hosted HTML skins as editable static templates plus exact package registration modules
  • cover Default, Minimal, Audio, Video, Live Audio, and Live Video across React, HTML, and CDN workflows
  • compare each transformed module graph so CSS skins cannot inherit Tailwind-only component dependencies
  • preserve packaged CSS semantics while keeping source-owned Tailwind resets in the base layer
  • stabilize preview startup with deterministic dependency prebundling and a change-only iframe state bridge
  • keep generated framework, registry, and Sandbox artifacts ignored and untracked

Verification

  • VJSC and Skins unit suites
  • hosted registry validation
  • Sandbox E2E and VJSC skin matrices
  • pnpm build:sandbox
  • pnpm typecheck
  • pnpm lint
  • pnpm check:workspace
  • generated-artifact audit

Closes #2494
Parent tracking issue: #2185

Stack


Note

Medium Risk
Large sandbox skin-loading and generated-artifact pipeline changes affect dev, StackBlitz, and E2E; failures would show up as missing _generated skins or flaky iframe startup rather than production package APIs.

Overview
Moves Sandbox, E2E, and the skins dev preview off @videojs/skins and onto packaged CSS skins plus source-owned Tailwind installed from the hosted Shadcn registry into gitignored app/_generated/.

Sandbox runs sync-source-owned-skins.ts during setup (local registry or shadcn.videojs.org), wires React/HTML loaders to _generated and @videojs/html / @videojs/react, and adds live audio (CDN, HTML, React). The shell iframe postMessages only when preview state actually changes to avoid startup races. Vite setup depends on @videojs/skins#build:shadcn when present and prebundles more deps for stable dev/E2E.

E2E broadens cross-renderer selectors for VJSC/Tailwind markup, drops the @videojs/skins dep, starts the sandbox via dev:sandbox, adds live skin coverage, and relaxes/skips RTL physical control-order checks pending VJSC gaps.

Skins dev preview drops the legacy source path and splits options, loaders, and media rendering into smaller modules.

Reviewed by Cursor Bugbot for commit d59058a. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
v10-sandbox Ready Ready Preview Sep 3, 2026 6:58pm UTC

Request Review

@netlify

netlify Bot commented Aug 29, 2026

Copy link
Copy Markdown

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit d59058a
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/6a99c2e1b247b5000700f97d
😎 Deploy Preview https://deploy-preview-2548--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new

pkg-pr-new Bot commented Aug 29, 2026

Copy link
Copy Markdown
@videojs/core

pnpm add https://pkg.pr.new/@videojs/core@2548

@videojs/element

pnpm add https://pkg.pr.new/@videojs/element@2548

@videojs/html

pnpm add https://pkg.pr.new/@videojs/html@2548

@videojs/media

pnpm add https://pkg.pr.new/@videojs/media@2548

@videojs/react

pnpm add https://pkg.pr.new/@videojs/react@2548

@videojs/spf

pnpm add https://pkg.pr.new/@videojs/spf@2548

@videojs/store

pnpm add https://pkg.pr.new/@videojs/store@2548

@videojs/utils

pnpm add https://pkg.pr.new/@videojs/utils@2548

commit: 1ef0211

@mihar-22
mihar-22 force-pushed the feat/vjsc-consumer-cutover branch 2 times, most recently from e565089 to ce970bb Compare August 29, 2026 19:33
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Initial Lazy
/video (default) 21.43 kB 56.87 kB
/video (default + hls) 161.19 kB 56.87 kB
/video (minimal) 21.35 kB 56.87 kB
/video (minimal + hls) 161.13 kB 56.87 kB
/audio (default) 13.66 kB 56.87 kB
/audio (minimal) 13.89 kB 56.87 kB
/background 11.54 kB 56.87 kB
Media (18)
Entry Initial
/media/mux-video 142.40 kB
/media/mux-audio 142.23 kB
/media/background-video 1.16 kB
/media/cloudflare-video 6.28 kB
/media/dash-video 211.61 kB
/media/hls-audio 22.09 kB
/media/hls-background-video 16.80 kB
/media/hls-video 28.04 kB
/media/hlsjs-video 141.22 kB
/media/mux-background-video 16.83 kB
/media/native-hls-video 7.57 kB
/media/shaka-video 199.18 kB
/media/spotify-audio 6.27 kB
/media/tiktok-video 6.33 kB
/media/twitch-video 6.22 kB
/media/vimeo-video 13.05 kB
/media/wistia-video 60.23 kB
/media/youtube-video 6.81 kB
Extensions (2)
Entry Initial
/extensions/google-cast 6.52 kB
/extensions/mux-data 26.94 kB
Players (5)
Entry Initial Lazy
/video/player 9.70 kB 56.87 kB
/audio/player 6.14 kB 56.87 kB
/background/player 4.46 kB 56.87 kB
/live-video/player 9.06 kB 56.87 kB
/live-audio/player 6.15 kB 56.87 kB
Skins (29)
Entry Type Initial Lazy
/video/minimal-skin.css css 8.48 kB
/video/skin.css css 8.50 kB
/video/minimal-skin js 12.42 kB 56.87 kB
/video/minimal-skin2 js 9.02 kB
/video/skin js 12.49 kB 56.87 kB
/video/skin2 js 9.13 kB
/audio/minimal-skin.css css 5.69 kB
/audio/skin.css css 5.54 kB
/audio/minimal-skin js 8.55 kB 56.87 kB
/audio/minimal-skin2 js 6.08 kB
/audio/skin js 8.33 kB 56.87 kB
/audio/skin2 js 5.87 kB
/background/skin.css css 139 B
/background/skin js 9.77 kB 56.87 kB
/background/skin2 js 187 B
/live-video/minimal-skin.css css 6.85 kB
/live-video/skin.css css 6.90 kB
/live-video/minimal-skin js 9.99 kB 56.87 kB
/live-video/minimal-skin2 js 7.29 kB
/live-video/skin js 10.13 kB 56.87 kB
/live-video/skin2 js 7.40 kB
/live-audio/minimal-skin.css css 4.33 kB
/live-audio/skin.css css 4.25 kB
/live-audio/minimal-skin js 6.68 kB 56.87 kB
/live-audio/minimal-skin2 js 4.62 kB
/live-audio/skin js 6.57 kB 56.87 kB
/live-audio/skin2 js 4.53 kB
/global.css css 190 B
/shared.css css 118 B
UI Components (62)
Entry Initial Lazy
/ui/airplay-button 11.26 kB 56.87 kB
/ui/alert-dialog 8.79 kB 56.87 kB
/ui/audio-track-radio-group 11.38 kB 56.87 kB
/ui/buffering-indicator 8.61 kB 56.87 kB
/ui/captions-button 11.51 kB 56.87 kB
/ui/captions-radio-group 11.46 kB 56.87 kB
/ui/cast-button 11.25 kB 56.87 kB
/ui/container 9.47 kB 56.87 kB
/ui/controls 8.77 kB 56.87 kB
/ui/controls-backdrop 1.69 kB 56.87 kB
/ui/controls-content 1.67 kB 56.87 kB
/ui/dialog 8.73 kB 56.87 kB
/ui/dialog-backdrop 1.70 kB 56.87 kB
/ui/dialog-close 2.06 kB 56.87 kB
/ui/dialog-description 1.69 kB 56.87 kB
/ui/dialog-popup 1.90 kB 56.87 kB
/ui/dialog-title 1.70 kB 56.87 kB
/ui/error-dialog 12.38 kB 56.87 kB
/ui/fullscreen-button 11.27 kB 56.87 kB
/ui/gesture 9.56 kB 56.87 kB
/ui/hotkey 9.97 kB 56.87 kB
/ui/live-button 9.74 kB 56.87 kB
/ui/menu 18.34 kB 56.87 kB
/ui/menu-checkbox-item 1.97 kB 56.87 kB
/ui/menu-content 7.50 kB 56.87 kB
/ui/menu-group 2.09 kB 56.87 kB
/ui/menu-group-label 1.64 kB
/ui/menu-item 2.29 kB 56.87 kB
/ui/menu-item-indicator 1.37 kB 56.87 kB
/ui/menu-radio-group 3.01 kB 56.87 kB
/ui/menu-radio-item 2.13 kB 56.87 kB
/ui/menu-separator 1.30 kB 56.87 kB
/ui/mute-button 11.28 kB 56.87 kB
/ui/pip-button 11.22 kB 56.87 kB
/ui/play-button 11.23 kB 56.87 kB
/ui/playback-rate-button 11.32 kB 56.87 kB
/ui/playback-rate-radio-group 11.37 kB 56.87 kB
/ui/popover 8.56 kB 56.87 kB
/ui/poster 8.67 kB 56.87 kB
/ui/quality-radio-group 11.97 kB 56.87 kB
/ui/seek-button 11.27 kB 56.87 kB
/ui/seek-indicator 12.69 kB 56.87 kB
/ui/seek-indicator-value 1.10 kB
/ui/slider 11.65 kB 56.87 kB
/ui/slider-preview 2.01 kB 56.87 kB
/ui/status-announcer 10.59 kB 56.87 kB
/ui/status-indicator 13.02 kB 56.87 kB
/ui/status-indicator-value 1.10 kB
/ui/thumbnail 9.84 kB 56.87 kB
/ui/time 10.80 kB 56.87 kB
/ui/time-slider 13.02 kB 56.87 kB
/ui/time-slider-chapter-title 8.79 kB 56.87 kB
/ui/time-slider-chapters 9.64 kB 56.87 kB
/ui/title 8.17 kB 56.87 kB
/ui/tooltip 9.94 kB 56.87 kB
/ui/tooltip-label 1.21 kB
/ui/tooltip-shortcut 1.18 kB
/ui/volume-indicator 13.01 kB 56.87 kB
/ui/volume-indicator-fill 1.11 kB
/ui/volume-indicator-value 1.10 kB
/ui/volume-popover 14.72 kB 56.87 kB
/ui/volume-slider 12.31 kB 56.87 kB
⚛️ @videojs/react — no changes
Presets (7)
Entry Initial Lazy
/video (default) 52.57 kB 56.87 kB
/video (default + hls) 190.56 kB 56.87 kB
/video (minimal) 52.62 kB 56.87 kB
/video (minimal + hls) 190.49 kB 56.87 kB
/audio (default) 40.10 kB 56.87 kB
/audio (minimal) 40.25 kB 56.87 kB
/background 581 B 56.87 kB
Media (22)
Entry Initial
/media/mux-video/hls-js 140.61 kB
/media/mux-video/spf 27.39 kB
/media/mux-audio/hls-js 140.55 kB
/media/mux-audio/spf 21.32 kB
/media/background-video 402 B
/media/cloudflare-video 4.34 kB
/media/dash-video 210.29 kB
/media/hls-audio 20.33 kB
/media/hls-background-video 16.46 kB
/media/hls-video 26.34 kB
/media/hlsjs-video 139.44 kB
/media/mux-audio 140.56 kB
/media/mux-background-video 16.45 kB
/media/mux-video 140.54 kB
/media/native-hls-video 5.76 kB
/media/shaka-video 197.52 kB
/media/spotify-audio 4.22 kB
/media/tiktok-video 4.18 kB
/media/twitch-video 4.30 kB
/media/vimeo-video 11.19 kB
/media/wistia-video 60.05 kB
/media/youtube-video 4.86 kB
Extensions (2)
Entry Initial
/extensions/google-cast 5.34 kB
/extensions/mux-data 25.70 kB
Players (5)
Entry Initial Lazy
/video/player 7.56 kB 56.87 kB
/audio/player 4.00 kB 56.87 kB
/background/player 2.27 kB 56.87 kB
/live-video/player 6.96 kB 56.87 kB
/live-audio/player 3.99 kB 56.87 kB
Skins (18)
Entry Type Initial Lazy
/video/minimal-skin.css css 8.34 kB
/video/skin.css css 8.36 kB
/video/minimal-skin js 52.58 kB 56.87 kB
/video/skin js 52.44 kB 56.87 kB
/audio/minimal-skin.css css 5.62 kB
/audio/skin.css css 5.47 kB
/audio/minimal-skin js 40.13 kB 56.87 kB
/audio/skin js 40.04 kB 56.87 kB
/background/skin.css css 90 B
/background/skin js 277 B
/live-video/minimal-skin.css css 6.70 kB
/live-video/skin.css css 6.77 kB
/live-video/minimal-skin js 43.78 kB 56.87 kB
/live-video/skin js 43.80 kB 56.87 kB
/live-audio/minimal-skin.css css 4.23 kB
/live-audio/skin.css css 4.12 kB
/live-audio/minimal-skin js 30.83 kB 56.87 kB
/live-audio/skin js 30.82 kB 56.87 kB
UI Components (39)
Entry Initial Lazy
/ui/airplay-button 10.43 kB 56.87 kB
/ui/alert-dialog 4.71 kB 56.87 kB
/ui/audio-track 7.93 kB 56.87 kB
/ui/audio-track-radio-group 9.45 kB 56.87 kB
/ui/buffering-indicator 7.77 kB 56.87 kB
/ui/captions-button 10.40 kB 56.87 kB
/ui/captions-radio-group 9.57 kB 56.87 kB
/ui/cast-button 10.40 kB 56.87 kB
/ui/controls 7.68 kB 56.87 kB
/ui/dialog 4.73 kB 56.87 kB
/ui/error-dialog 11.77 kB 56.87 kB
/ui/fullscreen-button 10.36 kB 56.87 kB
/ui/gesture 7.99 kB 56.87 kB
/ui/hotkey 8.38 kB 56.87 kB
/ui/live-button 8.76 kB 56.87 kB
/ui/menu 19.30 kB 56.87 kB
/ui/mute-button 10.41 kB 56.87 kB
/ui/pip-button 10.36 kB 56.87 kB
/ui/play-button 10.35 kB 56.87 kB
/ui/playback-rate 7.99 kB 56.87 kB
/ui/playback-rate-button 10.35 kB 56.87 kB
/ui/playback-rate-radio-group 9.50 kB 56.87 kB
/ui/popover 8.13 kB 56.87 kB
/ui/poster 7.54 kB 56.87 kB
/ui/quality 8.42 kB 56.87 kB
/ui/quality-radio-group 9.92 kB 56.87 kB
/ui/seek-button 10.38 kB 56.87 kB
/ui/seek-indicator 11.95 kB 56.87 kB
/ui/slider 12.73 kB 56.87 kB
/ui/status-announcer 10.06 kB 56.87 kB
/ui/status-indicator 12.26 kB 56.87 kB
/ui/thumbnail 8.71 kB 56.87 kB
/ui/time 9.74 kB 56.87 kB
/ui/time-slider 14.15 kB 56.87 kB
/ui/title 7.24 kB 56.87 kB
/ui/tooltip 8.90 kB 56.87 kB
/ui/volume-indicator 12.32 kB 56.87 kB
/ui/volume-popover 14.17 kB 56.87 kB
/ui/volume-slider 12.11 kB 56.87 kB
🧩 @videojs/core — no changes
Entries (76)
Entry Initial Lazy
. 13.15 kB
/dom 22.42 kB 56.87 kB
/vjsc 1.82 kB
/i18n 3.23 kB 56.87 kB
/i18n/locales/all 34.97 kB
/i18n/locales/ar 1.22 kB
/i18n/locales/az 1.09 kB
/i18n/locales/bg 1.29 kB
/i18n/locales/bn 1.23 kB
/i18n/locales/bs 1.00 kB
/i18n/locales/ca 1.07 kB
/i18n/locales/cs 1.07 kB
/i18n/locales/cy 1.02 kB
/i18n/locales/da 1006 B
/i18n/locales/de 1.09 kB
/i18n/locales/el 1.49 kB
/i18n/locales/en 785 B
/i18n/locales/es 1018 B
/i18n/locales/et 1.05 kB
/i18n/locales/eu 1.03 kB
/i18n/locales/fa 1.22 kB
/i18n/locales/fi 1.04 kB
/i18n/locales/fr 1.07 kB
/i18n/locales/gd 1.10 kB
/i18n/locales/gl 1022 B
/i18n/locales/he 1.14 kB
/i18n/locales/hi 1.30 kB
/i18n/locales/hr 1.02 kB
/i18n/locales/hu 1.10 kB
/i18n/locales/id 919 B
/i18n/locales/it 1.01 kB
/i18n/locales/ja 1.18 kB
/i18n/locales/ko 1.14 kB
/i18n/locales/lt 1.02 kB
/i18n/locales/lv 1.09 kB
/i18n/locales/mr 1.30 kB
/i18n/locales/nb 987 B
/i18n/locales/ne 1.29 kB
/i18n/locales/nl 1.00 kB
/i18n/locales/nn 987 B
/i18n/locales/oc 1.08 kB
/i18n/locales/pl 1.14 kB
/i18n/locales/pt 1.03 kB
/i18n/locales/pt-BR 1.03 kB
/i18n/locales/pt-PT 1.01 kB
/i18n/locales/ro 1.07 kB
/i18n/locales/ru 1.40 kB
/i18n/locales/sk 1.10 kB
/i18n/locales/sl 1.04 kB
/i18n/locales/sr 1.07 kB
/i18n/locales/sv 1.01 kB
/i18n/locales/te 1.32 kB
/i18n/locales/th 1.29 kB
/i18n/locales/tr 1.08 kB
/i18n/locales/uk 1.41 kB
/i18n/locales/vi 1.11 kB
/i18n/locales/zh 1.02 kB
/i18n/locales/zh-CN 1.02 kB
/i18n/locales/zh-TW 1.02 kB
/i18n/text/airplay 101 B
/i18n/text/buttons 137 B
/i18n/text/captions 93 B
/i18n/text/cast 114 B
/i18n/text/common 90 B
/i18n/text/container 75 B
/i18n/text/errors 285 B
/i18n/text/fullscreen 98 B
/i18n/text/live 126 B
/i18n/text/menu 249 B
/i18n/text/pip 101 B
/i18n/text/playback 80 B
/i18n/text/seek 105 B
/i18n/text/slider 65 B
/i18n/text/status 222 B
/i18n/text/time 280 B
/i18n/text/volume 133 B
🏷️ @videojs/element — no changes
Entries (2)
Entry Initial
. 1.05 kB
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Initial
. 1.72 kB
/html 703 B
/react 365 B
🔧 @videojs/utils — no changes
Entries (13)
Entry Initial
/array 271 B
/dom 5.02 kB
/events 320 B
/function 386 B
/i18n 249 B
/jwt 176 B
/object 535 B
/predicate 297 B
/percent 281 B
/string 239 B
/style 212 B
/time 976 B
/number 199 B

📦 @videojs/media

Path Base initial PR initial Initial diff Lazy diff
/dom/dash 209.83 kB 3.28 kB -206.54 kB (-98.4%)
/dom/wistia 60.09 kB 1.89 kB -58.20 kB (-96.9%)
Entries (23)
Entry Initial
. 1.07 kB
/dom 121 B
/dom/dash 3.28 kB
/dom/wistia 1.89 kB
/dom/audio-host 1.10 kB
/dom/cloudflare 3.69 kB
/dom/custom-media-element 2.13 kB
/dom/dash 209.83 kB
/dom/google-cast 4.06 kB
/dom/hls-js 139.16 kB
/dom/media-host 1.20 kB
/dom/media-played-ranges 576 B
/dom/mux 162.88 kB
/dom/native-hls 5.25 kB
/dom/shaka 197.02 kB
/dom/spotify 3.58 kB
/dom/tiktok 3.57 kB
/dom/twitch 3.62 kB
/dom/video-host 1.39 kB
/dom/vimeo 10.62 kB
/dom/wistia 60.09 kB
/dom/youtube 4.25 kB
/media-tracks 2.05 kB
📦 @videojs/spf — no changes
Entries (10)
Entry Initial
. 4.55 kB
/dom 6.60 kB
/hls 22.06 kB
/media-tracks 504 B
/hls-background-video 15.89 kB
/hls-audio 19.82 kB
/hls-video 25.85 kB
/mux-audio 20.76 kB
/mux-background-video 15.89 kB
/mux-video 26.67 kB

ℹ️ How to interpret

Each entry is independently bundled, minified, and brotli-compressed. Initial size includes its static import graph; lazy dynamic chunks are reported separately.

Entries are not additive because their dependency graphs overlap. Preset rows represent realistic combined bundles.

Changes of 300 B or less across initial, lazy, and total size are collapsed, not discarded.

Run pnpm size locally to check current initial sizes.


function escapeAttribute(value: string): string {
return value.replaceAll('&', '&').replaceAll('"', '"');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Local HTML escape helper added

Medium Severity

New HTML interpolation in the extracted preview media helper escapes attributes with a local escapeAttribute instead of shared escapeHtml from @videojs/utils. The leftover copy in main.tsx does the same. The local helper only encodes & and ", so < and other characters in poster, caption, and track URLs are not escaped before innerHTML.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by learned rule: HTML string interpolation must use shared escapeHtml — no local escape functions

Reviewed by Cursor Bugbot for commit 1ef0211. Configure here.

Comment thread packages/skins/dev/main.tsx
Comment thread apps/e2e/fixtures/selectors.ts
@mihar-22
mihar-22 force-pushed the feat/vjsc-consumer-cutover branch from 1ef0211 to 563f3a9 Compare September 3, 2026 18:52
@mihar-22
mihar-22 force-pushed the feat/vjsc-consumer-cutover branch from 563f3a9 to 4e41287 Compare September 3, 2026 18:53
@mihar-22
mihar-22 force-pushed the feat/vjsc-consumer-cutover branch from 4e41287 to be24c8b Compare September 3, 2026 18:53
@mihar-22
mihar-22 force-pushed the feat/vjsc-consumer-cutover branch from be24c8b to 34db279 Compare September 3, 2026 18:54
@mihar-22
mihar-22 force-pushed the feat/vjsc-consumer-cutover branch from 34db279 to d59058a Compare September 3, 2026 18:56
@mihar-22
mihar-22 merged commit 8a6a86c into main Sep 3, 2026
10 of 11 checks passed
@mihar-22
mihar-22 deleted the feat/vjsc-consumer-cutover branch September 3, 2026 18:59

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d59058a. Configure here.

if (server) await close(server);
}

await runCommand('git', ['check-ignore', '--quiet', 'apps/sandbox/app/_generated'], workspaceDir);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Setup git check breaks standalone

Medium Severity

After installing skins, setup always runs git check-ignore from the monorepo root with path apps/sandbox/app/_generated. Outside the workspace, including StackBlitz, that path and git root are wrong, so setup.ts throws and the sandbox never boots.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d59058a. Configure here.

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.

Architecture: Cut Internal Consumers Over to VJSC Skins

2 participants