# Vue Installation Guide

Install Video.js in Vue or Nuxt and build a video player with HTML custom elements

Vue apps built with Vite, Astro, or Nuxt use Video.js HTML custom elements directly in their templates. These lightweight, framework-free components build accessible, customizable players with small bundles, advanced features, and consistent behavior across browsers.

> **Note: Release Candidate**
>
> Video.js v10 is a *release candidate*. We feel the API is stable and ready to build with. With your [feedback](https://github.com/videojs/v10/issues), a few documentation updates, and any final fixes, we look forward to shipping 10.0.0 soon. [Read the Release Candidate blog post](https://videojs.org/blog/videojs-v10-release-candidate).

> **Tip: Coming from another player?**
>
> Follow the migration guide for [Video.js 8](./migrate-from-video-js-8.md), [Mux Player](./migrate-from-mux-player.md), [Plyr](./migrate-from-plyr.md), or [Media Chrome](./migrate-from-media-chrome.md). Each maps your existing setup onto Video.js v10 instead of starting from scratch.

## AI Quickstart

Paste this prompt into your coding agent:

```
Install the Video.js skill: run `npx @videojs/cli agents skills` and follow the steps for the agent you are running in. If you can't run commands, follow the install instructions at https://github.com/videojs/skills instead. Then use the Video.js skill for this project. When installation details are needed, run `npx @videojs/cli agents init --framework vue` to print the version-matched choices and instructions without changing files.
```

## Installation options for coding agents

The web Markdown page contains the default installation. Add the query parameters below to its `.md` URL for a complete, validated variation. From a project or an offline docs bundle, run the CLI command below instead. Both paths use the same installation renderer and only return instructions; they do not modify a project.

This page fixes the installation method to `packaged` and the framework to `vue`.

```sh
npx @videojs/cli agents init
```

### Query parameters

- `project`: Whether to adapt the current project or scaffold a new one. New projects need a named app setup. Values: `new`, `existing`. Default: existing.
- `preset`: The player configuration and control set. Values: `video`, `audio`, `live-video`, `live-audio`, `background-video`. Default: video.
- `skin`: The visual skin. Minimal has cleaner surfaces and the same controls as Default. Values: `default`, `minimal`, `none`. Default: default. Applies when preset is not background-video.
- `media`: The media source or playback adapter. See the preset compatibility map below. Values: `background-video`, `hls-background-video`, `cloudflare`, `dash`, `hls`, `html5-audio`, `html5-video`, `mux-audio`, `mux-background-video`, `mux-video`, `spotify`, `tiktok`, `twitch`, `vimeo`, `youtube`. Default: the selected preset's first compatible media source.
- `extensions`: A comma-separated list of optional player extensions compatible with the selected player. Pass `none` when no extension is needed. Values: `none`, `google-cast`, `mux-data`. Default: mux-data for Mux media; none otherwise (reported as defaulted).
- `source-url`: The http:// or https:// media URL placed in the generated player example. Pass `demo` to choose the Video.js demo source for the selected media explicitly. Default: the Video.js demo source for the selected media (reported as defaulted).
- `package-manager`: The command runner used for app setup, packages, Shadcn, and the development server. Values: `npm`, `pnpm`, `yarn`, `bun`. Default: pnpm. Applies when method is not cdn with template none.
- `template`: The app setup and file layout. Values: `vite`, `astro`, `nuxt`. Default: vite.

Run the command above without flags to see the corresponding CLI flags for every framework.

### Decide in this order

1. **Inspect the project.** Read package.json, framework config, and lockfiles to infer the framework, app setup, and package manager. React installs @videojs/react; HTML, Vue, and Svelte install @videojs/html.
2. **Choose the starting point.** Use existing when adapting a compatible project. Use new only when the user wants a new app or the intended workspace has no app. Confirm the choice when the workspace and request do not make it clear.
3. **Choose the player.** Use video unless the request signals another experience: audio, music, or podcasts use audio; a live stream uses live-video or live-audio; a muted, looping decorative video uses background-video. Ask only when those signals conflict.
4. **Choose the skin.** Use default unless the request asks for a minimal, cleaner, or more subtle look, which uses minimal; both contain the same controls. Use none only when the project builds its own controls. Ask only when those signals conflict.
5. **Choose the media.** Infer the adapter from the source when possible. Mux wins for Mux playback URLs: stream.mux.com/\<playback-id>.m3u8 or a bare playback ID uses mux-video, mux-audio, or mux-background-video rather than hls. Mux static renditions such as .mp4 or .m4a files use html5-video or html5-audio. Other .m3u8 URLs use hls.
6. **Choose extensions.** Mux Data is included by default for Mux video and audio sources. Add Google Cast when a standard or live video player with a ready-made skin should cast a compatible source. Use none when no extension is needed.
7. **Choose how to install.** This guide uses packaged modules, which need a bundler. Match the package manager to the project lockfile. For an existing HTML site without a build step, use CDN scripts instead.
8. **Return one explicit plan.** Confirm the choices once, then pass every applicable query parameter, including `extensions=none` when no extension is needed and `source-url=demo` when there is no media URL yet. Check that Defaulted options says none. Adapt conditional setup steps and existing paths before changing files.

### Compatible media sources by preset

- `video`: `html5-video`, `hls`, `dash`, `mux-video`, `vimeo`, `youtube`, `cloudflare`, `tiktok`, `twitch`
- `audio`: `html5-audio`, `mux-audio`, `spotify`
- `live-video`: `hls`, `mux-video`
- `live-audio`: `mux-audio`
- `background-video`: `background-video`, `hls-background-video`, `mux-background-video`

### App setup by framework

- `vue`: templates `vite`, `astro`, `nuxt`

### Installation pages

- [Packaged modules: React](https://videojs.org/docs/guides/installation/react.md)
- [Packaged modules: HTML](./installation.md)
- [Packaged modules: Vue](./installation-vue.md)
- [Packaged modules: Svelte](./installation-svelte.md)
- [Editable Shadcn source: React source](https://videojs.org/docs/guides/installation/shadcn.md?framework=react)
- [Editable Shadcn source: HTML source](./installation-shadcn.md)
- [CDN: HTML from jsDelivr](./installation-cdn.md)

## Selected options

- `method`: `packaged`
- `framework`: `vue`
- `project`: `existing`
- `preset`: `video`
- `skin`: `default`
- `media`: `html5-video`
- `extensions`: `none`
- `source-url`: `https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4`
- `package-manager`: `pnpm`
- `template`: `vite`

Defaulted options: project, preset, skin, source-url, media, extensions, template, package-manager.

## Reproduce or change these instructions

```sh
npx @videojs/cli@10.0.0-rc.3 agents init --method packaged --framework vue --project existing --preset video --skin default --media html5-video --extensions none --source-url https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4 --package-manager pnpm --template vite
```

## Install the packages

```bash
pnpm add @videojs/html@10.0.0-rc.3
```

## Register custom elements

Use the file that matches your Vue toolchain.

### `vite.config.ts`

_Merge this into the existing file, or create the file when it is missing._

```ts
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';

const videoJsElements = new Set(['video-player', 'video-skin']);

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => videoJsElements.has(tag),
        },
      },
    }),
  ],
});
```

## Add your player

Merge the example into the existing Vite route or component that should render the player, and preserve unrelated content.

### `src/components/VideoPlayer.vue`

_Merge this into the existing file, or create the file when it is missing._

```vue
<script setup lang="ts">
import '@videojs/html/video/player';
import '@videojs/html/video/skin';
</script>

<template>
  <!--
    The player element owns and shares state between the UI
    components and Media. Put layout on the skin or container.
   -->
  <video-player>
    <!--
      Skins contain the entire player UI and are easily swappable.
      Add the skin source to your project for full control over its
      UI components.
     -->
    <video-skin>
      <!--
          Media are players without UIs, handling networking
          and display of the media. They are easily swappable
          to handle different sources.
        -->
      <slot />
    </video-skin>
  </video-player>
</template>

<style>
video-skin {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
}
</style>
```

### `src/App.vue`

_Merge this into the existing file, or create the file when it is missing._

```vue
<script setup lang="ts">
import VideoPlayer from './components/VideoPlayer.vue';
</script>

<template>
  <VideoPlayer>
    <video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsinline></video>
  </VideoPlayer>
</template>
```

## Run your app

Start the development server and verify that the selected media plays.

_Long-running: start it in the background, verify the result, then stop it._

```bash
pnpm dev
```

> These are instructions only. Review and run the commands in your project; no files were modified.

That’s it! You now have a working Video.js player.

> **Note: Server rendering with Nuxt**
>
> Keep the element imports static. Nuxt renders the custom-element markup on the server, and the browser upgrades it when the page loads. If you need to read player state or call player methods, wait until Vue has mounted the element. See [Use Nuxt](./vue.md#use-nuxt) for client-only registration.

## Choose what to do next

### Customize

- [Use Video.js with Vue and Nuxt](./vue.md): Read player state, pass objects as properties, and configure Nuxt
- [Customize skins](./customize-skins.md#style-a-packaged-skin): Change colors, typography, sizing, and poster presentation
- [Architecture](./architecture.md): Learn how the player, skins, media, and UI components fit together

### Deploy

- [Browser support](./browser-support.md): Check supported browsers and rendering environments
- [TypeScript](./typescript.md): Configure TypeScript for Video.js packages
- [Bundlers](./bundlers.md): Check bundler compatibility
- [Content Security Policy](./content-security-policy.md): Configure Content Security Policy for your player
- [CDN](./cdn.md): See every bundle the CDN serves and the layout rules behind the URLs
- [Self-host the player](./self-hosting.md): Serve the player from your own origin for offline or restricted-network deployments

Something not quite right? You can [submit an issue](https://github.com/videojs/v10/issues) and ask for help, or explore [other support options](https://videojs.org/html5-video-support).