Troubleshooting custom preview of YouTube video in Sanity.io
3 replies
Last updated: Mar 30, 2023
C
Hello everyone! π
Im trying to make a custom preview of a embed youtube video but it doesnt work. What am i doing wrong? Its version 3.
Im trying to make a custom preview of a embed youtube video but it doesnt work. What am i doing wrong? Its version 3.
import { defineField, defineType } from "sanity"; import getYouTubeId from "get-youtube-id"; interface Youtube { _type: "youtube"; url: string; } interface PreviewProps { media: React.ReactNode; title: string; } const YoutubePreview: React.FC<PreviewProps> = ({ media, title }) => { const id = getYouTubeId(media as string); const embedUrl = `<https://www.youtube.com/embed/${id}>`; return ( <div> <h2>{title}</h2> <iframe width="560" height="315" src={embedUrl} title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen ></iframe> </div> ); }; export default defineType({ name: "youtube", type: "object", fields: [ { name: "url", title: "URL", type: "url", validation: (Rule) => Rule.required(), }, ], preview: { select: { url: "url", }, prepare(selection) { const { url } = selection; if (!url) { return { title: "Missing YouTube URL", media: <div>Missing YouTube URL</div>, }; } const id = getYouTubeId(url); const media = ( <img src={`<https://i.ytimg.com/vi/${id}/hqdefault.jpg>`} alt="Video thumbnail" /> ); return { title: "YouTube Video", media, }; }, component: YoutubePreview, }, }) as unknown as Youtube;
Mar 21, 2023, 11:22 AM
S
Ah you dont want to just define the preview.media (but as you can see it does work in general π ), but define the preview component for the whole type. At the moment youβre only defining a custom component for media.you need to define this on the type bot in the preview, but I would still select and prepare values as do
π
π
components:{ preview: YoutubePreview, }
Mar 21, 2023, 12:05 PM
J
HI, is there a full example of this ? All examples i found are on v2 π
Mar 30, 2023, 6:10 PM
J
ok got it`Μ`import {defineType, defineArrayMember} from 'sanity'
/**
* This is the schema definition for the rich text fields used for
* for this blog studio. When you import it in schemas.js it can be
* reused in other parts of the studio with:
* {
* name: 'someName',
* title: 'Some title',
* type: 'blockContent'
* }
*/
export default defineType({
title: 'Block Content',
name: 'blockContent',
type: 'array',
of: [
defineArrayMember({
title: 'Block',
type: 'block',
// Styles let you set what your user can mark up blocks with. These
// correspond with HTML tags, but you can set any title or value
// you want and decide how you want to deal with it where you want to
// use your content.
styles: [
{title: 'Normal', value: 'normal'},
{title: 'H1', value: 'h1'},
{title: 'H2', value: 'h2'},
{title: 'H3', value: 'h3'},
{title: 'H4', value: 'h4'},
{title: 'Quote', value: 'blockquote'},
],
lists: [{title: 'Bullet', value: 'bullet'}],
// Marks let you mark up inline text in the block editor.
marks: {
// Decorators usually describe a single property β e.g. a typographic
// preference or highlighting by editors.
decorators: [
{title: 'Strong', value: 'strong'},
{title: 'Emphasis', value: 'em'},
],
// Annotations can be any object structure β e.g. a link or a footnote.
annotations: [
{
name: 'link',
type: 'object',
title: 'External link',
fields: [
{
name: 'href',
type: 'url',
title: 'URL',
},
{
title: 'Ouvrir dans un nouvel onglet',
name: 'blank',
type: 'boolean',
},
{
title: 'Nofollow',
name: 'nofollow',
type: 'boolean',
},
{
title: 'Sponsored',
name: 'sponsored',
type: 'boolean',
},
{
title: 'User generated content',
name: 'ugc',
type: 'boolean',
},
{
title: 'Cloaked',
name: 'cloaked',
type: 'boolean',
},
],
},
{
name: 'internalLink',
type: 'object',
title: 'Internal link',
fields: [
{
name: 'reference',
type: 'reference',
title: 'Reference',
to: [
{type: 'post'},
// other types you may want to link to
],
},
{
name: 'obfuscation',
title: 'obfuscation',
type: 'boolean',
},
],
},
],
},
}),
// You can add additional types here. Note that you can't use
// primitive types such as 'string' and 'number' in the same array
// as a block type.
defineArrayMember({
type: 'image',
options: {hotspot: true},
}),
defineArrayMember({
type: 'youtube',
}),
],
})
/**
* This is the schema definition for the rich text fields used for
* for this blog studio. When you import it in schemas.js it can be
* reused in other parts of the studio with:
* {
* name: 'someName',
* title: 'Some title',
* type: 'blockContent'
* }
*/
export default defineType({
title: 'Block Content',
name: 'blockContent',
type: 'array',
of: [
defineArrayMember({
title: 'Block',
type: 'block',
// Styles let you set what your user can mark up blocks with. These
// correspond with HTML tags, but you can set any title or value
// you want and decide how you want to deal with it where you want to
// use your content.
styles: [
{title: 'Normal', value: 'normal'},
{title: 'H1', value: 'h1'},
{title: 'H2', value: 'h2'},
{title: 'H3', value: 'h3'},
{title: 'H4', value: 'h4'},
{title: 'Quote', value: 'blockquote'},
],
lists: [{title: 'Bullet', value: 'bullet'}],
// Marks let you mark up inline text in the block editor.
marks: {
// Decorators usually describe a single property β e.g. a typographic
// preference or highlighting by editors.
decorators: [
{title: 'Strong', value: 'strong'},
{title: 'Emphasis', value: 'em'},
],
// Annotations can be any object structure β e.g. a link or a footnote.
annotations: [
{
name: 'link',
type: 'object',
title: 'External link',
fields: [
{
name: 'href',
type: 'url',
title: 'URL',
},
{
title: 'Ouvrir dans un nouvel onglet',
name: 'blank',
type: 'boolean',
},
{
title: 'Nofollow',
name: 'nofollow',
type: 'boolean',
},
{
title: 'Sponsored',
name: 'sponsored',
type: 'boolean',
},
{
title: 'User generated content',
name: 'ugc',
type: 'boolean',
},
{
title: 'Cloaked',
name: 'cloaked',
type: 'boolean',
},
],
},
{
name: 'internalLink',
type: 'object',
title: 'Internal link',
fields: [
{
name: 'reference',
type: 'reference',
title: 'Reference',
to: [
{type: 'post'},
// other types you may want to link to
],
},
{
name: 'obfuscation',
title: 'obfuscation',
type: 'boolean',
},
],
},
],
},
}),
// You can add additional types here. Note that you can't use
// primitive types such as 'string' and 'number' in the same array
// as a block type.
defineArrayMember({
type: 'image',
options: {hotspot: true},
}),
defineArrayMember({
type: 'youtube',
}),
],
})
Mar 30, 2023, 6:21 PM
Sanityβ build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.