Package Exports
- slidewave
- slidewave/package.json
Readme
Slidewave
Low-level JS library for generating beautiful
.pptxfiles. pptxgenjs-compatible API, but with designer-grade primitives that LLMs can't uniformize.
Slidewave is a drop-in replacement for pptxgenjs that keeps its low-level API (inches, addText, addShape...) but adds rich primitives you can't get otherwise:
- π Mesh / radial / linear gradient backgrounds
- π«§ Organic blob shapes (seeded SVG, deterministic)
- β¨ Gradient-filled text (magazine-style)
- πͺ Glass-morphism cards with tint, border, highlight
- ποΈ Film grain textures
- π― Full pptxgenjs escape hatch β nothing is taken from you
Why
LLMs (Claude, GPT, Geminiβ¦) generating slides via pptxgenjs all produce the same thing: rectangles, limited gradients, identifiable-at-a-glance AI slides. Slidewave gives those same LLMs β and you β richer primitives to output .pptx files that look designed, not templated.
Install
npm install slidewave pptxgenjspptxgenjs is a peer dependency so you control its version.
Browser-only. Slidewave uses
Canvas,ImageandBlobto rasterize SVG primitives. It does not run in Node without a DOM shim.
Quick start
import { Pres } from 'slidewave'
const pres = new Pres({ layout: 'LAYOUT_WIDE', title: 'Demo' })
const slide = pres.addSlide()
// Rich background (mesh / aurora)
await slide.addBackground({
gradient: {
type: 'mesh',
base: '#0b0b0f',
colors: ['#6366f1', '#8b5cf6', '#ec4899'],
blur: 80,
},
})
// Native editable text (stays editable in PowerPoint)
slide.addText('Hello world', {
x: 1, y: 1, w: 11, h: 2,
fontFace: 'Fraunces', fontSize: 140,
color: '#ffffff', italic: true,
charSpacing: -1, // POINTS β tight spacing
lineSpacingMultiple: 1.05,
})
// Gradient-filled text (rasterized, non-editable but visually impossible otherwise)
await slide.addGradientText('Redesigned.', {
x: 1, y: 3.2, w: 11, h: 2,
fontFamily: 'Fraunces, serif',
fontSize: 180, fontWeight: 500,
gradient: ['#ffffff', '#a5b4fc'],
angle: 180,
})
// Organic blob
await slide.addBlob({
x: 8.5, y: 0.5, w: 4.5, h: 4.5,
seed: 7, points: 9, irregularity: 0.35,
fillGradient: ['#ec4899', '#f59e0b'],
})
await pres.save('demo.pptx')API
new Pres(options)
new Pres({
layout?: 'LAYOUT_WIDE' | 'LAYOUT_16x9' | 'LAYOUT_16x10' | 'LAYOUT_4x3',
title?: string, author?: string, company?: string, subject?: string,
})| Method | Returns | Description |
|---|---|---|
addSlide(opts?) |
Slide |
Adds a new slide |
size() |
{ width, height } |
Slide dimensions in inches |
save(filename) |
Promise<void> |
Triggers browser download |
toBlob() |
Promise<Blob> |
Returns the raw .pptx blob |
toArrayBuffer() |
Promise<ArrayBuffer> |
Returns raw bytes |
.ShapeType, .AlignH, .AlignV |
pptxgenjs constants |
Slide β native primitives (editable in PowerPoint)
All coordinates are in inches. 16:9 wide = 13.333 Γ 7.5.
slide.addText(text, opts)
slide.addText('Title', {
x: 1, y: 1, w: 10, h: 1.2,
fontFace: 'Fraunces',
fontSize: 72,
color: '#0b0b0f',
bold, italic, underline,
align: 'left' | 'center' | 'right',
valign: 'top' | 'middle' | 'bottom',
charSpacing: 2, // POINTS β typical 2..6, negative = tighter
lineSpacingMultiple: 1.1,
shadow: { type: 'outer', blur: 20, offset: 4, angle: 90, color: '#000', opacity: 0.3 },
glow: { size: 8, opacity: 0.5, color: '#6366f1' },
outline:{ size: 1, color: '#000' },
})
charSpacingis in POINTS. Typical values:2to6. Negative tightens. Setting it to300will break your layout.
slide.addRect(opts)
slide.addRect({
x: 1, y: 3, w: 5, h: 2,
fill: '#818cf8', // or { type: 'solid', color }
radius: 0.2, // inches
borderColor: '#1e1b4b', borderWidth: 1,
shadow: { type: 'outer', blur: 40, offset: 20, angle: 90, color: '#000', opacity: 0.15 },
rotate: 0,
})Other native methods
slide.addShape('ellipse' | 'triangle' | ..., opts) // any pptxgenjs shape
slide.addLine({ x1, y1, x2, y2, color, width })
slide.addImage({ x, y, w, h, data, path })
slide.raw() // underlying pptxgenjs slideSlide β rich primitives (rasterized)
These are async because they render SVG β PNG before embedding.
slide.addBackground(opts)
await slide.addBackground({ color: '#fafaf7' })
await slide.addBackground({
gradient: {
type: 'mesh' | 'linear' | 'radial',
colors: ['#6366f1', '#8b5cf6', '#ec4899'],
base: '#0b0b0f', // mesh only β backdrop
angle: 135, // linear only
blur: 80, // mesh only
},
})slide.addGradientText(text, opts)
await slide.addGradientText('Hello', {
x, y, w, h,
fontFamily: 'Fraunces, serif',
fontSize: 140, fontWeight: 500,
fontStyle: 'normal' | 'italic',
letterSpacing: -0.03, // em units
lineHeight: 1.1,
align: 'left' | 'center' | 'right',
gradient: ['#6366f1', '#ec4899'],
angle: 135,
})slide.addBlob(opts)
await slide.addBlob({
x, y, w, h,
seed: 42, // deterministic PRNG
points: 8, // control points
irregularity: 0.4, // 0..1
fill: '#6366f1',
fillGradient: ['#ec4899', '#f59e0b'],
gradientAngle: 135,
})slide.addGlassCard(opts)
await slide.addGlassCard({
x, y, w, h,
tint: '#ffffff', tintOpacity: 0.12,
borderColor: '#ffffff', borderOpacity: 0.2, borderWidth: 2,
radius: 24,
highlight: true, // inner top reflection
})slide.addGrain(opts) Β· slide.addGradientRect(opts)
await slide.addGrain({ x, y, w, h, opacity: 0.08, monochrome: true })
await slide.addGradientRect({
x, y, w, h,
type: 'linear', colors: ['#0b0b0f', '#1e1b4b'], angle: 135,
})Low-level escape hatch
Nothing from pptxgenjs is hidden:
const rawSlide = slide.raw()
rawSlide.addChart(pres._pptx.ChartType.bar, data, chartOpts)
pres._pptx.defineSlideMaster({ ... })Exposed utilities
For advanced usage β build your own primitives:
import {
blobSvg, gradientSvg, gradientTextSvg, glassSvg,
svgToPngDataUrl, generateGrainPng,
normalizeHex, hexToRgb, rgbToHex, mix,
} from 'slidewave'Design rules
- Sync methods β native PPT XML β text + shapes stay editable
- Async methods β rasterized PNG β visually impossible effects, non-editable
- All sizes in inches (pptxgenjs-compatible)
- All colors as
#RRGGBBorRRGGBB pptxgenjsis a peer dep β use any compatible version you want
Use with LLMs
Slidewave is designed so agents (Claude, GPT, Gemini, Mistral) can produce richer output than pptxgenjs allows. Give an LLM the API reference above as part of your system prompt, and it will emit code that produces editorial-grade slides.
Development
git clone https://github.com/NdandaClaude/slidewave
cd slidewave
npm install
npm run dev # demo playground at localhost:5173
npm run build:lib # build library to dist/
npm run pack:check # verify npm package contentsRoadmap
- More primitives:
addIsometricGrid,addCodeBlock(syntax-highlighted),addIcon(Lucide) - Editorial-grade chart styles
- Node-compatible rasterizer (via
@napi-rs/canvas) for SSR use - Monaco-based playground
License
MIT Β© 2026 Claude Ndanda