Claude Skill

pptx-official

Generating PowerPoint presentations with pptxgenjs in Node.js. Use when creating automated presentations, slide decks, pitch decks, or reports in .pptx format from data.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download sabahattink-antigravity-fullstack-hq-skills_pptx-official-1acbfa7.zip · 2 KB
Part of sabahattink/antigravity-fullstack-hq — 27 skills

Install

skills CLI npx skills add https://github.com/sabahattink/antigravity-fullstack-hq/tree/main/skills/pptx-official
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install sabahattink-antigravity-fullstack-hq@llmmart
Git git clone https://github.com/sabahattink/antigravity-fullstack-hq.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole sabahattink/antigravity-fullstack-hq collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

PowerPoint Generation with pptxgenjs

Installation

npm install pptxgenjs
npm install -D @types/node

Basic Presentation

import PptxGenJS from 'pptxgenjs'

async function generatePresentation(data: PresentationData): Promise<Buffer> {
  const pptx = new PptxGenJS()

  // Global settings
  pptx.author  = 'Full Stack HQ'
  pptx.company = 'Full Stack HQ'
  pptx.title   = data.title
  pptx.subject = data.subject
  pptx.layout  = 'LAYOUT_WIDE'  // 16:9

  // ─── Title Slide ─────────────────────────────────────────
  const titleSlide = pptx.addSlide()
  titleSlide.background = { color: '1E3A5F' }

  titleSlide.addText(data.title, {
    x:     '10%',
    y:     '35%',
    w:     '80%',
    h:     '20%',
    fontSize:  40,
    bold:      true,
    color:     'FFFFFF',
    align:     'center',
    fontFace:  'Calibri',
  })

  titleSlide.addText(data.subtitle, {
    x:        '15%',
    y:        '60%',
    w:        '70%',
    h:        '10%',
    fontSize: 20,
    color:    'B0C4DE',
    align:    'center',
  })

  titleSlide.addText(new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long' }), {
    x:        '0%',
    y:        '88%',
    w:        '100%',
    h:        '8%',
    fontSize: 12,
    color:    '7094B5',
    align:    'center',
  })

  // ─── Content Slides ───────────────────────────────────────
  for (const section of data.sections) {
    addContentSlide(pptx, section)
  }

  // ─── Chart Slide ──────────────────────────────────────────
  if (data.chartData) {
    addChartSlide(pptx, data.chartData)
  }

  // ─── Summary Slide ────────────────────────────────────────
  addSummarySlide(pptx, data.keyPoints)

  // Return as buffer
  const buffer = await pptx.write({ outputType: 'nodebuffer' }) as Buffer
  return buffer
}

Content Slide with Bullets

function addContentSlide(pptx: PptxGenJS, section: Section) {
  const slide = pptx.addSlide()

  // Slide header bar
  slide.addShape(pptx.ShapeType.rect, {
    x: 0, y: 0, w: '100%', h: 0.8,
    fill: { color: '2563EB' },
    line: { color: '2563EB' },
  })

  // Title
  slide.addText(section.title, {
    x:        0.3,
    y:        0.1,
    w:        '90%',
    h:        0.6,
    fontSize: 22,
    bold:     true,
    color:    'FFFFFF',
    fontFace: 'Calibri',
  })

  // Bullet points
  slide.addText(
    section.bullets.map(bullet => ({
      text:    bullet,
      options: {
        bullet: { type: 'bullet', characterCode: '25CF' }, // filled circle
        paraSpaceAfter: 8,
      },
    })),
    {
      x:        0.5,
      y:        1.1,
      w:        '90%',
      h:        '75%',
      fontSize: 16,
      color:    '374151',
      fontFace: 'Calibri',
      valign:   'top',
    }
  )

  // Slide number
  slide.addText(`${section.slideNumber}`, {
    x:        '93%',
    y:        '92%',
    w:        '5%',
    h:        '6%',
    fontSize: 10,
    color:    '9CA3AF',
    align:    'right',
  })
}

Chart Slide

function addChartSlide(pptx: PptxGenJS, chartData: ChartData) {
  const slide = pptx.addSlide()

  // Header
  slide.addShape(pptx.ShapeType.rect, {
    x: 0, y: 0, w: '100%', h: 0.8,
    fill: { color: '2563EB' },
    line: { color: '2563EB' },
  })
  slide.addText(chartData.title, {
    x: 0.3, y: 0.1, w: '90%', h: 0.6,
    fontSize: 22, bold: true, color: 'FFFFFF',
  })

  // Bar chart
  slide.addChart(pptx.ChartType.bar, [
    {
      name:   chartData.seriesName,
      labels: chartData.labels,
      values: chartData.values,
    },
  ], {
    x:     0.5,
    y:     1.0,
    w:     9.0,
    h:     5.0,
    chartColors:  ['2563EB', '10B981', 'F59E0B', 'EF4444'],
    showValue:    true,
    showLegend:   true,
    legendPos:    'b',
    dataLabelFontSize: 10,
    catAxisLabelFontSize: 11,
    valAxisLabelFontSize: 11,
    title:         chartData.title,
    showTitle:     false,
  })
}

// Line chart for trends
slide.addChart(pptx.ChartType.line, [
  { name: 'Revenue', labels: months, values: revenueData },
  { name: 'Costs',   labels: months, values: costData },
], {
  x: 0.5, y: 1.0, w: 9.0, h: 5.0,
  lineSize:    2,
  showLegend:  true,
  showMarker:  true,
  chartColors: ['2563EB', 'EF4444'],
})

Table Slide

function addTableSlide(pptx: PptxGenJS, tableData: TableData) {
  const slide = pptx.addSlide()

  const rows: PptxGenJS.TableRow[] = [
    // Header row
    tableData.headers.map(h => ({
      text: h,
      options: {
        bold:     true,
        color:    'FFFFFF',
        fill:     { color: '2563EB' },
        fontSize: 12,
        align:    'center' as const,
      },
    })),
    // Data rows
    ...tableData.rows.map((row, i) =>
      row.map(cell => ({
        text: cell,
        options: {
          fontSize: 11,
          color:    '374151',
          fill:     i % 2 === 0 ? { color: 'F8FAFC' } : { color: 'FFFFFF' },
        },
      }))
    ),
  ]

  slide.addTable(rows, {
    x:     0.3,
    y:     1.0,
    w:     9.4,
    border: { type: 'solid', color: 'E5E7EB', pt: 0.5 },
    colW:  tableData.columnWidths,
  })
}

NestJS Integration

// presentations/presentations.service.ts
@Injectable()
export class PresentationsService {
  async generateReport(reportId: string): Promise<Buffer> {
    const report = await this.reportsRepo.findOneOrFail(reportId)

    return generatePresentation({
      title:    report.title,
      subtitle: report.period,
      subject:  'Monthly Report',
      sections: report.sections.map(s => ({
        title:  s.heading,
        bullets: s.points,
        slideNumber: s.order,
      })),
      chartData: {
        title:      'Revenue Trend',
        seriesName: 'Revenue',
        labels:     report.chart.months,
        values:     report.chart.values,
      },
      keyPoints: report.summary,
    })
  }
}

// presentations/presentations.controller.ts
@Get(':id/pptx')
@UseGuards(JwtAuthGuard)
async downloadPptx(
  @Param('id') id: string,
  @Res() res: Response,
) {
  const buffer = await this.presentationsService.generateReport(id)

  res.set({
    'Content-Type':        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    'Content-Disposition': `attachment; filename="report-${id}.pptx"`,
    'Content-Length':      buffer.length,
  })

  res.end(buffer)
}

Forbidden Patterns

  • Never use absolute pixel values for positioning — use percentages or inch values for portability
  • Never forget to await pptx.write() — it returns a Promise
  • Never include user-provided text without escaping HTML entities in text fields
  • Never create slides in a loop without checking memory — large decks need streaming or chunking
Files (antigravity-fullstack-hq)
  • SKILL.md 7.1 KB
    ---
    name: pptx-official
    description: Generating PowerPoint presentations with pptxgenjs in Node.js. Use when creating automated presentations, slide decks, pitch decks, or reports in .pptx format from data.
    ---
    
    # PowerPoint Generation with pptxgenjs
    
    ## Installation
    
    ```bash
    npm install pptxgenjs
    npm install -D @types/node
    ```
    
    ## Basic Presentation
    
    ```typescript
    import PptxGenJS from 'pptxgenjs'
    
    async function generatePresentation(data: PresentationData): Promise<Buffer> {
      const pptx = new PptxGenJS()
    
      // Global settings
      pptx.author  = 'Full Stack HQ'
      pptx.company = 'Full Stack HQ'
      pptx.title   = data.title
      pptx.subject = data.subject
      pptx.layout  = 'LAYOUT_WIDE'  // 16:9
    
      // ─── Title Slide ─────────────────────────────────────────
      const titleSlide = pptx.addSlide()
      titleSlide.background = { color: '1E3A5F' }
    
      titleSlide.addText(data.title, {
        x:     '10%',
        y:     '35%',
        w:     '80%',
        h:     '20%',
        fontSize:  40,
        bold:      true,
        color:     'FFFFFF',
        align:     'center',
        fontFace:  'Calibri',
      })
    
      titleSlide.addText(data.subtitle, {
        x:        '15%',
        y:        '60%',
        w:        '70%',
        h:        '10%',
        fontSize: 20,
        color:    'B0C4DE',
        align:    'center',
      })
    
      titleSlide.addText(new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long' }), {
        x:        '0%',
        y:        '88%',
        w:        '100%',
        h:        '8%',
        fontSize: 12,
        color:    '7094B5',
        align:    'center',
      })
    
      // ─── Content Slides ───────────────────────────────────────
      for (const section of data.sections) {
        addContentSlide(pptx, section)
      }
    
      // ─── Chart Slide ──────────────────────────────────────────
      if (data.chartData) {
        addChartSlide(pptx, data.chartData)
      }
    
      // ─── Summary Slide ────────────────────────────────────────
      addSummarySlide(pptx, data.keyPoints)
    
      // Return as buffer
      const buffer = await pptx.write({ outputType: 'nodebuffer' }) as Buffer
      return buffer
    }
    ```
    
    ## Content Slide with Bullets
    
    ```typescript
    function addContentSlide(pptx: PptxGenJS, section: Section) {
      const slide = pptx.addSlide()
    
      // Slide header bar
      slide.addShape(pptx.ShapeType.rect, {
        x: 0, y: 0, w: '100%', h: 0.8,
        fill: { color: '2563EB' },
        line: { color: '2563EB' },
      })
    
      // Title
      slide.addText(section.title, {
        x:        0.3,
        y:        0.1,
        w:        '90%',
        h:        0.6,
        fontSize: 22,
        bold:     true,
        color:    'FFFFFF',
        fontFace: 'Calibri',
      })
    
      // Bullet points
      slide.addText(
        section.bullets.map(bullet => ({
          text:    bullet,
          options: {
            bullet: { type: 'bullet', characterCode: '25CF' }, // filled circle
            paraSpaceAfter: 8,
          },
        })),
        {
          x:        0.5,
          y:        1.1,
          w:        '90%',
          h:        '75%',
          fontSize: 16,
          color:    '374151',
          fontFace: 'Calibri',
          valign:   'top',
        }
      )
    
      // Slide number
      slide.addText(`${section.slideNumber}`, {
        x:        '93%',
        y:        '92%',
        w:        '5%',
        h:        '6%',
        fontSize: 10,
        color:    '9CA3AF',
        align:    'right',
      })
    }
    ```
    
    ## Chart Slide
    
    ```typescript
    function addChartSlide(pptx: PptxGenJS, chartData: ChartData) {
      const slide = pptx.addSlide()
    
      // Header
      slide.addShape(pptx.ShapeType.rect, {
        x: 0, y: 0, w: '100%', h: 0.8,
        fill: { color: '2563EB' },
        line: { color: '2563EB' },
      })
      slide.addText(chartData.title, {
        x: 0.3, y: 0.1, w: '90%', h: 0.6,
        fontSize: 22, bold: true, color: 'FFFFFF',
      })
    
      // Bar chart
      slide.addChart(pptx.ChartType.bar, [
        {
          name:   chartData.seriesName,
          labels: chartData.labels,
          values: chartData.values,
        },
      ], {
        x:     0.5,
        y:     1.0,
        w:     9.0,
        h:     5.0,
        chartColors:  ['2563EB', '10B981', 'F59E0B', 'EF4444'],
        showValue:    true,
        showLegend:   true,
        legendPos:    'b',
        dataLabelFontSize: 10,
        catAxisLabelFontSize: 11,
        valAxisLabelFontSize: 11,
        title:         chartData.title,
        showTitle:     false,
      })
    }
    
    // Line chart for trends
    slide.addChart(pptx.ChartType.line, [
      { name: 'Revenue', labels: months, values: revenueData },
      { name: 'Costs',   labels: months, values: costData },
    ], {
      x: 0.5, y: 1.0, w: 9.0, h: 5.0,
      lineSize:    2,
      showLegend:  true,
      showMarker:  true,
      chartColors: ['2563EB', 'EF4444'],
    })
    ```
    
    ## Table Slide
    
    ```typescript
    function addTableSlide(pptx: PptxGenJS, tableData: TableData) {
      const slide = pptx.addSlide()
    
      const rows: PptxGenJS.TableRow[] = [
        // Header row
        tableData.headers.map(h => ({
          text: h,
          options: {
            bold:     true,
            color:    'FFFFFF',
            fill:     { color: '2563EB' },
            fontSize: 12,
            align:    'center' as const,
          },
        })),
        // Data rows
        ...tableData.rows.map((row, i) =>
          row.map(cell => ({
            text: cell,
            options: {
              fontSize: 11,
              color:    '374151',
              fill:     i % 2 === 0 ? { color: 'F8FAFC' } : { color: 'FFFFFF' },
            },
          }))
        ),
      ]
    
      slide.addTable(rows, {
        x:     0.3,
        y:     1.0,
        w:     9.4,
        border: { type: 'solid', color: 'E5E7EB', pt: 0.5 },
        colW:  tableData.columnWidths,
      })
    }
    ```
    
    ## NestJS Integration
    
    ```typescript
    // presentations/presentations.service.ts
    @Injectable()
    export class PresentationsService {
      async generateReport(reportId: string): Promise<Buffer> {
        const report = await this.reportsRepo.findOneOrFail(reportId)
    
        return generatePresentation({
          title:    report.title,
          subtitle: report.period,
          subject:  'Monthly Report',
          sections: report.sections.map(s => ({
            title:  s.heading,
            bullets: s.points,
            slideNumber: s.order,
          })),
          chartData: {
            title:      'Revenue Trend',
            seriesName: 'Revenue',
            labels:     report.chart.months,
            values:     report.chart.values,
          },
          keyPoints: report.summary,
        })
      }
    }
    
    // presentations/presentations.controller.ts
    @Get(':id/pptx')
    @UseGuards(JwtAuthGuard)
    async downloadPptx(
      @Param('id') id: string,
      @Res() res: Response,
    ) {
      const buffer = await this.presentationsService.generateReport(id)
    
      res.set({
        'Content-Type':        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        'Content-Disposition': `attachment; filename="report-${id}.pptx"`,
        'Content-Length':      buffer.length,
      })
    
      res.end(buffer)
    }
    ```
    
    ## Forbidden Patterns
    
    - Never use absolute pixel values for positioning — use percentages or inch values for portability
    - Never forget to `await pptx.write()` — it returns a Promise
    - Never include user-provided text without escaping HTML entities in text fields
    - Never create slides in a loop without checking memory — large decks need streaming or chunking
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related