Reading the repo
Reading the repo
How to install on Windows
Video.js v10 - open source media player framework for HTML and React.
Saved setup from 3 h ago
Will it work on my device?
CONTRIBUTING.mdFirst off, thank you for taking the time to contribute to Video.js 10 ❤️ Your input helps shape the next generation of open web media players.
Video.js is a free and open source library, and we appreciate any help you're willing to give - whether it's fixing bugs, improving documentation, or suggesting new features. Contributions and project decisions are overseen by the Video.js Technical Steering Committee (TSC).
Video.js 10 is set up a monorepo using pnpm workspaces. As such, most scripts run will be done from the project/workspace root. Unless otherwise specified, assume commands and similar should be run from the root directory.
[!TIP] This repo includes tooling for AI-assisted development. See Using AI.
You’ll need the following installed:
[!TIP] PNPM will automatically use the correct Node version when running scripts. If you prefer NVM: after installing it, simply run
nvm usein the repo root. NVM keeps global packages per Node version, so after switching to a new version reinstall pnpm at the versionpackage.json'spackageManagernames:npm i -g pnpm@<version>. If you prefer mise: see Using mise — it manages pnpm for you too.
git clone https://github.com/{your-github-username}/video.js.git
cd video.js
git remote add upstream git@github.com:videojs/video.js.git
git fetch upstream
git branch --set-upstream-to=upstream/main main
To update your local main branch later:
git fetch upstream
git checkout main
git pull upstream main
pnpm install
This also exposes the checked-in .agents/skills/ catalog through generated .claude/skills/ and .opencode/skills/ directory aliases. AGENTS.md is the canonical project guide; Claude's CLAUDE.md imports it.
[!NOTE] Windows users: Directory aliases use junctions and work without Developer Mode. If alias creation fails,
pnpm installlogs a warning and continues; the checked-in domain folders remain available.
Then build all workspace packages:
pnpm build:packages
ℹ️ VS Code Users: the project may suggest extensions to enhance the developer experience. If imports like
reactare not resolving, set your TS version to the workspace one:CMD/CTRL + Shift + P→TypeScript: Select TypeScript Version→ Use Workspace Version.
mise is an alternative to Volta/NVM that manages both Node and pnpm from the checked-in mise.toml.
mise trust # once per clone; mise only reads configs you've trusted
mise install # provisions Node (from .nvmrc) and pnpm
mise run setup # pnpm install + pnpm build:packages
mise.toml also puts the workspace's node_modules/.bin on PATH, so biome, turbo, and tsgo can be run directly rather than through pnpm exec.
Everything else stays as documented below: use the pnpm scripts, not mise tasks. Personal additions, such as extra tools, environment variables, belong in a gitignored mise.local.toml or .env.local and not in the shared config.
One exception: apps/react-native has its own mise.toml for the native toolchains (JDK, Ruby, CocoaPods), and there mise is not optional. See its README.
To run the workspace in development mode:
pnpm dev
This will run the entire workspace in developer mode, meaning all applications (examples and website) will also be started on their respective ports.
pnpm dev and pnpm dev:packages prepare package outputs, then watch development JavaScript and CSS only to reduce memory use. Restart either task or run pnpm build:packages to refresh type declarations and production outputs. Use Ctrl+C to stop the servers and watchers; interactive watcher shortcuts are disabled.
pnpm dev:site # just the documentation site
pnpm dev:packages # just the library packages (no apps)
pnpm dev:sandbox # just the sandbox playground
See Manual Testing with the Sandbox for how to use the sandbox to exercise player changes in the browser.
Sometimes you may want to do (non-dev) builds, say, to validate the full build process or evaluate production artifacts.
pnpm build:packages
To build the sandbox (and its package dependencies):
pnpm build:sandbox
To build all workspace packages and applications:
pnpm build
We use Vite+ with Oxlint and Oxfmt for linting and formatting. Between IDE integration, pre-commit hooks, and manual CLI fixes, many issues should get caught automatically.
To ensure your code follows our lint rules with:
pnpm lint # check the whole workspace
pnpm lint:fix # check and auto-fix the whole workspace
pnpm lint:fix:file <file> # check and auto-fix a single file
Vite+ pre-commit hooks automatically check and fix staged files.
We use TypeScript project references for fast, incremental typechecking across the workspace:
pnpm typecheck
[!TIP] Typecheck runs against built
.d.tsfiles. If you add or change exported types in a package, runpnpm -F <pkg> buildfirst so the new declarations are emitted before typechecking.
We use Vitest for unit testing.
pnpm test # all workspace tests
pnpm -F core test # just core package
pnpm -F core test:watch # watch core package
We use Playwright for end-to-end testing. The E2E tests live in apps/e2e/ and run against a Vite-based test app that hosts the player in multiple configurations (HTML, React, editable skin layouts, CDN bundles).
Playwright browsers and system dependencies are installed automatically during pnpm install. On Linux without sudo, browsers will install but system deps will be skipped with a note. If e2e tests fail due to missing system dependencies, install them manually:
sudo pnpm test:e2e:install
Running tests:
pnpm test:e2e # Chromium + WebKit (all engines)
pnpm test:e2e:vite # Chromium only (fast feedback)
Visual snapshot tests verify that skin CSS and layout aren't broken. If a snapshot test fails, it means the rendered skin looks different from the baseline. This could mean:
You intentionally changed the skin — update the baselines:
pnpm test:e2e:update
Review the updated PNGs in apps/e2e/tests/visual/ to confirm they look correct, then commit them.
You didn't intend to change the skin — the failure caught a real regression. Inspect the diff in the Playwright HTML report:
pnpm --dir apps/e2e report
The report shows expected vs. actual vs. diff images side-by-side.
[!TIP] Snapshot baselines are checked into git. When you update them, review the PNG diffs in your PR to make sure the visual changes are intentional.
The sandbox (apps/sandbox/) is a Vite playground for manually exercising player changes in a browser. The root URL renders an interactive shell — a navbar with dropdowns for platform, preset, skin, styling, and source — that previews the selected combination in an iframe. One-off templates outside the main matrix are reachable by navigating directly to /<template-name>/. See apps/sandbox/templates/ for the full list.
pnpm dev:sandbox # sandbox + workspace package watch
pnpm dev # also runs the docs site
Sandbox code lives in two parallel directories:
apps/sandbox/templates/ — source of truth, checked into git.apps/sandbox/src/ — your scratch copy, fully gitignored.On pnpm dev:sandbox, setup.ts copies any file from templates/ that doesn't already exist in src/. Existing files in src/ are never overwritten, so your local changes persist across restarts.
[!IMPORTANT] Because
src/is gitignored, edits you make there will not appear ingit status. When you want to promote a sandbox change into the repo, runpnpm -F @videojs/sandbox sync— it shows a diff of every changed file and prompts before copyingsrc/→templates/. To throw away local edits and restore from templates, runpnpm -F @videojs/sandbox reset.
See apps/sandbox/README.md for the full model, including the app/ shell, the @app/* alias for shared code, and how to add a new sandbox entry point.
Pull requests and commits on main publish an installable preview of the public packages to pkg.pr.new — nothing is published to npm. A bot comment on the PR lists the install commands, and the same URLs work by commit SHA:
pnpm add https://pkg.pr.new/@videojs/html@<pr-number-or-sha>
Use this to try a change in a real project before it is released. Previews are versioned 0.0.0-preview-<sha> so they can never satisfy a semver range for a real release, and they ship without the bundled markdown docs that real releases include.
Because a preview is an installable artifact carrying the Video.js name, it is only published for code someone with repository access pushed or vouched for. Pull requests from a branch in this repo publish automatically; pull requests from a fork publish only once a maintainer approves them. The approval has to be written against the pull request's latest commit, so any new commit needs a fresh approval before it is published.
This section is for maintainers. Releases run from .github/workflows/cd.yml in the production environment:
main, built from conventional commits. Merging it tags the release.packages/ to npm. Stable versions go to latest; prereleases go to next.@videojs/cdn GitHub release and updates the site/v10 branch.The publish step authenticates with npm trusted publishing (OIDC); there is no npm token. Every public package needs a GitHub Actions trusted publisher for repository videojs/video.js, workflow cd.yml, environment production, with publish permission. If the Publish step logs ERR_PNPM_AUTH_TOKEN_EXCHANGE ... (status code 404) and then fails with 404 Not Found, that package's trusted publisher is missing, expired, or doesn't match.
Each public package's Publishing access should be "Require two-factor authentication and disallow tokens", which npm recommends alongside trusted publishing: OIDC publishes keep working, and long-lived tokens can't publish. Set it once a new package has its trusted publisher, either under the package's Settings on npmjs.com or with npm access set mfa=publish <package>. npm asks for 2FA on each change.
To add or repair trusted publishers, log in with an npm account that has 2FA and write access to the packages, then run:
npm login
pnpm release:trust --dry-run # show each package's current trusted publisher
pnpm release:trust # add missing ones and replace mismatched ones
npm asks for 2FA to read trusted publishers as well as change them, so --dry-run prompts too. When npm's website offers "skip two-factor authentication for the next 5 minutes", tick it to get through the batch. Pass package names to limit the run, and add --force to replace configurations that look correct but are still rejected. The script only replaces trusted publishers for cd.yml; publishers for other workflows, such as the Video.js 8 release, are left alone.
[!IMPORTANT] npm can't attach a trusted publisher to a package that doesn't exist yet. When you add a new public package, run
pnpm release:trustbefore merging the release PR that first includes it. The script publishes a deprecated0.0.0-placeholderversion to claim the name, and the release then publishes the real version overlatest.The release PR's npm trusted publishing status fails while any public package isn't on npm, and its workflow summary lists the command to run. Once you've run it, re-run the failed
trusted-publishingjob in the Release PR workflow. The check can't read trusted publisher settings (that needs npm 2FA), so it doesn't catch expired or mismatched ones;pnpm release:trust --dry-rundoes.
If publishing fails after release-please has tagged the release, fix the cause, then run the Deployment workflow from main with the released version:
gh workflow run cd.yml --ref main -f recover_version=<version>
pnpm publish skips versions already on npm, so a partial publish resumes where it stopped. Recovery only accepts the current release, and it refuses to run once packages/ or site/ have changed on main since the tag. In that case, ship the fix in the next release instead.
Before opening a PR, run the workspace consistency check to catch common mistakes (CI coverage, scope mismatches, broken define imports, etc.):
pnpm check:workspace
To add a dependency to a specific package, you can use pnpm filtering from the workspace root:
pnpm -F <scope> add <package>
# Example:
pnpm -F react add @floating-ui/react-dom
To upgrade a dependency across all packages:
pnpm up <package>@<version> -r
[!CAUTION] We try to be very intentional with any dependencies we add to this project. This is true of both developer/tooling dependencies and especially package-level (source) dependencies. If you find yourself needing to add a dependency, we strongly encourage you to check in with the core maintainers before proceeding to avoid wasted time and effort for everyone involved (yourself included!).
Video.js 10 includes portable tooling for AI-assisted development. Read AGENTS.md for repo-wide conventions and source routing; Claude Code imports it through CLAUDE.md.
| Command | Purpose |
| ---------------- | ------------------------------------------------- |
| /commit-pr | Commit changes and create/update a PR |
| /review-branch | Review changes in the current branch |
| /investigate-issue <n> | Analyze an issue and generate a plan |
| /create-issue | Create a GitHub issue following repo conventions |
| /maintain-agent-docs | Update agent guidance and skills |
| /create-skill | Scaffold a new skill |
Focused workflows live as direct children of .agents/skills/; host-specific discovery paths are generated aliases. A few of the most-used skills:
| Skill | Use When |
| ------------------------ | ------------------------------------------------------- |
| design-api | Designing public APIs and TypeScript contracts |
| review-api | Auditing API and architecture changes |
| create-html-component | Building custom-element UI components |
| create-react-component | Building React UI components |
| implement-ui-transition| Implementing UI transition and rendered-presence logic |
| review-html-component | Reviewing custom-element component architecture |
| review-react-component | Reviewing React component architecture |
| write-html-component-design | Writing custom-element component design records |
| write-react-component-design | Writing React component design records |
| review-html-component-design | Reviewing proposed custom-element designs |
| review-react-component-design| Reviewing proposed React component designs |
| implement-accessible-ui| Implementing accessible interaction |
| review-accessibility | Auditing accessibility |
| write-docs | Writing guides, READMEs, and JSDoc |
| review-docs | Reviewing documentation |
| write-api-reference | Building generated component or utility references |
| create-spf-behavior | Creating one SPF behavior |
| change-spf-behavior | Updating, refactoring, splitting, or merging a behavior |
| document-spf-feature | Maintaining an SPF feature registry entry |
| document-spf-use-case | Maintaining an SPF use-case composition |
| implement-spf-feature | Implementing an SPF feature |
| implement-spf-use-case | Implementing an SPF use-case composition |
When your changes introduce new patterns:
AGENTS.md.agents/skills/check:workspaceWe use two types of design documents:
Design Docs (internal/design/) — Compact records of architecture or feature rationale that cannot be inferred from code and tests. Create one only when a maintainer explicitly requests it. See internal/design/README.md.
RFCs (rfc/) — Proposals needing buy-in from others. Write one when the decision affects multiple areas, changes shared API surface, or is hard to reverse. See rfc/README.md.
Rule of thumb: If you need someone else's approval, explicitly request an RFC. If you intentionally want durable rationale for a decision you own, explicitly request a Design Doc or decision record.
Skip both for: Bug fixes, small contained features, implementation details.
By submitting a pull request, you agree that your contribution is provided under the Apache 2.0 License and may be included in future releases. No contributor license agreement (CLA) has ever been required for contributions to Video.js. See the Developer's Certificate of Origin 1.1.
Whether you're adding something new, making something better, or fixing a bug, you'll first want to search the [GitHub issues](https://github.com/videojs/video.js/issu
Then run powershell -ExecutionPolicy Bypass -File .\setup.ps1. It stops at the first error and is safe to run again. Servers and tests aren't started; it lists them at the end. Read it first.
Needs Git: winget install Git.Git
git clone https://github.com/videojs/video.js.git cd video.js
Node.js 24.14.0
winget install jdx.mise mise install
corepack enable pnpm install
pnpm dev
pnpm test
Using an AI coding agent? Install the Video.js skill so it reads the docs that match your installed version before writing code.
Then print the version-matched installation choices for your framework. The command returns instructions without modifying your project:
npx @videojs/cli agents init
No reports for Windows yet.
Opens a chat with this manual already filled in, for Windows. It uses your own account; gitmanual sends nothing.