copilot/change-app-name-to-jcrguru
Content Calendar
Auto-schedule generated content across platforms using best-practice timing rules and content mix optimization.
Table of Contents
Platform Timing Rules
Optimal posting times based on platform-specific engagement data. Times are in the user's local timezone (ask if not provided, default to US Eastern).
| Platform | Best Days | Best Times | Frequency | Notes |
|----------|----------|-----------|-----------|-------|
| Twitter/X | Mon-Fri | 9-11am, 1-3pm | 1-2 posts/day | Threads perform best Tue-Thu morning |
| LinkedIn | Tue-Thu | 8-10am | 2-3 posts/week | Avoid weekends — engagement drops 60% |
| Instagram Feed | Mon, Wed, Fri | 11am-1pm | 3-5 posts/week | Quote cards + carousels outperform text |
| Instagram Reels | Tue, Thu, Sat | 9am, 12pm, 7pm | 3-5/week | First 3 seconds are critical |
| TikTok | Tue, Thu, Sat | 7-9pm | 3-5/week | Evening posts outperform morning |
| YouTube Shorts | Sat, Sun | 9am-12pm | 1-2/week | Weekend discovery is strongest |
| Newsletter | Tue or Thu | 7-9am | 1/week | Tuesday has highest open rates |
| Blog | Any weekday | Morning publish | 1/episode | SEO value accumulates over time |
Content Mix Strategy
Don't dump all content on release day. Spread it across the week following an episode release to maximize reach and avoid audience fatigue.
Release Week Schedule (Single Episode)
| Day | Platform | Content Piece | Why |
|-----|----------|--------------|-----|
| Day 0 (Release) | Blog, Newsletter | Blog post + newsletter | Drive listens on release day |
| Day 1 | Twitter/X | Thread (top atoms) | Morning engagement peak |
| Day 1 | Instagram | Quote card (highest-scored quote) | Visual hook |
| Day 2 | LinkedIn | Long-form post | Professional audience, mid-week peak |
| Day 2 | TikTok | Video clip #1 (most controversial) | Evening engagement |
| Day 3 | Twitter/X | Single tweet (data point atom) | Maintain presence |
| Day 3 | Instagram Reels | Video clip #1 (cross-post) | Reels algorithm favors consistency |
| Day 4 | Instagram | Quote card #2 | Keep feed active |
| Day 4 | YouTube Shorts | Video clip #2 | Weekend discovery window |
| Day 5 | Twitter/X | Quote tweet thread with commentary | Re-engage thread audience |
| Day 5 | TikTok | Video clip #2 | Different angle from clip #1 |
| Day 6 | Instagram Stories | Behind-the-scenes or teaser for next ep | Build anticipation |
Content Priority by Score
Map viral scores to scheduling priority:
- 80-100 (Priority): Schedule in prime-time slots (peak engagement hours). These are your hero posts — threads, lead video clips, newsletter leads.
60-79 (Strong): Fill standard slots. Good supporting content — quote cards, secondary clips, individual tweets.
40-59 (Fill): Use for low-competition slots or story content. Keep the feed active without risking weak performance in prime slots.
Below 40: Don't schedule. Archive for potential future use.
Calendar Generation Logic
Algorithm
- Sort all content pieces by viral score (descending)
Assign hero content (score 80+) to prime-time slots first
Fill remaining slots with strong content (60-79), respecting platform frequency limits
Add fill content (40-59) to any remaining open slots
Check for conflicts (no two posts on the same platform within 4 hours)
Verify content variety (no two quote cards back-to-back on the same platform)
Slot Assignment
from datetime import datetime, timedelta
PLATFORM_SLOTS = {
"twitter": [
{"day_offset": 1, "time": "09:00", "type": "thread"},
{"day_offset": 3, "time": "10:00", "type": "single_tweet"},
{"day_offset": 5, "time": "09:00", "type": "quote_tweet"},
],
"linkedin": [
{"day_offset": 2, "time": "08:30", "type": "article"},
],
"instagram_feed": [
{"day_offset": 1, "time": "12:00", "type": "quote_card"},
{"day_offset": 4, "time": "11:00", "type": "quote_card"},
],
"instagram_reels": [
{"day_offset": 3, "time": "12:00", "type": "video_clip"},
],
"tiktok": [
{"day_offset": 2, "time": "19:00", "type": "video_clip"},
{"day_offset": 5, "time": "19:00", "type": "video_clip"},
],
"youtube_shorts": [
{"day_offset": 4, "time": "10:00", "type": "video_clip"},
],
"newsletter": [
{"day_offset": 0, "time": "08:00", "type": "newsletter"},
],
"blog": [
{"day_offset": 0, "time": "09:00", "type": "blog_post"},
],
}
def generate_calendar(
content_pieces: list[dict],
release_date: datetime,
timezone: str = "US/Eastern",
) -> list[dict]:
"""Generate a content calendar from scored content pieces."""
sorted_pieces = sorted(
content_pieces, key=lambda p: p.get("score", 0), reverse=True
)
calendar = []
used_slots = set()
for piece in sorted_pieces:
platform = piece["platform"]
content_type = piece["type"]
slots = PLATFORM_SLOTS.get(platform, [])
for slot in slots:
if slot["type"] != content_type:
continue
slot_key = f"{platform}-{slot['day_offset']}-{slot['time']}"
if slot_key in used_slots:
continue
publish_date = release_date + timedelta(days=slot["day_offset"])
hour, minute = map(int, slot["time"].split(":"))
publish_dt = publish_date.replace(hour=hour, minute=minute)
calendar.append({
"platform": platform,
"type": content_type,
"publish_at": publish_dt.isoformat(),
"content": piece["content"],
"score": piece.get("score", 0),
"atom_id": piece.get("atom_id"),
})
used_slots.add(slot_key)
break
calendar.sort(key=lambda c: c["publish_at"])
return calendar
Output Format
The calendar is saved as JSON for easy integration with scheduling tools:
{
"episode": {
"title": "Episode Title",
"release_date": "2024-01-15",
"url": "https://..."
},
"timezone": "US/Eastern",
"calendar": [
{
"platform": "blog",
"type": "blog_post",
"publish_at": "2024-01-15T09:00:00",
"content_file": "blog-post.md",
"score": 82
},
{
"platform": "twitter",
"type": "thread",
"publish_at": "2024-01-16T09:00:00",
"content_file": "social/twitter-thread.md",
"score": 91
}
],
"stats": {
"total_pieces": 15,
"scheduled": 12,
"cut_below_threshold": 3,
"avg_score": 72,
"highest_score": 91,
"platforms_covered": 7,
"calendar_span_days": 6
}
}
Multi-Episode Scheduling
When processing multiple episodes (batch mode), interleave content from different episodes to maintain variety:
- Never schedule content from two different episodes on the same platform on the same day
Space episode releases at least 3 days apart in the calendar
Prioritize newer episodes for prime-time slots
Use older episode content as gap filler between new releases