Core library workflows

To create slides by editing TSX with an AI agent and a live preview, start with

Create slides with AI. This page covers the underlying function API.

This page walks the canonical @office-kit/pptx workflows: fill a template, build a deck from scratch, edit images in place. Every snippet below is a real .ts file in this repo — svelte-check compiles them against the live @office-kit/pptx types on every build, so when this page renders, it’s already proven that the code typechecks.

Token-based template fill

The most common @office-kit/pptx use case: take a designer-authored template, swap {{tokens}} with your data, save. Formatting on the surrounding runs is preserved.

site/src/lib/examples/template-fill.ts
// Open a template .pptx, replace `{{tokens}}` everywhere, save it back.
//
// This file is imported as ?raw into the docs site so the snippet shown
// to readers is exactly what svelte-check / tsc compiled — if an API
// rename breaks this import, the docs build fails before deploy.

import { readFile, writeFile } from 'node:fs/promises';
import { loadPresentation, replaceTokensInPresentation, savePresentation } from '@office-kit/pptx';

const pres = await loadPresentation(await readFile('template.pptx'));
replaceTokensInPresentation(pres, {
  name: 'Yamashita',
  event: 'Re:Invent',
  date: '2026-12-01',
});
await writeFile('out.pptx', await savePresentation(pres));

loadPresentation accepts a Uint8Array, ArrayBuffer, or Blob — anything you can fetch or readFile. replaceTokensInPresentation walks every text run in every slide (and the speaker notes) replacing exact-match {{name}} tokens.

Build a deck from scratch

createPresentation() returns an empty deck that already carries a slide master, a default theme, and three layouts (Blank, Title Slide, Title and Content), so there is no template file to ship. Add slides with addTitleSlide / addContentSlide / addBlankSlide, then fill them in with the typed addSlide* helpers:

site/src/lib/examples/build-deck.ts
// Build a deck from scratch: start from the built-in empty deck, add slides
// on its layouts, drop in a text box, an image, and a chart, then save.

import { readFile, writeFile } from 'node:fs/promises';
import {
  addBlankSlide,
  addSlideChart,
  addSlideImage,
  addSlideTextBox,
  addTitleSlide,
  createPresentation,
  inches,
  savePresentation,
} from '@office-kit/pptx';

const pres = createPresentation();
addTitleSlide(pres, 'Q3 review');

const slide = addBlankSlide(pres);
addSlideTextBox(slide, {
  x: inches(0.7),
  y: inches(0.5),
  w: inches(9),
  h: inches(0.7),
  text: 'Numbers up and to the right',
});
addSlideChart(slide, {
  x: inches(0.7),
  y: inches(1.5),
  w: inches(8),
  h: inches(4.5),
  spec: {
    kind: 'column',
    categories: ['Q1', 'Q2', 'Q3', 'Q4'],
    series: [{ name: 'Revenue', values: [120, 180, 240, 300] }],
    title: 'FY26',
  },
});
addSlideImage(slide, await readFile('logo.png'), {
  x: inches(8),
  y: inches(0.4),
  w: inches(1.5),
  h: inches(1),
});

await writeFile('out.pptx', await savePresentation(pres));

inches(n), cm(n), pt(n), and emu(n) all return a branded Emu number — internally @office-kit/pptx only sees EMUs, so unit confusion is caught at the type level.

Replace an image, preserve geometry

A common L2 (template-edit) workflow: a designer drops a placeholder image into the template, your code swaps in the real one without disturbing crop, position, or scaling.

site/src/lib/examples/image-replace.ts
// Swap an image in a template, preserving its crop / transform / sizing.
// The format is auto-detected from the new bytes.

import { readFile, writeFile } from 'node:fs/promises';
import {
  getShapeKind,
  getShapeName,
  getSlideShapes,
  getSlides,
  loadPresentation,
  savePresentation,
  setShapeImage,
} from '@office-kit/pptx';

const pres = await loadPresentation(await readFile('template.pptx'));
const newLogo = await readFile('new-logo.png');

for (const slide of getSlides(pres)) {
  for (const shape of getSlideShapes(slide)) {
    if (getShapeKind(shape) === 'picture' && getShapeName(shape) === 'Logo') {
      setShapeImage(shape, newLogo);
    }
  }
}
await writeFile('out.pptx', await savePresentation(pres));

setShapeImage auto-detects the new image’s format (PNG / JPEG / GIF / SVG / BMP / TIFF) from magic bytes — pass options.format to override.

Direct fs helpers (Node)

@office-kit/pptx/node exposes loadPresentationFile / savePresentationToFile so you can skip the readFile / writeFile glue:

site/src/lib/examples/node-fs.ts
// One-shot read + save direct from / to disk via the @office-kit/pptx/node
// helpers, no manual fs glue needed.

import { loadPresentationFile, savePresentationToFile } from '@office-kit/pptx/node';

const pres = await loadPresentationFile('input.pptx');
// ...mutate pres...
await savePresentationToFile(pres, 'output.pptx');

Browser via fetch

The default entry is browser-safe (no node:fs). Load straight from a fetch Response:

site/src/lib/examples/browser-fetch.ts
// Browser: fetch a .pptx and load it. loadPresentation accepts any of
// Uint8Array / ArrayBuffer / Blob — `await response.arrayBuffer()` is the
// most browser-portable form.

import { getSlides, getSlideTitle, loadPresentation } from '@office-kit/pptx';

const response = await fetch('/template.pptx');
const pres = await loadPresentation(await response.arrayBuffer());
for (const slide of getSlides(pres)) {
  console.log(getSlideTitle(slide));
}

This works in any environment with fetch: modern browsers, Bun, Deno, Cloudflare Workers, edge runtimes.

What’s next

  • Recipes — copy-pasteable code for the most common tasks (charts, tables, comments, animations, transitions, validation).
  • Cheatsheet — one-page lookup: "I want to do X" → exact functions to call.
  • API reference — every export, organized by section.
  • GitHub: office-kit/pptx