sampotts/plyr
40.5
Weak · 25 September 2026
8.2k
lines of production code
JavaScript
primary language
4
measurements over time
What this system is
This system is the Plyr video player library, providing a modular JavaScript implementation for HTML5, YouTube, and Vimeo media. It features a comprehensive UI with customizable controls, ad support, preview thumbnails, and accessibility enhancements, all styled via a modern, modular SCSS architecture. The project also includes a documentation site rebuilt with Preact and Vite to showcase the player's capabilities.
How it got here
2015 — Build tooling overhaul and legacy cleanup
10 changes.
The project migrated its build infrastructure from Gulp and LESS to a modern Vite, pnpm, and TypeScript pipeline, while removing legacy video player assets and documentation styles. This period focused on replacing outdated tooling and dependencies with a streamlined, modular architecture to support the release of Plyr v3.8.4.
2017–2018 — Plugin expansion and SCSS modularization
9 changes.
This period focused on expanding the player's capabilities with new features for advertisements, preview thumbnails, and enhanced YouTube/Vimeo integrations. Simultaneously, the codebase underwent significant structural improvements, including the modularization of SCSS styles into reusable utilities and CSS custom properties, and the refactoring of JavaScript utilities and configuration files for better maintainability.
2020–2026 — Site rebuild and build tooling overhaul
7 changes.
The project overhauled its internal build and deployment infrastructure to generate optimized ES module and UMD bundles, while simultaneously migrating the documentation site to Preact for improved performance. This period also focused on enhancing the core player's styling capabilities by adding dedicated SASS modules for audio/video players and preview thumbnails, alongside fixing TypeScript integration issues.
Features
Add dedicated SASS styles for audio and video player types
New SASS files have been added to define specific styling for audio and video player modes. The audio styles cover the control container, interactive states (including native :focus-visible support), range inputs, and progress buffering. The video styles handle the container overflow, embed aspect ratios (with a fallback for browsers lacking aspect-ratio support), Vimeo-specific positioning adjustments, control visibility transitions, and the overlaid play button behavior.
src/sass/types · high confidence
Add preview thumbnail styles for video scrubbing
Introduces new SCSS styles for the preview thumbnail plugin, enabling visual feedback during video scrubbing. The update adds settings for background, radius, shadow, and arrow size, along with layout rules for the thumbnail container, seek time display, and the scrubbing overlay image.
src/sass/plugins/preview-thumbnails · high confidence
Added fullscreen state styles for Plyr player
A new SCSS file for the fullscreen state has been introduced, defining styles for the \.plyr:fullscreen\ selector using the \plyr-fullscreen-active\ mixin. It also includes a fallback class \.plyr--fullscreen-fallback\ that applies the same mixin along with fixed positioning and a high z-index to ensure the player covers the viewport in browsers that do not support the native fullscreen API.
src/sass/states · high confidence
Added styling for ad container and progress bar cues
Introduced new Sass styles for the advertisement plugin, defining the layout for the ad container (positioned absolutely with z-index handling to overlay or sit behind controls) and the inner ad creative elements. Additionally, added visual styling for advertisement cue markers on the progress bar, ensuring they are visible and positioned correctly between the track and thumb.
src/sass/plugins · high confidence
Initial release of Plyr v3.8.4
This entry introduces the Plyr v3.8.4 player library, adding a complete, modular JavaScript implementation for HTML5, YouTube, and Vimeo video players. The update includes a new custom controls system with keyboard navigation, a settings menu for captions and quality, and support for Picture-in-Picture and fullscreen modes. It also adds features such as preview thumbnails, ad support, and improved accessibility with ARIA attributes.
src/js · high confidence
Introduction of Ads, Preview Thumbnails, and Enhanced YouTube/Vimeo Plugins
This update introduces new capabilities and significant improvements to existing video integrations. Users can now display mid-roll and pre-roll advertisements via the new Ads plugin, which leverages the Google IMA SDK and handles race conditions to prevent playback glitches. A new Preview Thumbnails plugin allows users to see frame previews when hovering or scrubbing through the seek bar, supporting both VTT sources and callback-based loading. The YouTube plugin now supports the noCookie mode for enhanced privacy, fetches and displays video titles, and improves poster image handling. The Vimeo plugin has been updated to support private videos via hash parameters, allows hiding native controls for premium accounts, and includes fixes for playback state synchronization and aspect ratios.
src/js/plugins · high confidence
New SASS utility library for animations, CSS variables, and UI components
This change introduces a new SASS library under src/sass/lib containing core utilities for the player's styling. It includes animation keyframes for progress, popups, and fade-ins, a mixin system for focus visibility, font smoothing, range inputs, and fullscreen modes, a helper for percentage conversion, and a compatibility layer for CSS custom properties that supports both native CSS variables and a Sass-based fallback map.
src/sass/lib · high confidence
New SCSS utility modules for animation and accessibility
Added two new SCSS utility files to the project: \animation.scss\ introduces a \.plyr--no-transition\ class to disable CSS transitions, and \hidden.scss\ provides screen-reader-only styling via \.plyr\_\_sr-only\ (with optional \!important\ enforcement controlled by a variable) and ensures elements with the \hidden\ attribute are visually removed from the layout.
src/sass/utils · high confidence
Removals
Removal of legacy distribution CSS files
The pre-built distribution stylesheets \dist/css/docs.css\ and \dist/css/simple-player.css\ have been removed from the project. Users relying on these specific minified files for styling the documentation site or the video player component will no longer have access to them via this path, likely requiring a switch to source SASS files or updated build outputs.
dist/css · high confidence
Removal of legacy distribution JavaScript files
The \dist/js/docs.js\, \dist/js/simple-player.js\, and \dist/js/templates.js\ files have been deleted from the distribution. These files previously contained the compiled video player logic, including custom controls, caption handling, and template rendering via Hogan.js. Their removal indicates that the legacy single-file distribution bundle is no longer maintained or served, likely as part of a broader refactoring to a different build or module system.
dist/js · high confidence
Removal of legacy documentation and player stylesheets
The stylesheets for the HTML5 video player demo page and its supporting library components have been removed. Specifically, \docs.less\ (which handled the demo page layout and typography), \simple-player.less\ (which defined the player UI, controls, and progress indicators), and the internal library files \lib/mixins.less\ and \lib/normalize.less\ are no longer present in the codebase. This eliminates the CSS rules that previously styled the video player interface and the documentation site layout.
assets/less · high confidence
Removal of legacy video controls template
The \assets/templates/controls.html\ file, which previously defined the HTML structure for video player controls (including play, pause, rewind, volume, and progress), has been removed. This change eliminates the default markup for these interactive elements, indicating that the video player's control UI is now generated or managed through a different mechanism.
assets/templates · high confidence
Removal of legacy video player and template library
The custom video player implementation (\assets/js/simple-media.js\) and its associated documentation example (\assets/js/docs.js\) have been removed, along with the Hogan.js template library (\assets/js/lib/hogan-3.0.2.mustache.js\) that the player relied on for rendering controls. This eliminates the legacy browser-sniffing logic and custom caption handling from the client-side bundle.
assets/js · high confidence
Removed legacy IcoMoon icon assets
The \design/IcoMoon - 7 Icons\ directory has been completely removed, deleting the associated SVG icon files (fast-forward, film, monitor, play, refresh, sound, up), the \svgdefs.svg\ symbol definitions, and the \demo.html\/\demo.css\/\style.css\ preview assets. This cleanup eliminates unused design resources from the repository.
design · high confidence
Architecture
Refactored utility modules into a modular structure
The generic utility functions in src/js/utils have been reorganized into distinct, specialized modules (such as animation, arrays, browser, elements, events, fetch, i18n, is, numbers, objects, strings, style, time, and urls). This change improves code maintainability and allows for more granular imports, while preserving the existing public API and behavior for consumers of these utilities.
src/js/utils · high confidence
Sass styles reorganized into modular structure
The player's styling has been restructured from a single file into a modular Sass architecture. The main entry point (plyr.scss) now imports distinct settings, base styles, and component-specific modules (such as controls, tooltips, and progress bars), enabling better organization and maintainability of the visual design.
src/sass · high confidence
Behavioural changes
Introduction of centralized configuration and type definitions
This change introduces new configuration files for the player: \defaults.js\ defines the default settings (including controls, quality options, and localization), \states.js\ exports player state constants (such as Picture-in-Picture states), and \types.js\ provides provider and media type definitions along with a utility to detect providers from URLs. These files establish the foundational configuration structure for the player.
src/js/config · high confidence
New build and deployment tooling for the player distribution
The project introduces a new set of internal build tasks that change how the player is compiled and distributed. The build process now generates ES module and UMD bundles (both plain and polyfilled versions) targeting ES2019 syntax, compiles Sass to CSS with custom properties and autoprefixing, and creates an optimized SVG icon sprite. A new deployment task handles uploading these built assets to the CDN, including logic to strip .min suffixes from published URLs and manage source map references.
tasks · high confidence
Project tooling and configuration overhaul
The repository has migrated its build and development tooling: the Gulp build system, LESS stylesheets, and Hogan templates have been removed in favor of a Vite+ (Rolldown/Oxc) build pipeline targeting ES2019. Development now uses pnpm (Node.js 22.18+), with a new Gitpod one-click setup, a Vercel-based site deployment, and automated releases via release-please. Configuration files have been updated or replaced, including a new .editorconfig, cspell.json, stylelintrc.json, and tsconfig.json, while legacy files like bower.json, .jshintrc, and gulpfile.js have been deleted.
(repo-wide) · high confidence
Redesigned site with Preact, Video.js, and Vercel analytics
The site has been rebuilt using Preact instead of React, featuring a new layout that showcases the Video.js player (streaming via Mux's SPF engine) alongside promotional content for Video.js and Plyr. The update integrates Vercel Analytics and Speed Insights for performance tracking, implements a custom button component with variant styling, and applies a new brand color system and dark mode support via Tailwind CSS.
site/src · high confidence
Sass settings modularized and exposed to CSS custom properties
The monolithic settings file has been split into distinct modules (badges, breakpoints, captions, colors, controls, cosmetics, helpers, menus, progress, sliders, tooltips, and type). All design tokens are now exposed as CSS custom properties (e.g., --plyr-color-main, --plyr-badge-background), allowing users to override styles directly via CSS variables without recompiling Sass, while maintaining Sass fallback defaults for backward compatibility.
src/sass/settings · high confidence
Site rebuilt with Preact and static rendering
The site has been migrated from React to Preact to reduce bundle size, with Vite configured to alias React imports to Preact/compat. The build process now uses server-side rendering to generate static HTML, which is served by Vercel, improving initial load performance and SEO.
site · high confidence
Video player UI components rewritten in SCSS
The player's visual interface has been restructured into modular SCSS files (badges, captions, control, controls, menus, poster, progress, sliders, times, tooltips, volume). This introduces a new badge component, refines caption positioning and visibility logic, updates control spacing and focus styles (including :focus-visible support), and improves the poster overlay behavior for YouTube and other sources.
src/sass/components · high confidence
Fixes
Added pre-commit hook for Vite processing
A new pre-commit hook has been introduced in the .vite-hooks directory. When files are staged for commit, this hook automatically executes the 'vp' command, ensuring that Vite-related processing or validation is applied before changes are committed to the repository.
.vite-hooks · medium confidence
Support CSS imports in TypeScript projects
Added a new TypeScript declaration file (src/css.d.ts) that allows TypeScript projects to import CSS files (specifically Plyr's CSS entry point) for their side effects without encountering type errors.
src · high confidence
Dependencies
Migrate to pnpm and modernize build tooling
The project has switched from npm to pnpm (v12.4.2) as the package manager, replacing the legacy Gulp-based build system with a Vite-based workflow. This update introduces TypeScript 7.0.2, Tailwind CSS 4.3.3, and Preact 11.0.0-rc.2 for the site, while the core player dependencies remain custom-event-polyfill, loadjs, rangetouch, and url-polyfill. The change also enforces a modern Node.js engine requirement (^22.18.0 \|\| \>=24.11.0) and updates the package name to 'plyr' with comprehensive ESM/CJS exports.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 27 → 41 (+13.3)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 37 → 32 (-4.3)
- Architecture 91 (new)
- Maturity 51 → 51 (-0.1)
- Readiness 11 → 32 (+20.7)
- Security 50 → 73 (+23.2)
Resolved (81)
- (anonymous) (cognitive 16) (src/js/controls.js)
- (anonymous) (cognitive 31) (src/js/source.js)
- (anonymous) (cognitive 34) (src/js/controls.js)
- (anonymous) (cyclomatic 23) (src/js/source.js)
- (anonymous) (cyclomatic 29) (src/js/controls.js)
- Change coupling: controls.js ↔ media.js (src/js/controls.js)
- Change coupling: defaults.js ↔ plyr.js (src/js/config/defaults.js)
- Change coupling: fullscreen.js ↔ plyr.js (src/js/fullscreen.js)
- Change coupling: listeners.js ↔ style.js (src/js/listeners.js)
- Change coupling: media.js ↔ plyr.js (src/js/media.js)
- Change coupling: plyr.js ↔ plyr.polyfilled.js (src/js/plyr.js)
- Change coupling: plyr.js ↔ style.js (src/js/plyr.js)
- Change coupling: plyr.js ↔ ui.js (src/js/plyr.js)
- Change coupling: vimeo.js ↔ style.js (src/js/plugins/vimeo.js)
- Change coupling: vimeo.js ↔ youtube.js (src/js/plugins/vimeo.js)
- Critical CVE: [GHSA redacted] (pnpm-lock.yaml)
- Critical CVE: [GHSA redacted] (pnpm-lock.yaml)
- Dimension evaluation failed
- FileTooLong: js/controls.js (src/js/controls.js)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- …and 61 more
New (71)
- ClassTooLong: Listeners (src/js/listeners.js)
- ClassTooLong: Plyr (src/js/plyr.js)
- Documentation: no contributor guidance (README.md)
- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- FileTooLong: js/plyr.js (src/js/plyr.js)
- Floating npm dependency: @videojs/mux-video
- Floating npm dependency: @videojs/react
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 51 more
Changes since last survey
- 17 commits — 12 feature/other, 5 fixes
By area
- (root) — 9 commits
- site/src — 4 commits
- src/js — 2 commits
- demo/src — 1 commit
- site/package-lock.json — 1 commit
Notable commits
- fix: chore: fix ci/cd workflows
- fix: fix(captions): case-insensitive language matching + keep selected track
- fix: fix(types): support default and CSS imports
- fix: fix: restore volume when unmuting from zero
- fix: refactor(site): add UTM params, style fixes
- change: Install Vercel Speed Insights
- change: chore(site): add Vercel Analytics
- change: chore(site): bump Video.js v10 preview to main@1c629d6
- change: chore(site): install Speed Insights with pnpm and block other lockfiles
- change: chore(site): limit button transitions and move the poster frame
- change: chore(site): move Vercel config into site for the site root directory
- change: chore: keep site changes out of release-please
- change: chore: tooling cleanup, site changes
- change: chore: update readme to clean it up
- change: perf(site): stream Mux video with the Video.js SPF engine instead of hls.js
- change: refactor(site): tweaks to dark button styles
- change: refactor: use preact instead of react
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
sampotts/plyr was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 25 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit d372627bd370108b82ee20ddab18386c0d63b7a5 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-dd72cc24c749.