Skip to content

Commit 83518b7

Browse files
authored
feat: add YouTube loader (#97)
* feat: Implement YouTube channel handle lookup and simplify demo pages\n\n- Implemented channel handle lookup in YouTube loader.\n- Simplified YouTube demo pages to use direct embeds.\n- Removed unused utility file and updated README with credential details. * More readme improvements * fix: TS fix * Add playlist support * Fix test * Changeset * Change playlist * Add playlists to docs * Refactor * Fixes * Update demos
1 parent e89af9b commit 83518b7

36 files changed

Lines changed: 5375 additions & 6 deletions

.changeset/empty-clocks-help.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ascorbic/youtube-loader": patch
3+
---
4+
5+
Adds YouTube loader

.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.astro
2+
.claude
3+
package.json
4+
CHANGELOG.md
5+
.changeset
6+
pnpm-lock.yaml
7+
pnpm-workspace.yaml

.prettierrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{}
1+
{}

demos/loaders/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"@ascorbic/csv-loader": "workspace:^",
1717
"@ascorbic/feed-loader": "workspace:^",
1818
"@ascorbic/mock-loader": "workspace:^",
19+
"@ascorbic/youtube-loader": "workspace:^",
1920
"@astro-community/astro-embed-bluesky": "^0.1.3",
21+
"@astro-community/astro-embed-youtube": "^0.5.6",
2022
"@astrojs/check": "^0.9.4",
2123
"@astrojs/netlify": "^6.4.0",
2224
"@atproto/api": "^0.13.31",

demos/loaders/src/content.config.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { csvLoader } from "@ascorbic/csv-loader";
44
import { airtableLoader } from "@ascorbic/airtable-loader";
55
import { mockLoader } from "@ascorbic/mock-loader";
66
import { authorFeedLoader } from "@ascorbic/bluesky-loader";
7+
import { youTubeLoader } from "@ascorbic/youtube-loader";
78
const releases = defineCollection({
89
loader: feedLoader({
910
url: "https://github.com/withastro/astro/releases.atom",
@@ -74,6 +75,75 @@ const bluesky = defineCollection({
7475
}),
7576
});
7677

78+
// YouTube Collections - Demonstrating different loader types
79+
const youtubeVideos = defineCollection({
80+
loader: youTubeLoader({
81+
type: "videos",
82+
apiKey: import.meta.env.YOUTUBE_API_KEY,
83+
videoIds: [
84+
"dQw4w9WgXcQ", // Rick Roll - classic
85+
"9bZkp7q19f0", // Gangnam Style
86+
"L_jWHffIx5E", // Smells Like Teen Spirit
87+
"fJ9rUzIMcZQ", // Bohemian Rhapsody
88+
"hTWKbfoikeg", // Never Gonna Give You Up (different version)
89+
],
90+
}),
91+
});
92+
93+
const channelVideos = defineCollection({
94+
loader: youTubeLoader({
95+
type: "channel",
96+
apiKey: import.meta.env.YOUTUBE_API_KEY,
97+
channelId: "UCrUL8K81R4VBzm-KOYwrcxQ", // FreeCodeCamp channel
98+
maxResults: 10,
99+
order: "date",
100+
}),
101+
});
102+
103+
// Search for videos about Astro
104+
const astroSearchVideos = defineCollection({
105+
loader: youTubeLoader({
106+
type: "search",
107+
apiKey: import.meta.env.YOUTUBE_API_KEY,
108+
query: "Astro web framework",
109+
maxResults: 15,
110+
order: "relevance",
111+
}),
112+
});
113+
114+
// Channel videos ordered by view count (most popular)
115+
const popularChannelVideos = defineCollection({
116+
loader: youTubeLoader({
117+
type: "channel",
118+
apiKey: import.meta.env.YOUTUBE_API_KEY,
119+
channelId: "UCrUL8K81R4VBzm-KOYwrcxQ", // FreeCodeCamp channel
120+
maxResults: 8,
121+
order: "viewCount",
122+
}),
123+
});
124+
125+
// Search with date filter - recent videos about JavaScript
126+
const recentJavaScriptVideos = defineCollection({
127+
loader: youTubeLoader({
128+
type: "search",
129+
apiKey: import.meta.env.YOUTUBE_API_KEY,
130+
query: "JavaScript tutorial",
131+
maxResults: 12,
132+
order: "date",
133+
publishedAfter: new Date("2024-01-01"),
134+
}),
135+
});
136+
137+
// Playlist example - Web Development Playlist
138+
const webDevPlaylist = defineCollection({
139+
loader: youTubeLoader({
140+
type: "playlist",
141+
apiKey: import.meta.env.YOUTUBE_API_KEY,
142+
playlistId: "PL8Qn4kutqAEuDiRlQ7TD2lthxTKtrbQTc",
143+
maxResults: 20,
144+
}),
145+
});
146+
77147
export const collections = {
78148
releases,
79149
podcasts,
@@ -82,4 +152,10 @@ export const collections = {
82152
mockBlog,
83153
mockOrders,
84154
bluesky,
155+
youtubeVideos,
156+
channelVideos,
157+
astroSearchVideos,
158+
popularChannelVideos,
159+
recentJavaScriptVideos,
160+
webDevPlaylist,
85161
};

demos/loaders/src/live.config.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { defineLiveCollection } from "astro:content";
22
import { liveFeedLoader } from "@ascorbic/feed-loader";
33
import { liveBlueskyLoader } from "@ascorbic/bluesky-loader";
4+
import { liveYouTubeLoader } from "@ascorbic/youtube-loader";
45

56
const news = defineLiveCollection({
67
type: "live",
@@ -17,4 +18,30 @@ const liveBluesky = defineLiveCollection({
1718
}),
1819
});
1920

20-
export const collections = { news, liveBluesky };
21+
const liveChannelVideos = defineLiveCollection({
22+
type: "live",
23+
loader: liveYouTubeLoader({
24+
type: "channel",
25+
apiKey: import.meta.env.YOUTUBE_API_KEY,
26+
channelHandle: "astrodotbuild",
27+
defaultMaxResults: 12,
28+
defaultOrder: "date",
29+
}),
30+
});
31+
32+
const livePlaylistVideos = defineLiveCollection({
33+
type: "live",
34+
loader: liveYouTubeLoader({
35+
type: "playlist",
36+
apiKey: import.meta.env.YOUTUBE_API_KEY,
37+
playlistId: "PL8Qn4kutqAEuEuNnDtbN7sZuGDKFBmxr3",
38+
defaultMaxResults: 15,
39+
}),
40+
});
41+
42+
export const collections = {
43+
news,
44+
liveBluesky,
45+
liveChannelVideos,
46+
livePlaylistVideos,
47+
};

demos/loaders/src/pages/index.astro

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,25 @@ const formatter = new Intl.DateTimeFormat("en-CA", {
2020
<ul>
2121
<li><a href="/news">BBC Science & Environment News (Live Feed Demo)</a></li>
2222
<li><a href="/live-bluesky">Live Bluesky Posts (Real-time)</a></li>
23+
<li><a href="/live-youtube">Live YouTube Channel Videos (Real-time)</a></li>
24+
<li><a href="/live-youtube-playlist">Live YouTube Playlist Videos (Real-time)</a></li>
2325
</ul>
2426

2527
<h2>Build-time Collections</h2>
2628
<ul>
2729
<li><a href="/bluesky">Bluesky Posts (Build-time)</a></li>
2830
</ul>
2931

32+
<h2>YouTube Loader Demos</h2>
33+
<ul>
34+
<li><a href="/youtube">YouTube Videos by ID</a> - Load specific videos using their YouTube IDs</li>
35+
<li><a href="/youtube-channel">Channel Videos (Latest)</a> - Load latest videos from FreeCodeCamp channel</li>
36+
<li><a href="/youtube-popular">Channel Videos (Most Popular)</a> - Load most popular videos from FreeCodeCamp channel</li>
37+
<li><a href="/youtube-search">Search Results</a> - Search for "Astro web framework" videos</li>
38+
<li><a href="/youtube-recent">Recent JavaScript Tutorials</a> - Search with date filtering (2024+)</li>
39+
<li><a href="/youtube-playlist">Playlist Videos</a> - Load videos from a Web Development playlist</li>
40+
</ul>
41+
3042
<h2>Spacecraft</h2>
3143
{
3244
spacecraft.map(({ data }) => (

0 commit comments

Comments
 (0)