diff --git a/site/src/components/docs/demos/cast-button/html/css/BasicUsage.astro b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.astro
new file mode 100644
index 00000000..c515bacd
--- /dev/null
+++ b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.astro
@@ -0,0 +1,9 @@
+---
+import HtmlDemo from '@/components/docs/demos/HtmlDemo.astro';
+import html from './BasicUsage.html?raw';
+---
+
+
+
diff --git a/site/src/components/docs/demos/cast-button/html/css/BasicUsage.css b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.css
new file mode 100644
index 00000000..fb784796
--- /dev/null
+++ b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.css
@@ -0,0 +1,39 @@
+.video-player {
+ position: relative;
+ display: block;
+}
+
+.video-player video {
+ width: 100%;
+}
+
+.media-cast-button {
+ position: absolute;
+ right: 10px;
+ bottom: 10px;
+ padding-block: 8px;
+ padding-inline: 20px;
+ color: black;
+ cursor: pointer;
+ background: rgba(255, 255, 255, 0.7);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ border-radius: 9999px;
+ backdrop-filter: blur(10px);
+}
+
+.media-cast-button[data-availability="unsupported"] {
+ display: none;
+}
+
+.media-cast-button .connected {
+ display: none;
+}
+.media-cast-button .disconnected {
+ display: none;
+}
+.media-cast-button[data-cast-state="connected"] .connected {
+ display: inline;
+}
+.media-cast-button:not([data-cast-state="connected"]) .disconnected {
+ display: inline;
+}
diff --git a/site/src/components/docs/demos/cast-button/html/css/BasicUsage.html b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.html
new file mode 100644
index 00000000..7badc5e9
--- /dev/null
+++ b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Stop casting
+ Start casting
+
+
+
diff --git a/site/src/components/docs/demos/cast-button/html/css/BasicUsage.ts b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.ts
new file mode 100644
index 00000000..77a1999f
--- /dev/null
+++ b/site/src/components/docs/demos/cast-button/html/css/BasicUsage.ts
@@ -0,0 +1,3 @@
+import '@videojs/html/video/player';
+import '@videojs/html/media/hls-video';
+import '@videojs/html/ui/cast-button';
diff --git a/site/src/components/docs/demos/cast-button/react/css/BasicUsage.css b/site/src/components/docs/demos/cast-button/react/css/BasicUsage.css
new file mode 100644
index 00000000..ca5562b7
--- /dev/null
+++ b/site/src/components/docs/demos/cast-button/react/css/BasicUsage.css
@@ -0,0 +1,25 @@
+.media-container {
+ position: relative;
+}
+
+.media-container video {
+ width: 100%;
+}
+
+.media-cast-button {
+ position: absolute;
+ right: 10px;
+ bottom: 10px;
+ padding-block: 8px;
+ padding-inline: 20px;
+ color: black;
+ cursor: pointer;
+ background: rgba(255, 255, 255, 0.7);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ border-radius: 9999px;
+ backdrop-filter: blur(10px);
+}
+
+.media-cast-button[data-availability="unsupported"] {
+ display: none;
+}
diff --git a/site/src/components/docs/demos/cast-button/react/css/BasicUsage.tsx b/site/src/components/docs/demos/cast-button/react/css/BasicUsage.tsx
new file mode 100644
index 00000000..72ac1769
--- /dev/null
+++ b/site/src/components/docs/demos/cast-button/react/css/BasicUsage.tsx
@@ -0,0 +1,27 @@
+import { CastButton, createPlayer } from '@videojs/react';
+import { HlsVideo } from '@videojs/react/media/hls-video';
+import { videoFeatures } from '@videojs/react/video';
+
+const Player = createPlayer({ features: videoFeatures });
+
+export default function BasicUsage() {
+ return (
+
+
+
+ (
+
+ )}
+ />
+
+
+ );
+}
diff --git a/site/src/content/docs/concepts/cast.mdx b/site/src/content/docs/concepts/cast.mdx
new file mode 100644
index 00000000..a3907ee5
--- /dev/null
+++ b/site/src/content/docs/concepts/cast.mdx
@@ -0,0 +1,225 @@
+---
+title: Google Cast
+description: How to add Chromecast support to your Video.js player — lazy SDK loading, session lifecycle, and configuration options
+---
+
+import FrameworkCase from '@/components/docs/FrameworkCase.astro';
+import DocsLink from '@/components/docs/DocsLink.astro';
+import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';
+import Aside from '@/components/Aside.astro';
+
+Video.js has built-in Google Cast support for HLS and DASH media elements. When a Chromecast device is on the same network, a Cast button appears automatically in Chromium browsers. Tapping it starts a session that moves playback to the TV while the browser stays in control.
+
+
+
+## How Cast works
+
+Cast uses a **sender / receiver** model:
+
+- **Sender** — the browser tab. It controls playback commands (play, pause, seek, volume) and sends a load request to the receiver with the source URL and metadata.
+- **Receiver** — the Chromecast device running the default media receiver application (or a custom receiver you configure).
+
+### Session lifecycle
+
+A Cast session moves through three states, exposed via the Remote Playback feature:
+
+| State | Meaning |
+|---|---|
+| `'disconnected'` | No active session |
+| `'connecting'` | User accepted; session negotiating |
+| `'connected'` | Receiver is playing |
+
+While `connected`, the media element's `play`, `pause`, `currentTime`, `volume`, `muted`, and `playbackRate` all proxy to the Cast receiver. Local playback is suspended.
+
+### The lazy-loaded SDK
+
+The Cast SDK (`cast_sender.js`) is injected into the page as a `