How to use Vidstack with Astro


Integrating Vidstack Video Player with Astro: Three Approaches Compared
Vidstack is a modern, headless video player library that offers excellent customization and performance. When working with Astro, you have several ways to integrate Vidstack into your project. In this post, we'll explore three different approaches, each with their own advantages and trade-offs.
What is Vidstack?
Vidstack is a flexible, framework-agnostic video player that provides both web components and framework-specific integrations. It's designed to be lightweight, accessible, and highly customizable, making it an excellent choice for modern web applications.
Why Astro?
Astro's component-based architecture and excellent performance characteristics make it a great choice for content-heavy sites that need video integration. Its ability to work with multiple frameworks and render static HTML by default aligns well with modern web development practices.
Solution 1: Web Components Approach
This approach uses Vidstack's native web components directly in your Astro templates.
---
// video.astro
import 'vidstack/player/styles/default/theme.css'
import 'vidstack/player/styles/default/layouts/video.css'
import Layout from '../layouts/Layout.astro';
const src = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
const poster = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg"
const title = "Big Buck Bunny";
---
<script>
import 'vidstack/player'
import 'vidstack/player/layouts/default'
import 'vidstack/player/ui'
</script>
<Layout>
<media-player title={title} src={src} volume={0.2} controls={false} playsInline>
<media-provider>
<media-poster class="vds-poster" src={poster}></media-poster>
</media-provider>
<media-video-layout></media-video-layout>
</media-player>
</Layout>
Pros:
Framework Agnostic: Works natively with Astro without requiring additional framework integrations
Lightweight: No additional JavaScript framework overhead
Standards Compliant: Uses native web components that work across all modern browsers
Simple Setup: Minimal configuration required, just import and use
Server-Side Rendering: Works seamlessly with Astro's SSR capabilities
Future Proof: Web components are a web standard and will continue to be supported
Cons:
Limited TypeScript Support: Web components don't provide the same level of TypeScript integration as framework-specific components
Less Customization: Harder to create complex custom controls compared to framework-specific approaches
Event Handling: Managing complex event listeners can be more verbose
State Management: No built-in reactive state management like you'd get with framework components
Learning Curve: Requires understanding of web component APIs and lifecycle
Solution 2: React Integration
This approach uses Vidstack's React components within Astro's React integration.
---
// video.astro
import 'vidstack/player/styles/default/theme.css'
import 'vidstack/player/styles/default/layouts/video.css'
import Layout from '../layouts/Layout.astro';
import SimpleVideoPlayer from '../components/SimpleVideoPlayer';
const src = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
const poster = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg"
const title = "Big Buck Bunny";
---
<Layout>
<SimpleVideoPlayer client:load
src={src}
poster={poster}
title={title} />
</Layout>
// SimpleVideoPlayer.tsx
import React from 'react';
import {
MediaPlayer,
MediaProvider,
Poster,
Track,
type MediaPlayerInstance,
type MediaCanPlayDetail,
type MediaCanPlayEvent,
type MediaPlayerProps,
} from '@vidstack/react';
import {
defaultLayoutIcons,
DefaultAudioLayout,
DefaultVideoLayout,
} from '@vidstack/react/player/layouts/default';
interface SimpleVideoPlayerProps {
src: string;
poster?: string;
title?: string;
className?: string;
subtitles?: Array<{
src: string;
label: string;
language: string;
default?: boolean;
}>;
}
export function SimpleVideoPlayer({
src,
poster,
title = "Video Player",
className = "",
subtitles = []
}: SimpleVideoPlayerProps) {
const playerRef = React.useRef<MediaPlayerInstance>(null);
function onCanPlay(detail: MediaCanPlayDetail, nativeEvent: MediaCanPlayEvent) {
console.log('Player is ready for playback');
}
return (
<MediaPlayer
className={`w-full max-w-4xl mx-auto ${className}`}
title={title}
src={src}
crossOrigin
playsInline
onCanPlay={onCanPlay}
ref={playerRef}
>
<MediaProvider>
{poster && <Poster className="vds-poster" src={poster} alt={`${title} poster`} />}
{subtitles.map((subtitle, index) => (
<Track
key={index}
src={subtitle.src}
kind="subtitles"
label={subtitle.label}
lang={subtitle.language}
default={subtitle.default}
/>
))}
</MediaProvider>
<DefaultAudioLayout icons={defaultLayoutIcons} />
<DefaultVideoLayout icons={defaultLayoutIcons} />
</MediaPlayer>
);
}
export default SimpleVideoPlayer;
Pros:
Full TypeScript Support: Excellent type safety and autocomplete support
Rich Component API: Access to all React-specific features and hooks
Advanced State Management: Easy integration with React state management solutions
Custom Components: Simple to create complex custom controls and layouts
Developer Experience: Better debugging tools and development experience
Event Handling: Clean, declarative event handling with React patterns
Ecosystem: Access to the entire React ecosystem for additional functionality
Cons:
Bundle Size: Adds React runtime overhead to your application
Hydration Complexity: Requires client-side hydration, adding complexity
Framework Dependency: Ties your video player to React specifically
Build Configuration: Requires setting up React integration in Astro
Performance: Additional JavaScript bundle size and runtime overhead
SSR Limitations: Some React features may not work with Astro's SSR by default
Solution 3: CDN Approach
This approach loads Vidstack directly from a CDN, minimizing build complexity.
---
// video.astro
import Layout from '../layouts/Layout.astro';
const src = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
const poster = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg"
const title = "Big Buck Bunny";
---
<link rel="stylesheet" href="https://cdn.vidstack.io/player/theme.css" />
<link rel="stylesheet" href="https://cdn.vidstack.io/player/video.css" />
<script is:inline src="https://cdn.vidstack.io/player" type="module"></script>
<Layout>
<media-player title={title} src={src} volume={0.2} controls={false} playsInline>
<media-provider>
<media-poster class="vds-poster" src={poster}></media-poster>
</media-provider>
<media-video-layout></media-video-layout>
</media-player>
</Layout>
Pros:
Zero Build Configuration: No need to configure bundlers or install npm packages
Fast Setup: Get started immediately without any setup
CDN Benefits: Leverage CDN caching and global distribution
Version Pinning: Easy to pin to specific versions via CDN URLs
Minimal Dependencies: No npm dependencies to manage or update
Quick Prototyping: Perfect for rapid prototyping and demos
Cons:
Network Dependency: Requires internet connection and relies on external CDN availability
Version Control: Harder to manage versions and ensure consistency across environments
Bundle Optimization: No opportunity for tree shaking or bundle optimization
Offline Development: Cannot work offline or in restricted network environments
Security Concerns: Potential security risks from loading external scripts
Performance Unpredictability: CDN performance can vary based on geographic location and network conditions
No TypeScript: Limited or no TypeScript support when loading from CDN
Which Approach Should You Choose?
Choose Web Components (Solution 1) if:
You want the simplest, most straightforward integration
You're building a mostly static site with minimal interactivity
You prefer standards-based solutions
You want to avoid additional framework dependencies
Bundle size is a primary concern
Choose React Integration (Solution 2) if:
You're already using React elsewhere in your Astro project
You need complex, interactive video player controls
TypeScript support is important to your development workflow
You want the best developer experience and tooling
You're building a highly interactive application
Choose CDN Approach (Solution 3) if:
You're prototyping or building a simple demo
You want to get started quickly without any build setup
You're working in an environment where you can't install npm packages
Network connectivity is reliable and CDN performance is acceptable
You don't need advanced bundling optimizations
Conclusion
All three approaches have their place depending on your specific needs. The Web Components approach offers the best balance of simplicity and performance for most Astro projects. The React integration provides the most powerful development experience if you're already committed to React. The CDN approach is perfect for quick setups and prototypes but should be used cautiously in production environments.
Consider your project's requirements, team expertise, and long-term maintenance needs when choosing between these approaches. You can always start with one approach and migrate to another as your needs evolve.
Subscribe to my newsletter
Read articles from Marius B. directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by