How to add a YouTube embed in the Studio, and render it on frontends
There are times when you want to embed a video in your rich text content. Usually you would paste the HTML embed code into the editor and move along. With Portable Text, however, you want to make sure that your content is structured, and you don't embed too many assumptions about presentation in it. Maybe you want to use this video in a native app, or rather use a specialized component for it in your frontend(s).
In this tutorial we will cover how to add a custom YouTube block into your schema and the editor, how to add a custom preview component for it, and and how to serialize it in the frontend. We will also look at how you can add a custom paste handler, so that your editors can copy-paste a YouTube link right into the editor, and have it stored as the custom block.
The main thing we are interested in when doing a YouTube embed, is not the embed code in itself, but a way to identify what video it is, that is, it's ID. The ID is included in the video URL, so if we for example have this URL, https://www.youtube.com/watch?v=asENbq3s1m8&feature=youtu.be, the ID is asENbq3s1m8.
Now, we could have asked our editors to find this ID and only put that into Sanity, but that seems a bit too much to ask, and isn't always easy since YouTube URLs can contain a lot of parameters. We will assume that we can work with an URL and find the ID programatically whereever we want to show the video.
We'll make a very simple schema to begin with. An object we call youtube, with a field called url. You can extend this later if you want to for example specify a time stamp, or other things.
Now you can access the new YouTube field in the editor’s toolbar where you can paste in a YouTube URL. However, it would be nice to get an actual preview of the video that you want to embed. So let’s add that.
You’re maybe already familiar with how to configure previews with Sanity. First you select the fields you want to get content from. You can assign them to variables like title, subtitle, and media and let the Studio figure out the rest. Or you can return a prepare function if you want to more control over what goes in to the slots.
However, you can also pass a React component and gain full control over what’s rendered. It still gets the variables that you define in select as props. For the YouTube preview, we’re going to use a pre-built component called react-youtube, as well as a package called get-youtube-id to first get the ID from the URL, and return and render the embed in the editor.
We start by installing the dependencies we need by running npm install react-youtube get-youtube-id in the root folder. Then we open the youtube.js file, and add the following to it:
This pretty much mirrors what you would do in a React frontend as well. And speaking of frontends, let's take a closer look at how this should be implemented.
Render the YouTube embed in a frontend
When you insert a YouTube embed in the rich text editor, it will be added as a custom block in the Portable Text array. If you are not familiar with how Portable Text works, you can learn more in this introduction. You can also tag along with this tutorial and follow the code examples if you just want to get a feel for it.
To render custom blocks, as the YouTube embed is, you have to add a serializer to the Portable Text package for React (currently called @sanity/block-content-to-react). If you don't have this in your project from before, you'll have to install it by running npm install @sanity/block-content-to-react in your command line.
Next up is installing a component to show the YouTube video, and a package to suss out the id for the YouTube video from its URL. In this case we’re going to install the same dependencies, and add pretty much the same code, as we did in the studio. So first, run npm install react-youtube get-youtube-id to add the dependencies in your frontend project.
And where you want to be able to output this YouTube embed, do the following:
To render custom blocks, as the YouTube embed is, you have to add a serializer to the Portable Text package for Vue (currently called sanity-block-vue-component). If you don't have this in your project from before, you'll have to install it by running npm installl sanity-block-vue-component in your command line. We need something for YouTube as well, so let's run npm install vue-youtube and add it to where we mount our Vue app:
Then we'll create a new YouTube.vue file for our component with the code we need to render the video. We'll add the same package as we used in the studio to get the ID from the URL (npm install get-youtube-id):