From f32bbf4fbce197b5b76cce43a8bca08a3869119c Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Wed, 14 Oct 2026 18:52:01 -0400 Subject: [PATCH 1/2] refactor(sanity): clean up schemas, organize Studio structure, and optimize GROQ queries --- .../skills/sanity-editorial-workflow/SKILL.md | 144 + .../SharePreviewActionButton.tsx | 109 - .../documentActions/sharePreviewAction.tsx | 36 - apps/sanity/extract.json | 10682 ++++------------ .../sync-missing-youtube-transcripts/index.ts | 2 +- apps/sanity/plugins/assist.ts | 225 +- apps/sanity/plugins/settings.tsx | 44 +- apps/sanity/sanity.config.ts | 428 +- .../schemas/documents/automatedVideo.ts | 713 -- apps/sanity/schemas/documents/category.ts | 45 - apps/sanity/schemas/documents/contentIdea.ts | 64 - apps/sanity/schemas/documents/course.ts | 60 - apps/sanity/schemas/documents/guest.ts | 19 +- apps/sanity/schemas/documents/lesson.ts | 20 - apps/sanity/schemas/documents/mediaAsset.ts | 92 - apps/sanity/schemas/documents/page.ts | 9 +- apps/sanity/schemas/documents/podcast.ts | 114 +- .../sanity/schemas/documents/podcastSeries.ts | 61 - apps/sanity/schemas/documents/post.ts | 26 +- apps/sanity/schemas/documents/short.ts | 81 - apps/sanity/schemas/documents/sponsor.ts | 8 +- apps/sanity/schemas/documents/sponsorLead.ts | 114 - apps/sanity/schemas/documents/sponsorPool.ts | 76 - .../schemas/documents/sponsorshipRequest.ts | 53 - apps/sanity/schemas/documents/transcript.ts | 8 +- .../schemas/documents/videoAnalytics.ts | 120 - apps/sanity/schemas/partials/content.ts | 9 - apps/sanity/schemas/partials/socialPreview.ts | 55 - apps/sanity/schemas/previewSession.ts | 26 - .../schemas/singletons/contentConfig.ts | 136 - .../schemas/singletons/dashboardSettings.ts | 77 - .../sanity/schemas/singletons/engineConfig.ts | 707 - apps/sanity/schemas/singletons/gcsConfig.ts | 29 - .../schemas/singletons/pipelineConfig.ts | 112 - .../schemas/singletons/remotionConfig.ts | 57 - apps/sanity/schemas/singletons/settings.tsx | 3 - .../schemas/singletons/sponsorConfig.ts | 69 - apps/sanity/structure.ts | 347 + apps/site/src/lib/sanity/queries/pages.ts | 4 +- apps/site/src/lib/sanity/queries/people.ts | 10 +- apps/site/src/lib/sanity/queries/podcasts.ts | 23 +- apps/site/src/lib/sanity/queries/posts.ts | 10 +- apps/site/src/lib/sanity/queries/shared.ts | 73 +- apps/site/src/lib/sanity/queries/sponsors.ts | 11 +- apps/site/src/pages/api/mcp.ts | 168 +- apps/site/src/pages/author/[slug].astro | 2 - apps/site/src/pages/guest/[slug].astro | 2 - apps/site/src/pages/sponsor/[slug].astro | 4 - 48 files changed, 3368 insertions(+), 11919 deletions(-) create mode 100644 .agents/skills/sanity-editorial-workflow/SKILL.md delete mode 100644 apps/sanity/components/documentActions/SharePreviewActionButton.tsx delete mode 100644 apps/sanity/components/documentActions/sharePreviewAction.tsx delete mode 100644 apps/sanity/schemas/documents/automatedVideo.ts delete mode 100644 apps/sanity/schemas/documents/category.ts delete mode 100644 apps/sanity/schemas/documents/contentIdea.ts delete mode 100644 apps/sanity/schemas/documents/course.ts delete mode 100644 apps/sanity/schemas/documents/lesson.ts delete mode 100644 apps/sanity/schemas/documents/mediaAsset.ts delete mode 100644 apps/sanity/schemas/documents/podcastSeries.ts delete mode 100644 apps/sanity/schemas/documents/short.ts delete mode 100644 apps/sanity/schemas/documents/sponsorLead.ts delete mode 100644 apps/sanity/schemas/documents/sponsorPool.ts delete mode 100644 apps/sanity/schemas/documents/sponsorshipRequest.ts delete mode 100644 apps/sanity/schemas/documents/videoAnalytics.ts delete mode 100644 apps/sanity/schemas/partials/socialPreview.ts delete mode 100644 apps/sanity/schemas/previewSession.ts delete mode 100644 apps/sanity/schemas/singletons/contentConfig.ts delete mode 100644 apps/sanity/schemas/singletons/dashboardSettings.ts delete mode 100644 apps/sanity/schemas/singletons/engineConfig.ts delete mode 100644 apps/sanity/schemas/singletons/gcsConfig.ts delete mode 100644 apps/sanity/schemas/singletons/pipelineConfig.ts delete mode 100644 apps/sanity/schemas/singletons/remotionConfig.ts delete mode 100644 apps/sanity/schemas/singletons/sponsorConfig.ts create mode 100644 apps/sanity/structure.ts diff --git a/.agents/skills/sanity-editorial-workflow/SKILL.md b/.agents/skills/sanity-editorial-workflow/SKILL.md new file mode 100644 index 000000000..585a6eb85 --- /dev/null +++ b/.agents/skills/sanity-editorial-workflow/SKILL.md @@ -0,0 +1,144 @@ +--- +name: sanity-editorial-workflow +description: End-to-end editorial workflow for CodingCat.dev using Sanity MCP, Sanity CLI, Gemini writing, cover photo generation/upload, and Sanity Content Releases readiness checks. Use when drafting blog posts or podcast show notes, creating or uploading cover images, checking draft/release status, or preparing Sanity Content Releases. +--- + +# Sanity Editorial Workflow (MCP, CLI, Gemini Writing, Photos & Content Releases) + +Use this skill whenever the user asks to: +- Check the status of drafts, upcoming episodes/posts, or **Sanity Content Releases** +- Write or update blog posts (`post`) or podcast show notes (`podcast`) using Gemini (from a topic or a YouTube `transcript`) +- Generate or upload cover images (`coverImage`) to Sanity and attach them to documents +- Stage or audit documents in a Sanity Content Release before publishing + +Do **not** create custom wrapper scripts when you can execute operations directly via **Sanity MCP** (`codingcat-dev` / Sanity Context MCP) and **Sanity CLI** (`pnpm --filter @codingcatdev/sanity exec sanity ...`). + +--- + +## 1. Checking Content Releases & Publishing Readiness + +Sanity stores documents in three ID namespaces depending on their lifecycle state: +- **Published**: `` +- **Drafts**: `drafts.` +- **Content Releases**: `versions..` (paired with a release metadata document of `_type == "system.release"`) + +### A. Inspect Active Content Releases & Versioned Documents +Run via Sanity CLI (`--with-user-token` reads `drafts.**` and `versions.**` using the logged-in Sanity CLI session): + +```bash +pnpm --filter @codingcatdev/sanity exec sanity documents query \ + '{ + "releases": *[_type == "system.release"] | order(_updatedAt desc) { + _id, + name, + state, + publishAt, + "metadata": metadata { title, description, releaseType } + }, + "releaseDocs": *[_id in path("versions.**") && _type in ["post", "podcast"]] | order(_updatedAt desc) { + _id, + _type, + title, + "slug": slug.current, + date, + "hasCoverImage": defined(coverImage.asset._ref), + "hasExcerpt": defined(excerpt) && length(excerpt) > 10, + "blockCount": count(content), + "hasYoutube": defined(youtube), + "hasSpotify": defined(spotify), + "hasTranscript": defined(transcript) + }, + "drafts": *[_id in path("drafts.**") && _type in ["post", "podcast"]] | order(_updatedAt desc) { + _id, + _type, + title, + "slug": slug.current, + date, + "hasCoverImage": defined(coverImage.asset._ref), + "hasExcerpt": defined(excerpt) && length(excerpt) > 10, + "blockCount": count(content), + "hasYoutube": defined(youtube), + "hasSpotify": defined(spotify), + "hasTranscript": defined(transcript) + } + }' --dataset production --api-version v2025-09-30 +``` + +### B. Publishing Readiness Checklist +Before a `post` or `podcast` is ready to publish (or ready inside a Content Release), verify: +1. **Shared Required Fields (`post` & `podcast`)**: + - `title` (non-empty string) + - `slug.current` (lowercase hyphenated slug) + - `date` (ISO 8601 datetime) + - `coverImage.asset._ref` (16:9 image uploaded to Sanity) + - `excerpt` (1–2 sentence summary, <= 160 chars recommended) + - `content` (non-empty Portable Text array) + - `author` (defaults to Alex Patterson `_ref: "RIgC5r4TJ0hCGOzxHszD1w"`) +2. **Podcast-Specific Fields (`podcast`)**: + - `season` (integer) & `episode` (integer) + - `recordingDate` (ISO 8601 datetime) + - `guest` (array of references to `guest` documents) + - `youtube` (YouTube URL — triggers `sync-youtube-transcript` on publish) + - `spotify` & `listenLinks` (auto-synced by `sync-podcast-links` once published on Anchor/Spotify RSS) + +--- + +## 2. Writing Posts & Podcast Show Notes via Gemini + +### Step 1: Retrieve Source Context (Transcript or Existing Draft) +- Use the `codingcat-dev` MCP tool `get_content_by_slug` or `query_content`, or run a Sanity CLI query to fetch the document and its `transcript->fullText`, `transcript->chapters`, and `guest[]->`: + ```bash + pnpm --filter @codingcatdev/sanity exec sanity documents query \ + '*[_type in ["post", "podcast"] && (slug.current == $slug || _id == $id)][0]{ + _id, _type, title, "slug": slug.current, excerpt, youtube, + "transcript": transcript->{ fullText, summary, chapters }, + "guests": guest[]->{ title, excerpt, socials, websites } + }' --dataset production + ``` + +### Step 2: Draft Content & Convert Markdown to Portable Text +- Write the article or episode show notes in clean Markdown: + - Use `##` (`h2`) and `###` (`h3`) headings to structure sections. + - Include bulleted takeaways, links mentioned, and fenced code blocks where relevant. + - Do **not** repeat the document `title` as an `# h1` at the top of `content`. + - Write a crisp 1–2 sentence `excerpt` that complements the title without repeating it. +- Convert the Markdown to Sanity Portable Text blocks using `@portabletext/markdown` (`markdownToPortableText`) — see `.agents/skills/portable-text-conversion/SKILL.md`. + +### Step 3: Save to Draft (`drafts.`) or Content Release (`versions..`) +- Target `drafts.` (or `versions..` if staging for a Content Release) so changes can be reviewed in Sanity Studio before going live: + ```bash + pnpm --filter @codingcatdev/sanity exec sanity documents create --replace --dataset production + ``` + +--- + +## 3. Creating & Uploading Photos (`coverImage`) + +### Step 1: Generate a 16:9 Cover Image (When Needed) +- Invoke the `image-generator` subagent with a clear 16:9 visual brief tailored to the post/podcast topic and CodingCat.dev's modern developer aesthetic (avoiding cluttered text overlays if the title is already rendered on cards). + +### Step 2: Upload the Image Asset & Attach `coverImage` +- Upload the local image file to Sanity's Asset API and patch the target draft/release document using `@sanity/client` via `pnpm --filter @codingcatdev/sanity exec sanity exec