Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
42 changes: 0 additions & 42 deletions .github/workflows/sync-shorts.yml

This file was deleted.

128 changes: 30 additions & 98 deletions apps/sanity/extract.json
Original file line number Diff line number Diff line change
Expand Up @@ -702,36 +702,6 @@
}
}
},
{
"type": "type",
"name": "automatedVideo.reference",
"value": {
"type": "object",
"attributes": {
"_ref": {
"type": "objectAttribute",
"value": {
"type": "string"
}
},
"_type": {
"type": "objectAttribute",
"value": {
"type": "string",
"value": "reference"
}
},
"_weak": {
"type": "objectAttribute",
"value": {
"type": "boolean"
},
"optional": true
}
},
"dereferencesTo": "automatedVideo"
}
},
{
"type": "type",
"name": "category.reference",
Expand Down Expand Up @@ -812,27 +782,13 @@
},
"optional": true
},
"description": {
"type": "objectAttribute",
"value": {
"type": "string"
},
"optional": true
},
"youtube": {
"type": "objectAttribute",
"value": {
"type": "string"
},
"optional": true
},
"shortVideoUrl": {
"type": "objectAttribute",
"value": {
"type": "string"
},
"optional": true
},
"thumbnail": {
"type": "objectAttribute",
"value": {
Expand Down Expand Up @@ -888,14 +844,6 @@
},
"optional": true
},
"sourceAutomatedVideo": {
"type": "objectAttribute",
"value": {
"type": "inline",
"name": "automatedVideo.reference"
},
"optional": true
},
"publishedAt": {
"type": "objectAttribute",
"value": {
Expand All @@ -910,52 +858,6 @@
},
"optional": true
},
"statistics": {
"type": "objectAttribute",
"value": {
"type": "object",
"attributes": {
"youtube": {
"type": "objectAttribute",
"value": {
"type": "object",
"attributes": {
"viewCount": {
"type": "objectAttribute",
"value": {
"type": "number"
},
"optional": true
},
"likeCount": {
"type": "objectAttribute",
"value": {
"type": "number"
},
"optional": true
},
"commentCount": {
"type": "objectAttribute",
"value": {
"type": "number"
},
"optional": true
},
"favoriteCount": {
"type": "objectAttribute",
"value": {
"type": "number"
},
"optional": true
}
}
},
"optional": true
}
}
},
"optional": true
},
"categories": {
"type": "objectAttribute",
"value": {
Expand Down Expand Up @@ -1281,6 +1183,36 @@
}
}
},
{
"type": "type",
"name": "automatedVideo.reference",
"value": {
"type": "object",
"attributes": {
"_ref": {
"type": "objectAttribute",
"value": {
"type": "string"
}
},
"_type": {
"type": "objectAttribute",
"value": {
"type": "string",
"value": "reference"
}
},
"_weak": {
"type": "objectAttribute",
"value": {
"type": "boolean"
},
"optional": true
}
},
"dereferencesTo": "automatedVideo"
}
},
{
"name": "videoAnalytics",
"type": "document",
Expand Down
60 changes: 2 additions & 58 deletions apps/sanity/functions/sync-youtube-analytics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,69 +70,13 @@ export const handler = scheduledEventHandler(async ({ context }) => {
useCdn: false,
});

// Step 0: Sync any published automatedVideo Shorts into standalone `_type == "short"` documents
const autoShortDocs = await client.fetch<
Array<{
_id: string;
_createdAt: string;
title: string;
slug?: { current?: string };
youtubeShortId: string;
shortUrl?: string;
hook?: string;
}>
>(
`*[_type == "automatedVideo" && defined(youtubeShortId) && !(_id in path("drafts.**"))]{
_id,
_createdAt,
title,
slug,
youtubeShortId,
shortUrl,
"hook": script.hook
}`,
);

for (const autoShort of autoShortDocs) {
const shortId = `short-${autoShort.youtubeShortId}`;
const slugCurrent =
autoShort.slug?.current ||
autoShort.title
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "")
.slice(0, 90);
await client
.createIfNotExists({
_id: shortId,
_type: "short",
title: autoShort.title,
slug: { _type: "slug", current: slugCurrent },
description: autoShort.hook || undefined,
youtube: `https://www.youtube.com/shorts/${autoShort.youtubeShortId}`,
shortVideoUrl: autoShort.shortUrl || undefined,
sourceAutomatedVideo: {
_type: "reference",
_ref: autoShort._id,
},
publishedAt: autoShort._createdAt,
duration: 60,
})
.catch((err) => {
console.warn(
`[Sync YouTube Analytics] Could not createIfNotExists short ${shortId}:`,
err,
);
});
}

// Query all posts, podcasts, and shorts with YouTube URLs
// Query all posts and podcasts with YouTube URLs
console.log(
`[Sync YouTube Analytics] Fetching documents with YouTube URLs in project ${projectId}, dataset ${dataset}...`,
);

const docs = await client.fetch<TargetVideoDoc[]>(
`*[_type in ["post", "podcast", "short"] && (defined(youtube) || defined(listenLinks.youtube)) && !(_id in path("drafts.**"))]{
`*[_type in ["post", "podcast"] && (defined(youtube) || defined(listenLinks.youtube)) && !(_id in path("drafts.**"))]{
_id,
_type,
title,
Expand Down
38 changes: 0 additions & 38 deletions apps/sanity/schemas/documents/short.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,12 @@ export default defineType({
},
validation: (rule) => rule.required(),
}),
defineField({
name: "description",
title: "Description / Hook",
type: "text",
rows: 3,
description: "Short hook or summary for SEO/AEO and card previews",
}),
defineField({
name: "youtube",
title: "YouTube",
type: "string",
description: "YouTube Shorts video ID or URL",
}),
defineField({
name: "shortVideoUrl",
title: "Direct MP4 Video URL",
type: "url",
description: "Direct Sanity CDN or R2 MP4 URL for native vertical video playback",
}),
defineField({
name: "thumbnail",
title: "Thumbnail",
Expand All @@ -62,13 +49,6 @@ export default defineType({
to: [{ type: "podcast" }],
description: "Long-form episode this Short was clipped from",
}),
defineField({
name: "sourceAutomatedVideo",
title: "Source Automated Video",
type: "reference",
to: [{ type: "automatedVideo" }],
description: "Automated video pipeline run that produced this Short",
}),
defineField({
name: "publishedAt",
title: "Published At",
Expand All @@ -80,24 +60,6 @@ export default defineType({
type: "number",
description: "Duration in seconds",
}),
defineField({
name: "statistics",
title: "Statistics",
type: "object",
fields: [
defineField({
name: "youtube",
title: "YouTube Statistics",
type: "object",
fields: [
defineField({ name: "viewCount", title: "Views", type: "number" }),
defineField({ name: "likeCount", title: "Likes", type: "number" }),
defineField({ name: "commentCount", title: "Comments", type: "number" }),
defineField({ name: "favoriteCount", title: "Favorites", type: "number" }),
],
}),
],
}),
defineField({
name: "categories",
title: "Categories",
Expand Down
4 changes: 2 additions & 2 deletions apps/sanity/schemas/singletons/engineConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,8 @@ export default defineType({
type: 'string',
fieldset: 'aiGeneration',
description:
'The Google Gemini model used for script generation and content analysis (e.g., gemini-2.5-flash, gemini-2.5-pro)',
initialValue: 'gemini-2.5-flash',
'The Google Gemini model used for script generation and content analysis',
initialValue: 'gemini-2.0-flash',
}),
defineField({
name: 'infographicModel',
Expand Down
4 changes: 2 additions & 2 deletions apps/sanity/schemas/singletons/pipelineConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export default defineType({
name: "geminiModel",
title: "Gemini Model",
type: "string",
description: "The Google Gemini model used for script generation and content analysis (e.g., gemini-2.5-flash, gemini-2.5-pro)",
initialValue: "gemini-2.5-flash",
description: "The Google Gemini model used for script generation and content analysis (e.g., gemini-2.0-flash, gemini-2.5-pro)",
initialValue: "gemini-2.0-flash",
}),
defineField({
name: "elevenLabsVoiceId",
Expand Down
8 changes: 1 addition & 7 deletions apps/site/src/components/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ import ThemeToggle from "./ThemeToggle.astro";
import SearchModal from "./SearchModal.astro";

const settings = await Astro.locals.sanity.loadQuery(settingsQuery);
const rawNavLinks = settings?.navLinks ?? [];
const navLinks = rawNavLinks.some((link) => link?.path === "/shorts")
? rawNavLinks
: [
...rawNavLinks,
{ _key: "shorts-nav", path: "/shorts", title: "Shorts", sideOnly: false },
];
const navLinks = settings?.navLinks ?? [];

// The Next header split these across a desktop <nav> and a mobile Sheet;
// `sideOnly` links appear only in the drawer.
Expand Down
Loading
Loading