Skip to content

codevakure/presentx

Repository files navigation

presentx

HTML slide presentation generator with PPTX export, self-healing validation, brand injection, and a streaming React viewer.

Generate slide decks from HTML, preview them live with streaming support, and export to editable PowerPoint files -- all client-side.

Features

  • HTML to PPTX -- Convert HTML slides to editable PowerPoint files with native charts, preserved layouts, and editable text
  • Self-healing validator -- Automatically fixes missing dimensions, overflow, flex layout, chart types, and other common LLM output issues
  • Streaming React viewer -- Progressive rendering with skeleton loading, slide counter, and auto-scroll during generation
  • Brand injection -- Automatically inject logos, headers, footers, and copyright into every slide via theme configuration
  • Customizable themes -- Register themes with colors, fonts, chart palettes, table styles, and brand assets
  • LLM prompt generation -- Theme-aware system prompt fragments for teaching LLMs to create slide presentations
  • Native Chart.js support -- Chart.js data in slides is converted to native, editable PowerPoint charts
  • Material Icons -- Automatic rasterization of Material Icons for PPTX compatibility

Installation

npm install presentx

Quick Start

React Viewer

import { SlideViewer } from 'presentx/react';
import 'presentx/styles';

function App() {
  return (
    <SlideViewer
      html={slidesHtml}
      isStreaming={false}
      theme="default"
    />
  );
}

Export to PPTX

import { convertSlidesToPptx, validatePresentation } from 'presentx';

// Validate and self-heal the HTML
const report = validatePresentation(slidesHtml);

// Convert to PowerPoint
const blob = await convertSlidesToPptx(report.fixedHtml, 'My Presentation');

// Download
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'presentation.pptx';
a.click();

LLM Prompt Generation (Node.js)

const { getSlideInstructions } = require('presentx/prompts');

const prompt = getSlideInstructions({ theme: 'my-brand' });
// Returns a system prompt fragment that teaches the LLM how to create slides

Entry Points

Import Environment Contents
presentx Browser Converter, validator, themes, brand injection, utilities
presentx/react Browser + React SlideViewer, SlideCounter components
presentx/prompts Node.js / Browser LLM instruction generation, routing rules, theme registry
presentx/styles Browser CSS for the React viewer

Integrating with LLM / Chat Platforms

presentx is designed to work with any LLM-powered chat platform. The library provides system prompt fragments that teach models how to generate slide HTML, a streaming viewer for real-time preview, and a PPTX converter for download -- all decoupled so you can adopt them independently.

Step 1: Inject the System Prompt (Server-Side)

On your API server, use presentx/prompts to generate a system prompt fragment. This teaches the LLM the slide HTML format, available components (charts, tables, icons, images), layout rules, and your brand palette.

// server/prompts.js
const { getSlideInstructions, registerTheme } = require('presentx/prompts');

// Optional: register a custom brand theme
registerTheme({
  name: 'my-brand',
  colors: {
    primary: '#1a1a2e',
    accent: '#e94560',
    text: '#333333',
    textLight: '#888888',
    bgDark: '#1a1a2e',
    bgLight: '#f5f5f5',
  },
  fonts: { heading: 'Montserrat', body: 'Inter' },
  chartPalette: ['#1a1a2e', '#e94560', '#0f3460', '#16213e', '#533483'],
});

// Generate the slide instructions
const slidePrompt = getSlideInstructions({
  theme: 'my-brand',
  // Optional: add platform-specific instructions on top
  extraInstructions: '## Platform Rules:\n- Use websearch for images\n- No red in charts',
});

// Append to your system prompt
const systemPrompt = baseSystemPrompt + '\n\n' + slidePrompt;

The prompt includes:

  • Slide frame templates (960x540px body slides, title/closing slides)
  • Font scale, layout patterns (KPIs, timelines, grids, charts)
  • Chart.js <canvas> + <script class="chart-data"> syntax
  • Table styling with inline styles for PPTX compatibility
  • Brand palette, fonts, and branding notices from your theme
  • Hard rules (no truncation, complete tags, HTTPS images, etc.)

Step 2: Detect and Render Slides (Client-Side)

When the LLM responds with slide content (using your artifact syntax or a marker), render it with the SlideViewer:

// client/SlideArtifact.tsx
import { SlideViewer } from 'presentx/react';
import { registerTheme } from 'presentx';
import 'presentx/styles';

// Register the same theme on the client (for brand injection in the viewer)
registerTheme({
  name: 'my-brand',
  colors: { /* same as server */ },
  fonts: { /* same as server */ },
  chartPalette: [ /* same as server */ ],
  brand: {
    logo: '<svg>...</svg>',           // Inline SVG or image URL
    logoDark: '<svg>...</svg>',       // Optional: for dark slide backgrounds
    logoIcon: '<svg>...</svg>',       // Optional: small icon for body slide headers
    name: 'My Company',
    header: {
      enabled: true,
      content: 'icon',               // 'logo' | 'icon' | 'name'
      position: 'right',
      height: 36,
    },
    footer: {
      enabled: true,
      showLogo: true,
      logoPosition: 'right',
      copyright: '© 2025 My Company',
      copyrightPosition: 'left',
      height: 32,
    },
  },
});

function SlideArtifact({ html, isStreaming }: { html: string; isStreaming: boolean }) {
  return (
    <SlideViewer
      html={html}
      isStreaming={isStreaming}
      theme="my-brand"
    />
  );
}

The viewer handles:

  • Streaming: progressively renders slides as the LLM generates HTML tokens
  • Validation: auto-fixes malformed slides (missing dimensions, broken tags)
  • Brand injection: overlays logo/header/footer from the theme config
  • Iframe sandbox: slides render in a sandboxed iframe with Tailwind, Google Fonts, Material Icons, and Chart.js pre-loaded

Step 3: PPTX Download (Client-Side)

Add a download button that converts the viewed slides to an editable PowerPoint file:

import { convertSlidesToPptx, validatePresentation, getTheme, injectBrand } from 'presentx';

async function downloadPptx(html: string, title: string) {
  // 1. Validate and self-heal
  const report = validatePresentation(html);

  // 2. Inject brand elements (logo, header, footer)
  const theme = getTheme('my-brand');
  const branded = injectBrand(report.fixedHtml, theme);

  // 3. Convert to PPTX
  const blob = await convertSlidesToPptx(branded, title, { theme: 'my-brand' });

  // 4. Trigger download
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `${title}.pptx`;
  a.click();
  URL.revokeObjectURL(url);
}

The PPTX converter:

  • Renders slides in a hidden iframe to capture exact layout via getBoundingClientRect()
  • Converts Chart.js canvases to native editable PPTX charts
  • Rasterizes SVG logos and Material Icons to embedded PNGs
  • Embeds fonts for cross-platform fidelity
  • Preserves table styles, borders, and zebra striping

Architecture Overview

LLM generates HTML slides
    |
    v
getSlideInstructions()     <-- Server: teaches LLM the slide format
    |
    v
validatePresentation()     <-- Client: self-heals malformed output
    |
    v
injectBrand()              <-- Client: adds logo/header/footer from theme
    |
    +---> SlideViewer       <-- Client: live preview (streaming or static)
    |
    +---> convertSlidesToPptx()  <-- Client: export to editable PowerPoint
              |
              v
          PptxGenJS engine  <-- DOM traversal + native charts + font embedding

Themes

Built-in Theme

  • default -- Neutral palette (navy primary, light blue accent, Arial fonts)

Registering a Custom Theme

import { registerTheme } from 'presentx';

registerTheme({
  name: 'my-brand',
  colors: {
    primary: '#1a1a2e',
    accent: '#e94560',
    text: '#333333',
    textLight: '#888888',
    bgDark: '#1a1a2e',
    bgLight: '#f5f5f5',
  },
  fonts: {
    heading: 'Montserrat',
    body: 'Inter',
  },
  chartPalette: ['#1a1a2e', '#e94560', '#0f3460', '#16213e', '#533483'],
  // Optional: additional named colors for the LLM prompt
  extendedColors: {
    borders: '#cccccc',
    'subtle bg': '#e8e8e8',
  },
  // Optional: table styling
  tableStyle: {
    headerBg: '#1a1a2e',
    headerText: '#ffffff',
    headerTextTransform: 'uppercase',
    headerFontWeight: '700',
    evenRowBg: '#ffffff',
    oddRowBg: '#f5f5f5',
    rowText: '#333333',
    rowBorder: true,
    rowBorderColor: 'rgba(0,0,0,0.08)',
  },
});

Brand Injection

Add a brand property to your theme to auto-inject logos, headers, and footers on every slide:

registerTheme({
  name: 'my-brand',
  colors: { /* ... */ },
  fonts: { /* ... */ },
  chartPalette: [ /* ... */ ],
  brand: {
    logo: '<svg>...</svg>',              // Full wordmark (light bg)
    logoDark: '<svg>...</svg>',          // Full wordmark (dark bg)
    logoIcon: '<svg>...</svg>',          // Small icon mark (light bg)
    logoIconDark: '<svg>...</svg>',      // Small icon mark (dark bg)
    name: 'My Company',
    header: {
      enabled: true,                     // Show header bar on body slides
      content: 'icon',                   // 'logo' | 'icon' | 'name'
      position: 'right',                 // 'left' | 'right'
      height: 36,
    },
    footer: {
      enabled: true,                     // Show footer bar
      showLogo: true,
      logoPosition: 'right',
      copyright: '© 2025 My Company',
      copyrightPosition: 'left',
      height: 32,
      showBorder: false,
    },
  },
});

Three slide types get different brand treatment:

  • Title slide (first): Full wordmark logo at top-left + copyright footer
  • Closing slide (last): Same as title slide
  • Body slides (middle): Icon in header bar + full footer with logo and copyright

The LLM prompt automatically includes branding notices so the model knows not to manually add logos.

Slide HTML Format

Slides use Tailwind CSS classes inside 960x540px containers:

<div class="slide w-[960px] h-[540px] overflow-hidden relative flex flex-col pt-[48px] pb-[44px] px-[40px]">
  <div class="shrink-0 pb-2 mb-3 border-b border-black/[0.06]">
    <h2 class="text-[28px] font-bold leading-tight">Slide Title</h2>
  </div>
  <div class="flex-grow min-h-0 flex flex-col">
    <!-- Body content fills remaining space -->
  </div>
</div>

Charts

Chart.js data embedded as JSON inside the slide:

<div class="slide w-[960px] h-[540px] overflow-hidden relative flex flex-col">
  <div class="flex-grow">
    <canvas data-chart-type="bar"></canvas>
  </div>
  <script type="application/json" class="chart-data">
    {"labels":["Q1","Q2","Q3","Q4"],"datasets":[{"label":"Revenue","data":[100,200,300,400]}]}
  </script>
</div>

Charts render as native editable charts in the exported PPTX.

API Reference

Main (presentx)

Export Description
convertSlidesToPptx(html, title, options?) Convert HTML slides to PPTX blob
validatePresentation(html) Validate and self-heal slide HTML
registerTheme(theme) Register a custom theme
getTheme(name?) Get a theme by name (default if omitted)
listThemes() List registered theme names
injectBrand(html, theme) Inject brand elements into slide HTML
getBrandCss(theme) Get brand CSS rules for a theme
countCompleteSlides(html) Count completed slides in HTML
extractCompleteSlides(html) Extract only complete slide divs
hasSlideContent(html) Check if HTML contains slides

React (presentx/react)

Export Description
SlideViewer Streaming slide viewer component (props: html, isStreaming, theme, className, onValidationReport)
SlideCounter Slide count indicator component

Prompts (presentx/prompts)

Export Description
getSlideInstructions(options?) Generate LLM system prompt for slide creation
getRoutingRules() Get artifact routing table entry
getArtifactTypeDescription() Get artifact type description string
registerTheme(theme) Register a theme (also available from main entry)
getTheme(name?) Get a theme (also available from main entry)

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Author

Varun Muppidi -- GitHub

License

MIT

About

HTML slide presentation generator with PPTX export, self-healing validation, brand injection, and streaming React viewer

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors