Podcast
Schemas for running a podcast backend on Sanity.io
By Knut Melvær
Podcast
// podcast.js
import languages from './languages';
export default {
name: 'podcast',
title: 'Podcast',
description: 'Create and configure a podcast',
type: 'document',
fields: [
{
name: 'title',
type: 'string',
required: true,
description:
'Remember that if your title is too long, it may be truncated in various podcatchers-'
},
{
name: 'subtitle',
type: 'string',
description: 'That catchy tagline.'
},
{
name: 'slug',
title: 'Podcast slug',
type: 'slug',
description: 'For when you need to refer to your podcast in a url.',
options: {
source: 'title',
slugify: input =>
input
.toLowerCase()
.replace(/\s+/g, '-')
.slice(0, 200)
}
},
{
name: 'description',
type: 'text',
required: true,
description:
'What is this podcast about and why should people subscribe to it?'
},
{
name: 'coverArt',
title: 'Cover art',
type: 'image',
required: true,
description:
'The image should be either jpg or png. Preferably 3000 x 3000, minimum 1400 x 1400 pixels.'
},
{
name: 'copyright',
type: 'string',
description: 'Who owns the rights to this podcast?'
},
{
name: 'language',
type: 'string',
description: 'What language is this podcast in?',
options: {
list: languages
}
},
{
name: 'explicit',
type: 'boolean',
description:
'Do you need to warn parents about the content in this podcast? (You can set this for individual episodes to)'
},
{
name: 'itunes',
title: 'iTunes settings',
type: 'itunes',
description: 'iTunes has extra stuff',
}
],
preview: {
select: {
title: 'title',
subtitle: 'subtitle',
description: 'description',
media: 'coverArt'
}
}
};Categories
// iTunes Categories
const categories = [
{ value: "Arts", title: "Arts" },
{ value: "Arts > Design", title: "Arts > Design" },
{ value: "Arts > Fashion & Beauty", title: "Arts > Fashion & Beauty" },
{ value: "Arts > Food", title: "Arts > Food" },
{ value: "Arts > Literature", title: "Arts > Literature" },
{ value: "Arts > Performing Arts", title: "Arts > Performing Arts" },
{ value: "Arts > Visual Arts", title: "Arts > Visual Arts" },
{ value: "Business", title: "Business" },
{ value: "Business > Business News", title: "Business > Business News" },
{ value: "Business > Careers", title: "Business > Careers" },
{ value: "Business > Investing", title: "Business > Investing" },
{ value: "Business > Management & Marketing", title: "Business > Management & Marketing" },
{ value: "Business > Shopping", title: "Business > Shopping" },
{ value: "Comedy", title: "Comedy" },
{ value: "Education", title: "Education" },
{ value: "Education > Education", title: "Education > Education" },
{ value: "Education > Education Technology", title: "Education > Education Technology" },
{ value: "Education > Higher Education", title: "Education > Higher Education" },
{ value: "Education > K-12", title: "Education > K-12" },
{ value: "Education > Language Courses", title: "Education > Language Courses" },
{ value: "Education > Training", title: "Education > Training" },
{ value: "Games & Hobbies", title: "Games & Hobbies" },
{ value: "Games & Hobbies > Automotive", title: "Games & Hobbies > Automotive" },
{ value: "Games & Hobbies > Aviation", title: "Games & Hobbies > Aviation" },
{ value: "Games & Hobbies > Hobbies", title: "Games & Hobbies > Hobbies" },
{ value: "Games & Hobbies > Other Games", title: "Games & Hobbies > Other Games" },
{ value: "Games & Hobbies > Video Games", title: "Games & Hobbies > Video Games" },
{ value: "Government & Organizations", title: "Government & Organizations" },
{ value: "Government & Organizations > Local", title: "Government & Organizations > Local" },
{ value: "Government & Organizations > National", title: "Government & Organizations > National" },
{ value: "Government & Organizations > Non-Profit", title: "Government & Organizations > Non-Profit" },
{ value: "Government & Organizations > Regional", title: "Government & Organizations > Regional" },
{ value: "Health", title: "Health" },
{ value: "Health > Alternative Health", title: "Health > Alternative Health" },
{ value: "Health > Fitness & Nutrition", title: "Health > Fitness & Nutrition" },
{ value: "Health > Self-Help", title: "Health > Self-Help" },
{ value: "Health > Sexuality", title: "Health > Sexuality" },
{ value: "Kids & Family", title: "Kids & Family" },
{ value: "Music", title: "Music" },
{ value: "News & Politics", title: "News & Politics" },
{ value: "Religion & Spirituality", title: "Religion & Spirituality" },
{ value: "Religion & Spirituality > Buddhism", title: "Religion & Spirituality > Buddhism" },
{ value: "Religion & Spirituality > Christianity", title: "Religion & Spirituality > Christianity" },
{ value: "Religion & Spirituality > Hinduism", title: "Religion & Spirituality > Hinduism" },
{ value: "Religion & Spirituality > Islam", title: "Religion & Spirituality > Islam" },
{ value: "Religion & Spirituality > Judaism", title: "Religion & Spirituality > Judaism" },
{ value: "Religion & Spirituality > Other", title: "Religion & Spirituality > Other" },
{ value: "Religion & Spirituality > Spirituality", title: "Religion & Spirituality > Spirituality" },
{ value: "Science & Medicine", title: "Science & Medicine" },
{ value: "Science & Medicine > Medicine", title: "Science & Medicine > Medicine" },
{ value: "Science & Medicine > Natural Sciences", title: "Science & Medicine > Natural Sciences" },
{ value: "Science & Medicine > Social Sciences", title: "Science & Medicine > Social Sciences" },
{ value: "Society & Culture", title: "Society & Culture" },
{ value: "Society & Culture > History", title: "Society & Culture > History" },
{ value: "Society & Culture > Personal Journals", title: "Society & Culture > Personal Journals" },
{ value: "Society & Culture > Philosophy", title: "Society & Culture > Philosophy" },
{ value: "Society & Culture > Places & Travel", title: "Society & Culture > Places & Travel" },
{ value: "Sports & Recreation", title: "Sports & Recreation" },
{ value: "Sports & Recreation > Amateur", title: "Sports & Recreation > Amateur" },
{ value: "Sports & Recreation > College & High School", title: "Sports & Recreation > College & High School" },
{ value: "Sports & Recreation > Outdoor", title: "Sports & Recreation > Outdoor" },
{ value: "Sports & Recreation > Professional", title: "Sports & Recreation > Professional" },
{ value: "Technology", title: "Technology" },
{ value: "Technology > Gadgets", title: "Technology > Gadgets" },
{ value: "Technology > Tech News", title: "Technology > Tech News" },
{ value: "Technology > Podcasting", title: "Technology > Podcasting" },
{ value: "Technology > Software How-To", title: "Technology > Software How-To" },
{ value: "TV & Film", title: "TV & Film" },
];
export default {
name: 'categories',
title: 'Categories',
type: 'object',
description:
'Each podcast can belong to 3 separate categories, and will be ranked separately in each.',
fieldsets: [
{
title: 'Optional categories',
name: 'categories',
options: {
collapsable: true
}
}
],
fields: ['first', 'secondary', 'tertiary'].map((category, index) => ({
name: `${category}Category`,
type: 'string',
description: 'Where should this podcast be organized in iTunes?',
options: {
list: categories
},
fieldset: index ? 'categories' : null
}))
}Episode
export default {
name: 'episode',
title: 'Episode',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
required: true,
description: 'Remember that long titles can be truncated in podcast apps',
type: 'string'
},
{
name: 'podcast',
description: 'Choose podcast(s) to publish this episode in',
type: 'array',
of: [{ type: 'reference', weak: true, to: [{ type: 'podcast' }] }]
},
{
name: 'schedule',
type: 'schedule',
title: 'Publish schedule',
},
{
name: 'file',
title: 'Podcast media file',
description:
'Most podcatchers support .mp3, but other audio-formats may work as well',
type: 'file'
},
{
name: 'fileUrl',
title: 'External location for podcast media file',
description: 'For when you host your podcast media file elsewhere',
type: 'url'
},
{
name: 'duration',
title: 'Duration',
description: 'HH:MM:SS',
type: 'string'
},
{
name: 'subtitle',
type: 'string',
title: 'Subtitle',
},
{
name: 'explicit',
title: 'Explicit content',
type: 'boolean'
},
{
name: 'summary',
title: 'Summary',
description: 'An episode summary is a string containing one or more descriptive sentences summarizing your episode for potential listeners. You can specify up to 4000 characters.',
type: 'text'
},
{
name: 'description',
title: 'Description',
description: `An episode description is a string containing one or more sentences describing your episode to potential listeners. You can specify up to 4000 characters.`,
type: 'text',
validation: Rule => Rule.max(4000)
},
{
name: 'content',
title: 'Content',
description: 'An episode note. Where encoded is a string containing information about your episode.',
type: 'array',
of: [{
type: 'block'
}]
},
{
name: 'linkList',
title: 'Link list',
description: 'A more structured way to add links for show notes. Will be compiled at the end of the episode content field in a podcast RSS feed',
type: 'array',
of: [
{
type: 'linkListItem'
}
]
},
{
name: 'slug',
title: 'Episode slug',
type: 'slug',
description: 'When you need to refer to your podcast episode in a url',
options: {
source: 'title',
slugify: input =>
input
.toLowerCase()
.replace(/\s+/g, '-')
.slice(0, 200)
}
},
{
name: 'tags',
title: 'Tags',
type: 'array',
options: {
layout: 'tags'
},
of: [
{
type: 'string'
}
]
},
{
name: 'itunes',
title: 'iTunes Settings',
type: 'itunesEpisodeSettings',
},
{
name: 'coverArt',
title: 'Cover art',
type: 'image'
},
{
name: 'sponsors',
type: 'array',
title: 'Sponsors',
of: [
{ type: 'sponsorRead' }
]
},
],
orderings: [
{
title: 'Publish Date, New',
name: 'publishDateDesc',
by: [
{field: 'schedule.publish', direction: 'desc'}
]
},
{
title: 'Publish Date, Old',
name: 'publishDateAsc',
by: [
{field: 'schedule.publish', direction: 'asc'}
]
}
],
preview: {
select: {
title: 'title',
subtitle: 'podcast.0.title',
description: 'summary',
media: 'coverArt',
schedule: 'schedule'
},
prepare({title, subtitle, description, media, schedule}) {
return {
title,
esubtitle: `${new Date(schedule.publish).toDateString()} – ${subtitle}`,
description,
media,
}
}
}
};Host
export default {
name: 'host',
title: 'Host',
type: 'document',
fields: [
{
name: 'name',
title: 'Name',
type: 'string',
},
{
name: 'email',
type: 'email',
},
{
name: 'description',
title: 'Description',
description: 'Describe your host in the most interesting way',
type: 'array',
of: [
{
type: 'block'
}
]
},
{
name: 'image',
type: 'image'
}
]
}Itunes
export default {
name: 'itunes',
title: 'iTunes settings',
type: 'object',
description: 'iTunes has extra stuff',
fields: [
{
name: 'author',
type: 'string',
title: 'Author',
description: 'Podcast author, typically the host(s)'
},
{
name: 'owner',
type: 'owner',
title: 'Owner',
},
{
name: 'url',
type: 'url',
description:
'Helpful for when you want to show this podcast in other contexts than iTunes'
},
{
name: 'type',
type: 'string',
description:
'Is this a ongoing (episodic) podcast, or is it structured in seasons?',
options: {
list: [
{
value: 'episodic',
title: 'Episodic'
},
{
value: 'serial',
title: 'Serial'
}
]
}
},
{
name: 'categories',
title: 'Categories',
type: 'categories'
}
]
}Itunes Episode Settings
export default {
name: 'itunesEpisodeSettings',
title: 'iTunes Settings',
type: 'object',
fields: [
{
name: 'type',
title: 'Episode type',
type: 'string',
options: {
list: [
{ value: 'full', title: 'Full' },
{ value: 'trailer', title: 'Trailer' },
{ value: 'bonus', title: 'Bonus' }
]
}
},
{
name: 'season',
title: 'Season',
type: 'number'
}
]
}Languages
export default [
{ value: "af", title: "af" },
{ value: "ar", title: "ar" },
{ value: "az", title: "az" },
{ value: "bg", title: "bg" },
{ value: "bn", title: "bn" },
{ value: "bs", title: "bs" },
{ value: "ca", title: "ca" },
{ value: "cs", title: "cs" },
{ value: "cy", title: "cy" },
{ value: "da", title: "da" },
{ value: "de", title: "de" },
{ value: "de-at", title: "de-at" },
{ value: "de-ch", title: "de-ch" },
{ value: "el", title: "el" },
{ value: "en", title: "en" },
{ value: "en-au", title: "en-au" },
{ value: "en-ca", title: "en-ca" },
{ value: "en-gb", title: "en-gb" },
{ value: "en-ie", title: "en-ie" },
{ value: "en-in", title: "en-in" },
{ value: "en-nz", title: "en-nz" },
{ value: "en-us", title: "en-us" },
{ value: "en-za", title: "en-za" },
{ value: "eo", title: "eo" },
{ value: "es", title: "es" },
{ value: "es-419", title: "es-419" },
{ value: "es-ar", title: "es-ar" },
{ value: "es-cl", title: "es-cl" },
{ value: "es-co", title: "es-co" },
{ value: "es-cr", title: "es-cr" },
{ value: "es-ec", title: "es-ec" },
{ value: "es-mx", title: "es-mx" },
{ value: "es-pa", title: "es-pa" },
{ value: "es-pe", title: "es-pe" },
{ value: "es-us", title: "es-us" },
{ value: "es-ve", title: "es-ve" },
{ value: "et", title: "et" },
{ value: "eu", title: "eu" },
{ value: "fa", title: "fa" },
{ value: "fi", title: "fi" },
{ value: "fr", title: "fr" },
{ value: "fr-ca", title: "fr-ca" },
{ value: "fr-ch", title: "fr-ch" },
{ value: "gl", title: "gl" },
{ value: "he", title: "he" },
{ value: "hi", title: "hi" },
{ value: "hi-in", title: "hi-in" },
{ value: "hr", title: "hr" },
{ value: "hu", title: "hu" },
{ value: "id", title: "id" },
{ value: "is", title: "is" },
{ value: "it", title: "it" },
{ value: "it-ch", title: "it-ch" },
{ value: "ja", title: "ja" },
{ value: "km", title: "km" },
{ value: "kn", title: "kn" },
{ value: "ko", title: "ko" },
{ value: "lo", title: "lo" },
{ value: "lt", title: "lt" },
{ value: "lv", title: "lv" },
{ value: "mk", title: "mk" },
{ value: "mn", title: "mn" },
{ value: "mr-in", title: "mr-in" },
{ value: "ms", title: "ms" },
{ value: "nb", title: "nb" },
{ value: "ne", title: "ne" },
{ value: "nl", title: "nl" },
{ value: "nn", title: "nn" },
{ value: "or", title: "or" },
{ value: "pl", title: "pl" },
{ value: "pt", title: "pt" },
{ value: "pt-br", title: "pt-br" },
{ value: "rm", title: "rm" },
{ value: "ro", title: "ro" },
{ value: "ru", title: "ru" },
{ value: "sk", title: "sk" },
{ value: "sl", title: "sl" },
{ value: "sr", title: "sr" },
{ value: "sv", title: "sv" },
{ value: "sw", title: "sw" },
{ value: "ta", title: "ta" },
{ value: "th", title: "th" },
{ value: "tl", title: "tl" },
{ value: "tr", title: "tr" },
{ value: "tt", title: "tt" },
{ value: "uk", title: "uk" },
{ value: "ug", title: "ug" },
{ value: "ur", title: "ur" },
{ value: "uz", title: "uz" },
{ value: "vi", title: "vi" },
{ value: "wo", title: "wo" },
{ value: "zh-cn", title: "zh-cn" },
{ value: "zh-hk", title: "zh-hk" },
{ value: "zh-tw", title: "zh-tw" },
{ value: "zh-yue", title: "zh-yue" },
]Link list item
export default {
name: "linkListItem",
type: 'object',
fields: [
{
name: 'title',
type: 'string'
},
{
name: 'URL',
type: 'url'
},
{
name: 'excerpt',
type: 'text'
},
{
name: 'timestamp',
type: 'string',
}
]
}Owner
export default {
name: 'owner',
type: 'object',
description:
'The name and email of the person or organization that iTunes should list in their different views',
fields: [
{
name: 'email',
type: 'email'
},
{
name: 'name',
type: 'string'
}
]
}Schedule
export default {
name: 'schedule',
type: 'object',
title: 'Publish schedule',
fields: [
{
name: 'publish',
type: 'datetime',
title: 'Date of publication',
description: 'When should this episode be available?',
options: {
inputUtc: false,
dateFormat: 'YYYY-MM-DD',
timeFormat: 'HH:mm',
inputDate: true,
inputTime: true,
timeStep: 15,
calendarTodayLabel: 'Today',
placeholderDate: '2017-04-18',
placeholderTime: '11:29'
}
},
{
name: 'unpublish',
type: 'datetime',
title: 'When should this episode be unaccessible?',
description:
'In case you want to unpublish an episode on a said date.',
options: {
inputUtc: false,
dateFormat: 'YYYY-MM-DD',
timeFormat: 'HH:mm',
inputDate: true,
inputTime: true,
timeStep: 15,
calendarTodayLabel: 'Today',
placeholderDate: '2017-04-18',
placeholderTime: '11:29'
}
}
]
}Social
export default {
name: 'social',
title: 'Social network presence',
type: 'object',
fields: [
{
name: 'twitter',
type: 'string',
},
{
name: 'facebook',
type: 'string',
},
{
name: 'googleplus',
type: 'string',
},
{
name: 'instagram',
type: 'string',
},
{
name: 'linkedin',
type: 'string',
},
{
name: 'youtube',
type: 'string',
},
]
}Sponsor
export default {
name: 'sponsor',
type: 'document',
title: 'Sponsor',
fields: [
{
name: 'name',
type: 'string',
title: 'Name of sponsor'
},
{
name: 'url',
type: 'url',
title: 'URL',
},
{
name: 'description',
type: 'array',
title: 'Description',
of: [{ type: 'block' }]
},
{
name: 'logo',
type: 'image',
title: 'Logo',
},
]
}Sponsor read
export default {
name: 'sponsorRead',
type: 'object',
title: 'Sponsor read',
fields: [
{
name: 'sponsor',
type: 'reference',
to: [
{
type: 'sponsor'
}
]
},
{
name: 'copy',
type: 'array',
title: 'copy',
of: [{ type: 'block'}]
},
]
}These schemas add the following document types to your Sanity dataset: Podcast, Episode, Host, Sponsor. You can create as many podcasts as you want, and attach episodes to them. This plugin supports cross-posting episodes to multiple podcasts, as well as scheduling and connecting specific sponsor reads to episodes.
Contributor

Knut Melvær
Knut is a principal developer marketing manager at Sanity.io
Norway