Objective
What you're building
Everything from Lessons 1-4 wired into one CLI command: python factory.py "<url-or-video-or-text>" runs the whole pipeline and saves all 6 outputs somewhere durable. Today's lesson is the last piece before this is genuinely a tool you'd use again next week instead of a script you ran once for this course.
Notion as the output destination
from notion_client import Client
notion = Client(auth=os.environ["NOTION_API_KEY"])
def save_to_notion(database_id: str, source: str, results: dict):
for platform, result in results.items():
if result["status"] != "ok":
continue
notion.pages.create(
parent={"database_id": database_id},
properties={
"Name": {"title": [{"text": {"content": f"{platform} - {source[:50]}"}}]},
"Platform": {"select": {"name": platform}},
},
children=[{
"object": "block", "type": "paragraph",
"paragraph": {"rich_text": [{"text": {"content": result["content"][:2000]}}]},
}],
)
Note the if result["status"] != "ok": continue -- this is Lesson 4's failed-vs-succeeded distinction paying off directly: you never silently write a failed generator's error message into Notion as if it were real content. Also note the [:2000] truncation -- Notion's rich_text blocks have their own length limits per block, which is exactly the kind of platform-specific constraint (like Lesson 3's tweet-length enforcement) that's easy to discover the hard way if you don't check for it up front.
Not everyone wants a Notion account for a course lab
Build a local-markdown fallback too: if NOTION_API_KEY isn't set, write each result to output/{platform}_{timestamp}.md instead. This isn't extra scope for its own sake -- it's the same "handle the realistic failure case" instinct from Lesson 2's preprocessors, applied to the output side: don't make the whole pipeline unusable because of one missing API key.
The CLI entry point: the whole pipeline, one command
This is the moment the pipeline becomes a tool, not a demo
Everything before this lesson required you to import functions and call them from a Python shell or a test script. python factory.py "https://youtube.com/watch?v=..." running end to end -- preprocess, generate all 6 in parallel, save to Notion or local files -- is the actual "ship moment" for this course. If a friend asked you to repurpose a video into social content right now, this is the command you'd actually run.
You run python factory.py with a YouTube URL that turns out to have no captions available. What should happen?
This connects Lesson 2's explicit-failure design directly to Lesson 5's orchestration: if preprocessing fails, there's no real source material, and running all 6 generators anyway would either error confusingly or (worse) generate 6 pieces of confidently-wrong content from an error string treated as source text. The CLI entry point needs one check: does the preprocessor's output look like real content before handing it to the generators at all?
Build
Ship it
Run factory.py on 3 different real inputs -- something you'd genuinely want repurposed, not test URLs. Confirm all 6 outputs land somewhere durable (Notion or local files) for each one.
Ship Prompt: Drop the URL you tested it on plus a screenshot of the 6 outputs. Which output surprised you with how good it was? Which one still needs work?