← Files Investment BankingARCHIVED FILE
skills/pitch-deck-builder/scripts/build_deck_storyboard.py
3.9 KB · Oct 5, 2026 · 18:28 UTC
#!/usr/bin/env python3
"""Convert structured deck plan JSON into a markdown storyboard."""
import json
import sys
from pathlib import Path
def bullet_list(items):
if not items:
return "- none"
return "\n".join(f"- {item}" for item in items)
def main() -> int:
if len(sys.argv) != 3:
print("usage: build_deck_storyboard.py <deck_plan.json> <output.md>", file=sys.stderr)
return 2
data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
out_path = Path(sys.argv[2])
meta = data.get("deck_metadata", {})
story = data.get("md_storyline", {})
lines = []
lines.append(f"# {meta.get('client_or_subject', 'Unknown')} Pitch Deck Storyboard")
lines.append("")
lines.append(
f"Prepared: {meta.get('prepared_date', 'unknown')} | Deck type: {meta.get('deck_type', 'unknown')} | Audience: {meta.get('audience', 'unknown')} | Source confidence: {meta.get('source_confidence', 'unknown')}"
)
lines.append("")
lines.append("## MD-level storyline")
lines.append("")
lines.append(f"**Recommended action:** {story.get('recommended_action', 'unknown')}")
lines.append(f"**Why now:** {story.get('why_now', 'unknown')}")
lines.append("")
lines.append("**Proof pillars:**")
lines.append(bullet_list(story.get("proof_pillars", [])))
lines.append("")
lines.append("**Key risks / objections:**")
lines.append(bullet_list(story.get("key_risks_or_objections", [])))
lines.append("")
lines.append("## Proposed deck architecture")
lines.append("")
lines.append("| # | Slide title | Purpose | Visual | Evidence status |")
lines.append("|---:|---|---|---|---|")
for slide in data.get("slides", []):
lines.append(
f"| {slide.get('slide_number', '')} | {slide.get('slide_title', '')} | {slide.get('slide_purpose', '')} | {slide.get('recommended_visual', '')} | {slide.get('evidence_status', '')} |"
)
lines.append("")
lines.append("## Slide-by-slide draft")
for slide in data.get("slides", []):
lines.append("")
lines.append(f"### {slide.get('slide_number', '')}. {slide.get('slide_title', '')}")
lines.append(f"**Key message:** {slide.get('key_message', '')}")
lines.append(f"**Recommended visual:** {slide.get('recommended_visual', '')}")
lines.append("")
lines.append("**Content blocks:**")
lines.append(bullet_list(slide.get("content_blocks", [])))
lines.append("")
if slide.get("metrics"):
lines.append("**Metrics:**")
for metric in slide.get("metrics", []):
lines.append(
f"- {metric.get('metric', '')}: {metric.get('value', '')} ({metric.get('period', 'unknown period')}; source: {metric.get('source_id', 'unknown')}; label: {metric.get('evidence_label', 'unknown')})"
)
lines.append("")
lines.append(f"**Speaker notes:** {slide.get('speaker_notes', '')}")
lines.append(
f"**Footnotes:** {', '.join(slide.get('footnotes', [])) if slide.get('footnotes') else 'none'}"
)
lines.append(
f"**Open items:** {', '.join(slide.get('open_items', [])) if slide.get('open_items') else 'none'}"
)
lines.append("")
lines.append("## Source register")
lines.append("")
lines.append("| ID | Source | Type | Date | Freshness | Confidence | Supports |")
lines.append("|---|---|---|---|---|---|---|")
for source in data.get("sources", []):
lines.append(
f"| {source.get('source_id', '')} | {source.get('name', '')} | {source.get('type', '')} | {source.get('document_date', '')} | {source.get('freshness', '')} | {source.get('confidence', '')} | {', '.join(source.get('supports', []))} |"
)
out_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"wrote {out_path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
SHA-256: e4905aed27d862a2774a841cf664f8bb60e05d8801c747e254b199e966b8e7e9