Products
Products
Video Hosting
Upload and manage your videos in a centralized video library.
Image Hosting
Upload and manage all your images in a centralized library.
Galleries
Choose from 100+templates to showcase your media in style.
Video Messaging
Record, and send personalized video messages.
CincoTube
Create your own community video hub your team, students or fans.
Pages
Create dedicated webpages to share your videos and images.
Live
Create dedicated webpages to share your videos and images.
For Developers
Video API
Build a unique video experience.
DeepUploader
Collect and store user content from anywhere with our file uploader.
Solutions
Solutions
Enterprise
Supercharge your business with secure, internal communication.
Townhall
Webinars
Team Collaboration
Learning & Development
Creative Professionals
Get creative with a built in-suite of editing and marketing tools.
eCommerce
Boost sales with interactive video and easy-embedding.
Townhall
Webinars
Team Collaboration
Learning & Development
eLearning & Training
Host and share course materials in a centralized portal.
Sales & Marketing
Attract, engage and convert with interactive tools and analytics.
"Cincopa helped my Enterprise organization collaborate better through video."
Book a Demo
Resources
Resources
Blog
Learn about the latest industry trends, tips & tricks.
Help Centre
Get access to help articles FAQs, and all things Cincopa.
Partners
Check out our valued list of partners.
Product Updates
Stay up-to-date with our latest greatest features.
Ebooks, Guides & More
Customer Stories
Hear how we've helped businesses succeed.
Boost Campaign Performance Through Video
Discover how to boost your next campaign by using video.
Download Now
Pricing
Watch a Demo
Demo
Login
Start Free Trial
When working with rich content in Sanity, there are times when you need to embed YouTube videos directly inside your content, whether it's for a blog post or a documentation site. While it’s technically possible to paste raw HTML embed codes, this approach mixes presentation with content and makes it difficult to reuse or manage consistently across different frontends. A better solution is to store only the essential video data in Sanity (such as the YouTube URL) and let your frontend components decide how to render it. This improves flexibility, ensures consistent styling, and keeps your content structure clean and future-proof. Add a YouTube Schema Type To embed a YouTube video, an important thing is the video’s ID. This ID is part of the video URL. For example, in this link: https://www.youtube.com/watch?v=asENbq3s1m8 The ID is asENbq3s1m8 . However, asking content editors to extract and paste just the ID can easily lead to mistakes—especially when URLs have extra parameters or different formats. Instead, we’ll let them paste the full URL and handle ID extraction in code. To start, define a custom schema type for YouTube videos in your Sanity Studio: // ./schemaTypes/youTubeType/index.ts import {defineType, defineField} from 'sanity' import {PlayIcon} from '@sanity/icons' export const youTubeType = defineType({ name: 'youtube', type: 'object', title: 'YouTube Embed', icon: PlayIcon, fields: [ defineField({ name: 'url', type: 'url', title: 'YouTube video URL', }), ] }) Explanation : preview.select.title : Maps the video URL to the preview title, so the YouTube URL is passed into the YouTubePreview component. preview.components.preview : Overrides the default Sanity preview with a custom React component ( YouTubePreview ).
: Renders the YouTube video in the frontend using the video URL stored in Sanity. getIdFromUrl : A helper function from vue-youtube that extracts the video ID from a full YouTube URL. components.types.youtube : Defines how to render the youtube block type when using @portabletext/vue in a Vue app. Now import and register this type in your main schema file so it’s available across your project: // ./schemaTypes/index.ts import {youtube} from './youTubeType' export const schemaTypes = [ // other schema types youtube ] By creating a custom schema for YouTube, you separate concerns: the CMS stores clean video data, and the frontend controls how the video is displayed. This makes your system more maintainable and easier to scale. Add to Block Content To allow YouTube videos inside rich text fields (like documentation pages), you’ll need to extend your block content schema. Here’s how you can add the YouTube type to Portable Text: // ./schemaTypes/blockContentType.ts import {defineType, defineArrayMember} from 'sanity' export const blockContentType = defineType({ name: 'blockContent', type: 'array', title: 'Body', of: [ defineArrayMember({ type: 'block' }), defineArrayMember({ type: 'youTube' }) ] }) Explanation : blockContentType : The schema definition for rich text content, allowing both text blocks and YouTube embeds. defineType : A Sanity function used to define a new custom schema type. defineArrayMember : A helper used to declare the types of content allowed within an array field. type: 'youTube' : Allows YouTube embeds (defined in a custom schema) to be inserted into the rich text content. This allows content creators to insert YouTube videos directly from the editor UI and improve usability without touching raw code or embed snippets. Add a Block Preview Using ReactPlayer for Editor Clarity By default, Sanity only shows the URL in the editor, which can be unclear and frustrating. This is especially true when working with multiple videos. To enhance the editorial experience, you can provide a live preview of the embedded video using ReactPlayer to support YouTube and other platforms. Example : Install the Required Dependencies npm install react-player @sanity/ui Then, create a preview component that renders the video player using the pasted URL: // ./schemaTypes/youTubeType/YouTubePreview.tsx import type {PreviewProps} from 'sanity' import {Flex, Text} from '@sanity/ui' import YouTubePlayer from 'react-player/youtube' export function YouTubePreview({title: url}: PreviewProps) { return (
{typeof url === 'string' ?
:
Add a YouTube URL
}
) } Explanation : PreviewProps : The type definition for Sanity preview component props, used to ensure correct structure for preview data. YouTubePlayer : A React component from react-player/youtube used to render the YouTube video preview based on the provided URL. typeof url === 'string' ?
:
Add a YouTube URL
: A conditional rendering logic that shows the video if a valid URL is present, or fallback text if not. Next, update your schema to use this preview: // ./schemaTypes/youTubeType/index.ts import {defineType, defineField} from 'sanity' import {PlayIcon} from '@sanity/icons' import {YouTubePreview} from './YouTubePreview' export const youtube = defineType({ name: 'youtube', type: 'object', title: 'YouTube Embed', icon: PlayIcon, fields: [ defineField({ name: 'url', type: 'url', title: 'YouTube video URL', }), ], preview: { select: {title: 'url'}, }, components: { preview: YouTubePreview, }, }) Explanation : fields: [...] : Defines the set of fields included in the YouTube object schema. name: 'url' : The internal identifier for the field storing the full YouTube video URL. title: 'YouTube video URL' : The label shown to content editors when entering the video URL. preview.select.title : Maps the URL field to the title property used in the preview component. components.preview : Overrides the default preview with the custom YouTubePreview component. Providing this visual feedback helps content editors verify that they’ve pasted the correct video and reduces friction and mistakes during content creation. Render the YouTube Embed in a Frontend Sanity stores YouTube embeds as custom blocks inside the Portable Text array. To display them correctly on your website or app, you’ll need to define a custom serializer that knows how to render the YouTube block. React Example If you don’t have it yet, install the Portable Text React package and React Player: npm install @portabletext/react react-player Then, create a reusable component that renders Portable Text with the YouTube serializer: // src/components/Body.tsx import React from 'react' import {PortableText} from '@portabletext/react' import ReactPlayer from 'react-player' const serializers = { types: { youtube: ({value}) =>
} } export default function Body({blocks}) { return
} Explanation : serializers.types.youtube : A custom serializer that tells PortableText how to render youtube block types using ReactPlayer. value.url : The YouTube video URL stored in the Sanity document, passed to ReactPlayer for playback. Body({blocks}) : A React component that receives blocks (Portable Text content) as a prop and renders it using PortableText. components={serializers} : Passes the custom serializers to PortableText, enabling support for embedded YouTube videos. Using ReactPlayer here ensures consistent video behavior across devices and browsers, and allows you to maintain a single rendering strategy for all your rich content blocks. Vue Example To integrate YouTube embeds in Vue, Install the packages: npm install @portabletext/vue vue-youtube Create a Vue component for the video:
Explanation : getIdFromUrl : A utility function from vue-youtube that extracts the video ID from a full YouTube URL. videoId() : A computed property that returns the extracted YouTube video ID using getIdFromUrl .
: A Vue component that renders the embedded YouTube video using the extracted video ID. Then, configure Portable Text rendering:
Explanation : components.types.youtube : A custom block renderer that tells PortableText to use the YouTube component for youtube block types.
: Renders the provided Portable Text content using the custom YouTube renderer. The same pattern works for other frameworks like Svelte or Astro; just adapt the serializer to match the framework’s conventions.