👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

Adding a Vimeo schema to the Sanity blog template for Sveltekit integration

3 replies
Last updated: Sep 30, 2022
Good morning. I have added a couple additional types to the
bodyPortableText
schema that comes with the Sanity blog template. I’ve got it working in Studio, but I can’t figure out how to render it in Sveltekit. Here’s the schema in studio:
// studio/schemas/bodyPortableText.js

export default {
  name: 'bodyPortableText',
  type: 'array',
  title: 'Post body',
  of: [
    {
      type: 'block',
      title: 'Block',
      // Styles let you set what your user can mark up blocks with. These
      // corrensponds 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' },
        { title: 'Number', value: 'number' },
      ],
      // 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: 'URL',
            fields: [
              {
                title: 'URL',
                name: 'href',
                type: 'url',
                validation: (Rule) =>
                  Rule.uri({
                    scheme: ['http', 'https', 'mailto', 'tel'],
                  }),
              },
            ],
          },
        ],
      },
      of: [{ type: 'authorReference' }],
    },
    // 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.
    {
      type: 'mainImage',
      options: { hotspot: true },
    },
    {
      type: 'vimeo',
    },
  ],
}
Within
+page.svelte
I’ll call the portableText using for example
{@html renderBlocks(event.body)}.
The
renderBlocks
function is with the
_sanity.js
config file in Sveltekit for some reason, and is as follows:
import sanity from '@sanity/client';
import blocksToHTML from '@sanity/block-content-to-html';
import imageUrlBuilder from '@sanity/image-url';

/* … projectId, token, etc. here for sanityConfig */
 
export const client = sanity(sanityConfig);

export const imageUrlFor = (source) =>
  imageUrlBuilder(sanityConfig).image(source);

const h = blocksToHTML.h;
const serializers = {
  types: {
    code: ({ node }) => h('pre', h('code', { lang: node.language }, node.code)),
    mainImage: ({ node }) =>
      h('img', {
        src: imageUrlFor(node.asset).url()
      }),
    authorReference: ({ node }) => h('p', 'Author: ' + node.author.name)
  }
};

export const renderBlocks = (blocks) => {
  return blocksToHTML({
    blocks,
    serializers
  });
};
I figure I need to add a type for “vimeo” in the serializer, but can’t seem to get anything returning then. Thank you for anyone who can point me in the right direction.
🙂
Aug 29, 2022, 8:23 AM
Hey
user S
! What have you tried for your vimeo serializer?
Aug 29, 2022, 3:54 PM
hi
user M
! I didn’t mean to ghost you. Life happened and then I forgot. But I did solve it.
For anyone looking for the same, I made a vimeo schema as follows:

import React from 'react'
import ReactPlayer from 'react-player/vimeo'

const vimeoPreview = ({ value }) => {
  const url = value.url
  const wrapperStyle = {
    position: 'relative',
    paddingTop: '56.25%',
  }
  const playerStyle = {
    position: 'absolute',
    top: '0',
    left: '0',
  }
  return (
    <div style={wrapperStyle}>
      <ReactPlayer url={url} controls="true" width="100%" height="100%" style={playerStyle} />
    </div>
  )
}

export default {
  name: 'vimeo',
  type: 'object',
  title: 'Vimeo Embed',
  fields: [
    {
      name: 'url',
      type: 'url',
      title: 'Vimeo video URL',
    },
  ],
  preview: {
    select: {
      url: 'url',
    },
    component: vimeoPreview,
  },
}
Sep 30, 2022, 8:30 AM
Just happy to hear you got it working! Thanks for sharing your solution!
Sep 30, 2022, 3:43 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.

Was this answer helpful?