Skip to content

Commit

Permalink
New Keystatic YouTube playlist with playlist block in CMS (#801)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonswiss authored Dec 4, 2023
1 parent 8f5056a commit 717c473
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
20 changes: 20 additions & 0 deletions docs/keystatic.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,13 @@ export default config({
label: 'Resource type',
options: [
{ label: 'YouTube video', value: 'youtube-video' },
{ label: 'YouTube playlist', value: 'youtube-playlist' },
{ label: 'Article', value: 'article' },
],
defaultValue: 'youtube-video',
}),
{
// Single videos
'youtube-video': fields.object({
videoId: fields.text({
label: 'Video ID',
Expand All @@ -304,6 +306,24 @@ export default config({
validation: { length: { min: 1 } },
}),
}),
// Playlists
'youtube-playlist': fields.object({
playlistId: fields.text({
label: 'Playlist ID',
description: 'The ID of the playlist (not the URL!)',
validation: { length: { min: 1 } },
}),
thumbnail: fields.cloudImage({
label: 'Video thumbnail',
description: 'A 16/9 thumbnail image for the video.',
}),
description: fields.text({
label: 'Playlist description',
multiline: true,
validation: { length: { min: 1 } },
}),
}),
// Articles
article: fields.object({
url: fields.url({
label: 'Article URL',
Expand Down
45 changes: 42 additions & 3 deletions docs/src/app/(public)/resources/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ type VideoProps = {
'kind'
>;

type PlaylistProps = {
title: ResourceEntry['title'];
} & Extract<
ResourceEntry['type'],
{ discriminant: 'youtube-playlist' }
>['value'];

type ArticleProps = {
title: ResourceEntry['title'];
} & Omit<
Expand All @@ -30,6 +37,18 @@ export default async function Resources() {
const resources = await reader().collections.resources.all();
if (!resources) notFound();

// Preparing sorted data
const sortedPlaylists = resources
.filter(resource => resource.entry.type.discriminant === 'youtube-playlist')
.sort((a, b) => {
return (a.entry.sortIndex as number) - (b.entry.sortIndex as number);
})
.map(resource => ({
title: resource.entry.title,
sortIndex: resource.entry.sortIndex,
...resource.entry.type.value,
})) as PlaylistProps[];

const sortedVideos = resources
.filter(
resource =>
Expand Down Expand Up @@ -96,6 +115,14 @@ export default async function Resources() {
has a growing collection of content about Keystatic.
</p>
<ResourceGrid>
{sortedPlaylists.map(video => (
<Video
title={video.title}
playlistId={video.playlistId}
description={video.description}
thumbnail={video.thumbnail}
/>
))}
{sortedVideos.map(video => (
<Video
title={video.title}
Expand All @@ -120,8 +147,8 @@ export default async function Resources() {
<ResourceGrid>
{sortedTalks.map(video => (
<Video
videoId={video.videoId}
title={video.title}
videoId={video.videoId}
description={video.description}
thumbnail={video.thumbnail}
/>
Expand Down Expand Up @@ -163,8 +190,20 @@ export default async function Resources() {
);
}

function Video({ videoId, title, description, thumbnail }: VideoProps) {
const videoUrl = `https://www.youtube.com/watch?v=${videoId}&list=PLYyvXL46d-pzqwOKdofd5aKiqPTAN3ql6`;
function Video({
title,
description,
thumbnail,
...props
}: VideoProps | PlaylistProps) {
let videoUrl = '';

if ('videoId' in props) {
// Single video URL with Thinkmill's Keystatic playlist parameter
videoUrl = `https://www.youtube.com/watch?v=${props.videoId}&list=PLYyvXL46d-pzqwOKdofd5aKiqPTAN3ql6`;
} else {
videoUrl = `https://www.youtube.com/playlist?list=${props.playlistId}`;
}
return (
<li>
<Link
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
title: 'Mini Course: Create a GitHub-Powered Blog With Keystatic and Next.js'
type:
discriminant: youtube-playlist
value:
playlistId: PLHrxuCR-0CcSmkyLcmdV7Ruql8DTm644k
thumbnail:
src: >-
https://thinkmill-labs.keystatic.net/keystatic-site/images/tqo28xdnifzt/playlist-thumbnail
alt: Thumbnail of YouTube Playlist
height: 900
width: 1600
description: >-
In this mini-course, you'll create a simple blog from scratch with
Keystatic and Next.js 14.
sortIndex: 0

2 comments on commit 717c473

@vercel
Copy link

@vercel vercel bot commented on 717c473 Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 717c473 Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

keystatic – ./dev-projects/next-app

keystatic-git-main-thinkmill-labs.vercel.app
keystatic-thinkmill-labs.vercel.app
keystatic.vercel.app

Please sign in to comment.