Workflow
1. Clarify Requirements
- Ask the user: Single-slide or multi-slide (3-4 slides)?
- Ask the user: Any specific focus areas or topics to emphasize?
- Only after user confirms, proceed to research
2. Research & Planning
Data Sources:
- Primary: Company filings (BamSEC, SEC EDGAR - "Item 1. Business", MD&A), investor presentations, corporate website
- Market data: Bloomberg, FactSet, CapIQ (price, shares, market cap, net debt, EV, ownership)
- Estimates: FactSet/CapIQ consensus for NTM revenue, EBITDA, EPS
- News: Press releases from last 90 days, M&A activity, guidance changes
Required Metrics:
- Financials: Revenue, EBITDA, margins (%), EPS, FCF for ±3 years
- Valuation: Market Cap, EV, EV/Revenue, EV/EBITDA, P/E multiples
- Growth: YoY growth rates (%)
- Ownership: Top 5 shareholders with % ownership
- Segments: Product mix and/or geographic mix (% breakdown)
Normalization:
- Convert all amounts to consistent currency
- Scale consistently ($mm or $bn throughout, not mixed)
Before Building:
- Print outline to chat with 4-5 bullet points per item (actual numbers, no placeholders)
- Print style choices: fonts, colors (hex codes), chart types for each data set
- Get user alignment: "Does this outline and visual strategy align with your vision?"
3. Slide-by-Slide Creation
CRITICAL: You MUST create ONE slide at a time and get user approval before proceeding to the next slide.
For EACH slide:
- Create ONLY this one slide with PptxGenJS
- MANDATORY: Convert to image for review - You MUST convert slides to images so you can visually verify them:
soffice --headless --convert-to pdf presentation.pptx pdftoppm -jpeg -r 150 -f 1 -l 1 presentation.pdf slide - MANDATORY VISUAL REVIEW: You MUST carefully examine the rendered slide image before proceeding:
- Text overlap check: Scan every text element - do any labels, bullets, or titles collide with each other?
- Text cutoff check: Is any text truncated at boundaries? Are all words fully visible?
- Chart boundary check: Do charts stay within their containers? Are ALL axis labels fully visible?
- Quadrant integrity: Does content in one quadrant bleed into adjacent quadrants?
- If ANY overlap or cutoff is detected: Fix immediately using these strategies in order:
- First: Reduce font size (go down 1-2pt)
- Second: Shorten text (abbreviate, remove less critical info)
- Third: Adjust element positions or container sizes
- Re-render and verify again - do not proceed until all text fits cleanly
- Show slide image to user with download link
- STOP and wait for explicit user approval before creating the next slide. Do NOT proceed until user confirms.
YOU MUST CHECK FOR THESE SPECIFIC ISSUES ON EVERY PAGE:
- Table rows colliding with text below them
- Chart x-axis labels cut off at bottom
- Long bullet points wrapping into adjacent content
- Quadrant content bleeding into adjacent quadrants
- Title text overlapping with content below
- Legend text overlapping with chart elements
- Footer/source text colliding with main content
Slide Format Requirements
Information Density is Critical
The #1 goal is MAXIMUM information density. A busy executive should understand the entire company story in 30 seconds. Fill every quadrant to capacity.
Per quadrant targets:
- Company Overview: 6-8 bullets minimum (HQ, founded, employees, CEO/CFO, market cap, ticker, industry, key stat)
- Business & Positioning: 6-8 bullets (revenue drivers, products, market share %, competitive moat, customer count, geographic mix)
- Key Financials: Table with 8-10 rows OR chart + 4-5 key metrics (Revenue, EBITDA, margins, EPS, FCF, growth rates, valuation multiples)
- Fourth quadrant: 5-7 bullets (ownership %, recent M&A, developments, catalysts)
Information packing techniques:
- Combine related facts: "HQ: Austin, TX; Founded: 2003; 140K employees"
- Always include numbers: "$50B revenue" not "large revenue"
- Add context: "EBITDA margin: 25% (vs. 18% industry avg)"
- Include YoY changes: "Revenue: $125M (+28% YoY)"
- Use percentages: "Enterprise: 62% of revenue"
If a quadrant looks sparse, add more:
- Segment breakdowns with %
- Geographic revenue splits
- Customer concentration (top 10 = X%)
- Recent contract wins with $ values
- Guidance vs. consensus
- Insider ownership %
Line spacing - use single textbox per section:
def add_section(slide, x, y, w, header_text, bullets, header_size=10, bullet_size=8):
"""Header + bullets in single textbox with natural spacing"""
tb = slide.shapes.add_textbox(x, y, w, Inches(len(bullets) * 0.18 + 0.3))
tf = tb.text_frame
tf.word_wrap = True
# Header paragraph
p = tf.paragraphs[0]
p.text = header_text
p.font.bold = True
p.font.size = Pt(header_size)
p.font.color.rgb = RGBColor(0, 51, 102)
p.space_after = Pt(6) # Small gap after header
# Bullet paragraphs
for bullet in bullets:
p = tf.add_paragraph()
p.text = bullet
p.font.size = Pt(bullet_size)
p.space_after = Pt(3)
return tb
Key spacing principles:
- Put header + bullets in SAME textbox (no separate header textbox)
- Use
space_after = Pt(6)after header,Pt(3)between bullets - Don't hardcode gaps - let paragraph spacing handle it naturally
- If content overflows, reduce font by 1pt rather than removing content
-
3-4 dense slides - use quadrants, columns, tables, charts
-
Bullets for ALL body text - NEVER paragraphs. Use ONE textbox per section with all bullets inside - do NOT create separate textboxes for each bullet point. Use PptxGenJS bullet formatting:
// CORRECT: Single textbox with bullet list - each array item becomes a bullet // Position in top-left quadrant (Company Overview) - after header with accent bar slide.addText( [ { text: 'Headquarters: Austin, Texas; Founded 2003', options: { bullet: { indent: 10 }, breakLine: true } }, { text: 'Employees: 140,000+ globally across 6 continents', options: { bullet: { indent: 10 }, breakLine: true } }, { text: 'CEO: Elon Musk; CFO: Vaibhav Taneja', options: { bullet: { indent: 10 }, breakLine: true } }, { text: 'Market Cap: $850B (#6 globally by market cap)', options: { bullet: { indent: 10 }, breakLine: true } }, { text: 'Segments: Automotive (85%), Energy (10%), Services (5%)', options: { bullet: { indent: 10 } } } ], { x: 0.45, y: 0.95, w: 4.5, h: 2.6, fontSize: 11, fontFace: 'Arial', valign: 'top', paraSpaceAfter: 6 } ); // WRONG: Multiple separate textboxes for each bullet - causes alignment issues // slide.addText('Headquarters: Austin', { x: 0.5, y: 1.0, bullet: true });Bullet formatting tips:
bullet: { indent: 10 }- controls bullet indentation (smaller = tighter)paraSpaceAfter: 6- space after each paragraph in points- Pack multiple related facts into each bullet (e.g., "HQ: Austin; Founded: 2003")
- Include specific numbers and percentages for information density
-
Title case for titles (not ALL CAPS), left-aligned
-
Consistent fonts everywhere including tables
-
Company's brand colors - YOU MUST research actual brand colors via web search before creating slides. Do not guess or assume colors.
-
Follow brand guidelines if provided
Visual Reference
See examples/Nike_Strip_Profile_Example.pptx for layout inspiration. Adapt colors to each company's brand.
First Page Layout
Must pass "30-second comprehension test" for a busy executive.
Slide Setup (CRITICAL)
Use 4:3 aspect ratio (standard IB pitch book format):
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_4x3'; // 10" wide × 7.5" tall - MUST USE THIS
Slide Coordinate System
PptxGenJS uses inches. 4:3 sli