YouTube Posting
The posting service uploads approved videos to YouTube as Shorts and seeds engagement with an AI-generated first comment.
What It Does
Once a video has been approved in the review queue, this stage handles everything needed to publish it on YouTube: uploading the video file, setting optimized metadata (title, description, tags, category), flagging it as AI-generated content, and posting an engagement comment to seed discussion.
How It Works
- Download video from Supabase Storage to a temp file
- Get access token — exchange the stored refresh token for a short-lived OAuth access token
- Upload to YouTube — resumable upload via YouTube Data API v3
- Post engagement comment — AI-generated question to seed discussion
- Update content record — store the YouTube video ID and posting timestamp
Metadata Optimization
Every piece of metadata is optimized for the Shorts algorithm:
Title
The hook (first 100 characters). Front-loaded for mobile — only about 40 characters are visible in the Shorts feed.
Description
{hook}
#Shorts {niche hashtags}The full script is NOT included. It is invisible in the Shorts feed and wastes space.
Category
Niche-specific category IDs for better algorithmic matching:
| Channel Niche | YouTube Category |
|---|---|
| Gaming | 20 (Gaming) |
| Movies and TV | 24 (Entertainment) |
| Books | 27 (Education) |
| Finance | 27 (Education) |
| AI Tools | 28 (Science and Technology) |
| Default | 24 (Entertainment) |
Tags
Channel name + “Shorts” + “YouTube Shorts” + niche keywords. Trimmed to stay under YouTube’s 500-character limit.
Compliance Flags
containsSyntheticMedia: true— Discloses AI-generated content (required by YouTube policy)selfDeclaredMadeForKids: falsedefaultLanguage: "en"
Engagement Comments
After posting, the system posts a first comment from the creator’s account to seed engagement. The comment is generated dynamically:
- AI-generated (GPT-4o-mini): Creates a contextual question based on the video’s hook and topic. One sentence, ends with a question mark, casual tone, no hashtags or emoji.
- Fallback: Static niche-specific questions if AI generation fails (e.g., “What do you think about this?” for general topics).
Posting Modes
Immediate Posting
Trigger posting for a specific content item right away from the content detail page or review queue.
Scheduled Posting
Set a scheduled_for timestamp on an approved content item. The hourly cron job checks for items where the scheduled time has passed and posts them automatically.
Batch Posting
The POST /pipeline/post-scheduled endpoint checks all approved items with a past scheduled_for timestamp and posts them in sequence.
Where to Find It
- Dashboard: Content detail page, Post button; or Review Queue, Approve and Post action
- API:
POST /pipeline/post/{content_id}(immediate) orPOST /pipeline/post-scheduled(batch/scheduled)
Configuration
Posting behavior is determined by the channel’s niche and the content’s metadata. There are no separate posting configuration fields — the system uses the channel name, niche, and content hook/script to generate all metadata dynamically.
Per-Channel YouTube Connection
Each dashboard channel connects to its own YouTube brand channel via OAuth. This allows you to run multiple channels posting to different YouTube accounts from a single deployment.
- Global credentials:
YOUTUBE_CLIENT_IDandYOUTUBE_CLIENT_SECRETare shared across all channels — they come from a single Google Cloud project - Per-channel tokens: Each channel stores its own
youtube_refresh_tokenandyoutube_channel_idin the database - Brand channel picker: During the OAuth flow, Google shows a brand channel picker — select the correct brand channel for each dashboard channel
- Fallback behavior: If a channel has no per-channel credentials, the worker falls back to the global
YOUTUBE_REFRESH_TOKENenvironment variable
To connect a channel, go to the channel’s settings page, open the Publishing tab, and click Connect YouTube Channel. You’ll be redirected to Google to authorize and pick the target brand channel.
Dependencies
YOUTUBE_CLIENT_ID— Google OAuth 2.0 client IDYOUTUBE_CLIENT_SECRET— Google OAuth 2.0 client secretYOUTUBE_REFRESH_TOKEN— Long-lived refresh token (global fallback, used when a channel has no per-channel credentials)OPENAI_API_KEY— For generating dynamic engagement comments