Astro JS Mux Video: using Custom Elements
Tags: webdev, javascript, video, astro
Published: 2022-08-15 12:26:50

---
title: "Astro JS Mux Video: using Custom Elements"
published: "true"
description: "Astro JS Mux Video: how you can add video to your site with the Mux HTML 5 Custom Elements video player. No framework needed!"
tags: "webdev, javascript, video, astro"
canonical_url: "https://rodneylab.com/astro-js-mux-video/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fydh1zwev5fu3phpbeoi.png"
---


## 🔥 HTML Elements

In this post on Astro JS Mux Video, we see how you can integrate the Mux HTML components video player into your site. We will also see that you can put a site together quite quickly with Astro.  And that is **without the need for learning frameworks** like React and Svelte.  Astro is principally a **static site builder**, thought it also support server rendered content.  It is aligned with the **islands architecture philosophy**. That is where components on a page can exist and hydrate independently of each other.  This is a recipe for fast sites.

Mux is a video streaming service. You upload your video in a single format and they sweat the details of making it work with user devices, be they Android or iOS mobile, Windows, Linux or MacOS desktop.  In fact, you can even have the player stream to **Chromecast** compatible devices.  The Mux Player is a **custom element** or Web Component.  The advantage of using **Web Components** is that, in theory, you can write your components once and use them in any web framework or with none at all, just like we will today!

There is minimal setup and you really can build out an Astro site using the Mux Custom Elements video player in a matter of minutes. So let&rsquo;s punch it!

## 🧱 Getting Started with Mux Video Player

You do not need a Mux account if you want to follow along.  As an aside, however, we see how to set one up in the <a href="https://plus.rodneylab.com/tutorials/svelte-video-blog">Svelte Video Blog Tutorial</a>.  To play a Mux video, you just need a Mux playback ID for the video.  We have a Mux promotional asset ID which we can use here for this purpose.

If you are following along, let&rsquo;s start by spinning up a new Astro project from the Terminal:

```shell
pnpm create astro@latest astro-mux-video
cd astro-mux-video
pnpm install
pnpm astro telemetry disable
pnpm install @mux/mux-video
pnpm run dev
```

At the time of writing the Mux player is still in beta testing.  Taking that into account, you should probably avoid using this setup for production projects.

In the block above we set up a new Astro project, disabled Astro telemetry (which is enabled by default) and installed the `@mux/mux-video` package in our project.  Ignore the `telemetry disable` step if you are OK with sending data to Astro.

## 📀 Video Component

The Mux Player is a Web Component.  All we need to do to make it work with Astro is export the NPM package in a JavaScript (or TypeScript) file.  The final step, to make sure it gets bundled with our site, is then to add a link to this file in a script tag.  We will do that on our home page which we will look at next.

Here&rsquo;s the code for the Video Component.  Make a `src/components` folder and create a `mux-video.ts` file in there:

```typescript
export * as MuxVideo from '@mux/mux-video';
```

Hope that wasn&rsquo;t too much typing 😅.

## 📼 Home Page

Essentially, as we just mentioned, you now just need to import the component in a script tag, then add a `mux-video` element in the Astro markup.  Here is a pared back version:

```astro
---
---

<html lang="en">

<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width" />
	<script>import '../components/mux-video.ts'</script>
	<script defer src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script> 
	<title>Mux Video Player in 🖖🏽 Astro</title>
</head>

<body>
	<main class="container">
    <mux-video playback-id="EcHgOK9coz5K4rjSwOkoE7Y7O01201YMIC200RI6lNxnhs" controls />
	</main>
</body>

</html>
```

In line `9` we make the import mentioned.  The `script` tag in line `10`, meanwhile adds **Chromecast support** &mdash; it&rsquo;s that simple! The player also supports Airplay (used by Apple devices).  We use minimal attributes on the `mux-video` element.  You see this web component does not look too different to a regular HTML component.  In fact we will see below, we can add the usual attributes we have on an HTML5 video element.  We use a Mux promotional video for the playback-id here.  When using your own video, You&rsquo;ll notice Mux generate two IDs.  It is the **public playback-id** rather than the master-access ID which you will need here. 

## 💫 Levelling Up

In the markup below, we take it up a level, adding attributes to reduce layout shift and video controls as well as some styling.  We learn more about <a aria-label="Learn about how to do video in the Svelte Video blog tutorial" href="https://plus.rodneylab.com/tutorials/svelte-video-blog">reducing cumulative shift and lazy-loading video</a> in the Svelte Video blog tutorial. We use SvelteKit there, though Astro works with Svelte components.

```astro
---
---

<html lang="en">

<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width" />
	<link rel="icon" href="/favicon.ico" sizes="any" />
	<link rel="icon" href="/icon.svg" type="image/svg+xml" />
	<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
	<link rel="manifest" href="/manifest.webmanifest" />
	<script>import '../components/mux-video.ts'</script>
		<script defer src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script> 
	<title>Mux Video Player in 🖖🏽 Astro</title>
</head>

<body>
	<main class="container">
		<h1 class="heading">Mux Video Player in 🖖🏽 Astro</h1>
		<figure>
			<div class="video-container">
				<mux-video playback-id="EcHgOK9coz5K4rjSwOkoE7Y7O01201YMIC200RI6lNxnhs" autoplay controls loop width="688px"
					height="387px" poster="/mux-video-player-poster.png" preload="none" primary-color="#31274a"
					secondary-color="#ff5d01">
				</mux-video>
			</div>
			<figcaption>VIDEO CREDIT: William Ehrendreich: <a href="https://www.videvo.net/profile/williamehrendreich/"
					rel="nofollow noopener noreferrer">www.videvo.net/profile/williamehrendreich/</a> </figcaption>
		</figure>
		<p>Boldly going where no video player has gone before&hellip;</p>
	</main>
</body>

</html>

<style>
	/* space-grotesk-500 - latin */
	@font-face {
		font-family: Space Grotesk;
		font-style: normal;
		font-weight: 500;
		src: local(''),
			url('/fonts/space-grotesk-v12-latin-500.woff2') format('woff2'),
			/* Chrome 26+, Opera 23+, Firefox 39+ */
			url('/fonts/space-grotesk-v12-latin-500.woff') format('woff');
		/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
	}

	/* space-grotesk-700 - latin */
	@font-face {
		font-family: Space Grotesk;
		font-style: normal;
		font-weight: bold;
		src: local(''),
			url('/fonts/space-grotesk-v12-latin-700.woff2') format('woff2'),
			/* Chrome 26+, Opera 23+, Firefox 39+ */
			url('/fonts/space-grotesk-v12-latin-700.woff') format('woff');
		/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
	}

	:root {
		/* mercury */
		--colour-light: hsl(0deg 5% 92%);

		/* green spring */
		--colour-alt: hsl(107deg 7% 74%);

		/* Xiketic */
		--colour-dark: hsl(240deg 100% 4%);

		/* BlazeOrange */
		--colour-theme: hsl(22 100% 50%);
	}

	body {
		margin: var(--spacing-0);
		min-height: 100vh;

		--spacing-0: 0;
		--spacing-1: 0.25rem;
		--spacing-2: 0.5rem;
		--spacing-12: 3rem;
		--spacing-18: 4.5rem;
		--max-width-wrapper: 48rem;

		--font-size-root: 16px;
		--font-size-1: 1rem;
		--font-size-3: 1.563rem;
		--font-size-6: 3.052rem;


		--font-weight-medium: 500;
		--font-weight-bold: 700;

		font-family: Space Grotesk;
		font-weight: var(--font-weight-medium);

		background-color: var(--colour-dark);
		/* CREDIT https://www.joshwcomeau.com/gradient-generator/ */
		background-image: linear-gradient(45deg,
				hsl(240deg 100% 4%) 0%,
				hsl(243deg 37% 10%) 27%,
				hsl(246deg 32% 15%) 41%,
				hsl(253deg 31% 20%) 53%,
				hsl(285deg 36% 26%) 64%,
				hsl(327deg 60% 38%) 75%,
				hsl(347deg 72% 51%) 86%,
				hsl(22deg 100% 50%) 99%);
	}

	a {
		color: var(--colour-theme)
	}

	.container {
		color: var(--colour-alt);
		width: min(100% - var(--spacing-12), var(--max-width-wrapper));
		margin: var(--spacing-18) auto;
		font-size: var(--font-size-3);
		text-align: right;
	}

	.heading {
		color: var(--colour-light);
		text-align: center;
		font-size: var(--font-size-6);
		font-weight: var(--font-weight-bold);
		margin-bottom: var(--spacing-18)
	}

	mux-video {
		background-color: var(--colour-theme);
	}

	.video-container,
	mux-video {
		max-width: var(--max-width-full);
		aspect-ratio: 16 / 9;
	}

	figure {
		margin-bottom: var(--spacing-12);
		text-align: left;
	}

	figcaption {
		font-size: var(--font-size-1);
		margin-block: var(--spacing-2);
	}
</style>
```
I added self-hosted fonts here.  For this to work, you need to <a aria-label="Download fonts from google-webfonts-helper" href="https://google-webfonts-helper.herokuapp.com/api/fonts/space-grotesk?download=zip&subsets=latin&variants=500,700&formats=woff,woff2">download them from google-webfonts-helper</a>, then extract the zip and place the `.woff` and `.woff2` files in a new `public/fonts` folder in your project.

There is a <a aria-label="Open the live demo site" href="https://astro-mux-player.rodneylab.com/">live demo</a> if you want to see the full thing in action.

![Astro JS Mux Video: screenshot of demo site shows a video primed to play, currently displaying a poster image reading Boldly going where no video player has gone before.  Video controls are visible](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eordg5e5430e4ou6z7yx.png)

## 🙌🏽 Astro JS Mux Video: Wrapping Up

We have taken a look at the Mux custom elements video player in this post.  In particular, we saw:

- how to **add the mux-video to an Astro site**,
- linking your Mux video assets in the mux-video player,
- that Astro can work **without a framework** like React or Svelte.

We have just scratched the surface of what we can do with the Mux custom elements player in this Astro JS Mux video post.  The video works fine on this simple page, where it is the main content. However, for video lower down the page, you might consider using a Svelte or React component.  Svelte, especially, can make it easy to add lazy loading.  This is important for making your page load faster.  If you prefer to stay frameworkless, many modern browsers have <a aria-label="Read about browser lazy loading A P Is" href="https://web.dev/fast/#lazy-load-images-and-video">lazy loading support</a> and you can access this adding a `loading="lazy"` attribute.  Also <a aria-label="Open Mux video player docs" href="https://docs.mux.com/guides/video/mux-player">check out Mux docs for more customisations</a>.

Take a look at the full project code on the <a aria-label="Open the Astro blog Markdown starter in Stack Blitz" href="https://github.com/rodneylab/astro/tree/main/demos/astro-mux-player">Rodney Lab GitHub page</a>.  I hope you found this article useful and am keen to hear how you will the starter on your own projects as well as possible improvements.

## 🙏🏽 Astro JS Mux Video: Feedback

Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please <a aria-label="Support Rodney Lab via Buy me a Coffee" href="https://rodneylab.com/giving/">consider supporting me through Buy me a Coffee</a>.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via <a aria-label="Reach out on Twitter" href="https://twitter.com/messages/compose?recipient_id=1323579817258831875">@askRodney</a> on Twitter and also <a aria-label="Contact Rodney Lab via Telegram" href="https://t.me/askRodney">askRodney on Telegram</a>. Also, see <a aria-label="Get in touch with Rodney Lab" href="https://rodneylab.com/contact">further ways to get in touch with Rodney Lab</a>. I post regularly on <a aria-label="See posts on Astro" href="https://rodneylab.com/tags/astro/">Astro</a> as well as <a aria-label="See posts on svelte kit" href="https://rodneylab.com/tags/sveltekit/">SvelteKit</a>. Also <a aria-label="Subscribe to the Rodney Lab newsletter" href="https://rodneylab.com/about/#newsletter">subscribe to the newsletter to keep up-to-date</a> with our latest projects.