WebDocs SDK
A TypeScript API for the browser-native WebDocs engine. Load a Word document, read and mutate its model, drive the WebGPU renderer and the PDF/DOCX/ODT export — all from your own app, over one small, versioned C ABI.
WebDocs is a from-scratch word processor compiled to WebAssembly and drawn entirely on
the GPU (see Technology). The SDK
(@squareys/webdecks-sdk) is the supported way to build on that engine: a
thin, zero-garbage binding that speaks to the wasm through a curated
wdoc_sdk_* C ABI — not the raw exports. It is the same surface our own UI
is being rebuilt on, so what you get is dogfooded by construction.
Status
The SDK is WebDocs-only today, covering load, model read/update, caret and selection, clipboard, styling, undo/redo, and rendering/export (ABI v2). WebSheets and WebDecks bindings share the same ABI shape and land in a later phase. The API is versioned and allowed to change before GA.
Import it
The SDK is authored in erasable-syntax-only TypeScript, resolved through its package exports:
# The SDK is a workspace package in the WebDecks monorepo.
# In your own project, add it as a dependency and import by name:
import { Webdocs, DFMT, createDocInfo } from "@squareys/webdecks-sdk";
The SDK is pure TypeScript — it drives a loaded wasm module, it does not ship
one. Loading the engine (webdocs.js / webdocs.wasm plus the UI
font) is the host's job; the reference demo's engine.ts is a copy-paste
starting point, and Live examples shows it in a
running editor.
A tiny editor in ~30 lines
Boot the engine, open a document, read it, make an edit, paint a page, and export — the whole loop, using nothing but the SDK:
import { Webdocs, DFMT, createDocInfo } from "@squareys/webdecks-sdk";
import { loadEngine } from "./engine"; // boots webdocs.wasm — see the reference demo
import { unzipDocx } from "./docx"; // inflates a .docx ZIP with DecompressionStream
// 1. Boot the engine and open a document.
const { mod } = await loadEngine("/engine/");
const doc = Webdocs.create(mod); // asserts the ABI version, opens a doc handle
// 2. Load a .docx the user picked (any File from an <input type=file>).
const parts = await unzipDocx(await file.arrayBuffer());
doc.loadDocxParts(parts);
// 3. Read the model into a reusable record (allocates nothing per call).
const info = createDocInfo();
doc.docInfo(info);
console.log(info.paraCount + " paragraphs, " + info.wordCount + " words");
// 4. Edit: bold the first three characters of paragraph 0.
doc.setCaret(0, 0);
doc.select(0, 0, 3);
doc.toggleFmt(DFMT.BOLD);
// 5. Render page 0 into a <canvas> via WebGPU (raw RGBA -> ImageData).
const [w, h] = [816, 1056]; // 8.5x11 inch @ 96dpi
const rgba = await doc.exportPng(0, w, h, 1);
canvas.getContext("2d").putImageData(
new ImageData(new Uint8ClampedArray(rgba), w, h), 0, 0);
// 6. Export — the same paths the WebDocs File menu uses.
const pdf = doc.exportPdf(); // Uint8Array: hand to a Blob download
const docx = doc.exportDocx(); Reading the model
The hot-path readers fill a record you own instead of allocating one per call — create the record once and reuse it across every read (this is the SDK's zero-garbage discipline, so a live editor can poll the model every frame without churning the GC):
const para = createParaInfo();
const run = createRunInfo();
for (let p = 0; p < info.paraCount; p++) {
doc.paraInfo(p, para); // textLen, align, style, indent, spacing
const text = doc.paraText(p); // the paragraph's UTF-8 text as a JS string
doc.runInfo(p, 0, run); // the formatting run starting at byte 0
const bold = (run.fmt & DFMT.BOLD) !== 0;
} Concepts worth knowing
- Numeric handles. A document is a
u32handle into the engine;0xFFFFFFFFis the null. Lifetime is explicit —Webdocs.create()opens one,doc.close()releases it. Nothing relies on the garbage collector to free wasm memory. - ABI-version gate.
Webdocs.create()reads the wasm's ABI version and refuses a module it wasn't generated against, so a mismatched engine fails loudly at startup instead of corrupting reads. - Positions are (paragraph, byte). The caret and selection are paragraph index + UTF-8 byte offset pairs — no NUL scanning, and stable across reads.
- Export mirrors the UI.
exportPdf(),exportDocx()andexportPng()reuse the exact paths the WebDocs File menu uses, so a consumer gets pixel and print parity for free. PDF/PNG need a WebGPU device; DOCX/ODT do not.
Next
Read the API reference for every operation, or open the live examples — a full React editor built on the SDK, plus copy-paste snippets.