Read, edit, and write Office files in TypeScript

Three libraries, one for each file format. Each opens existing files as well as creating new ones, follows the ECMA-376 spec, and runs in Node and the browser from a single ESM build.

@office-kit/pptx

Open a deck made in PowerPoint, Keynote, or Google Slides, fill its placeholders, add slides, charts, and tables, and save it back. A companion package draws slides as SVG and PNG, so you can check a deck without opening Office.

import {
  loadPresentation,
  replaceTokensInPresentation,
  savePresentation,
} from '@office-kit/pptx';

// A designer makes template.pptx. Your code fills it in.
const pres = await loadPresentation(templateBytes);
replaceTokensInPresentation(pres, {
  name: 'Alice',
  event: 'Re:Invent',
});
const out = await savePresentation(pres);

@office-kit/xlsx

Read and write workbooks with styles, formulas, charts, and conditional formatting. Streaming reads and writes keep memory flat on sheets with millions of rows. Inspired by openpyxl.

import {
  fromResponse,
  loadWorkbook,
  workbookToBytes,
} from '@office-kit/xlsx/io';
import { setCell } from '@office-kit/xlsx/worksheet';

const response = await fetch('/input.xlsx');
const wb = await loadWorkbook(fromResponse(response));
const sheet = wb.sheets[0];
if (sheet?.kind === 'worksheet') {
  setCell(sheet.sheet, 1, 1, 'Hello from @office-kit/xlsx');
}
const out = await workbookToBytes(wb);

@office-kit/docx

Build a Word document from paragraphs, lists, tables, and images, or open an existing .docx as a template and replace its text. A companion package renders documents in the browser.

import {
  addBulletList,
  addTable,
  appendParagraph,
  createDocx,
  toUint8Array,
} from '@office-kit/docx';

const doc = createDocx({ paragraphs: ['Hello, world.'] });
appendParagraph(doc, 'Bullets:');
addBulletList(doc, ['one', 'two', 'three']);
addTable(doc, [
  ['Name', 'Score'],
  ['Alice', '90'],
]);
const out = toUint8Array(doc);

Built on the same rules

They read as well as they write.
Each library opens a file a person made, changes it, and saves it. Generating from nothing is one use; filling in a template someone designed is the more common one.
The spec is the source of truth.
The models follow ECMA-376, the Office Open XML standard. A file that opens in one app and breaks in another is treated as a bug, not a quirk.
One ESM build, in Node and in the browser.
No native modules and no Node-only built-ins on the hot path. The same import works in a server, a worker, and a web page.
You ship only what you import.
Every capability is a standalone function in a side-effect-free package, so a bundler drops whatever you do not call.
MIT, in one tier.
No paid edition holds back the features you need.