Learning in public — this documentation is written in the open and updated as the engine moves.
paged.Paged Docs
Scripting (paged.*)

Scripting with paged.*

The Boa-based scripting layer — a sandboxed ECMAScript surface for reading and authoring a paged document through the paged.* host API. The full surface is generated from the engine catalog.

Tier: IntermediateIntermediateIIexplanation

In short Paged embeds a Boa ECMAScript engine and exposes a single global, paged.*, for inspecting and editing the open document. The same surface runs in the editor's script panel/REPL and headless via the paged-run CLI. This reference is generated from the engine's own catalog, so it always matches the running engine exactly.

How a script becomes pixels

scriptpaged.* sourceBoa sandboxbudgeted ECMAScriptOperation channelone undoable logapplyrebuild listrenderrepaintpaged.undo() / redo()budgets: 10M loops · depth 512 · ~2s

Your script. Plain ECMAScript calling paged.* — no modules, no I/O.

A paged.* script runs in a sandboxed Boa engine; every write flows through the same Operation channel as the UI, so it re-renders live and is fully undoable.

The shape of a script

A script is plain ECMAScript (no modules, no I/O — see constraints). It addresses elements by id, reads with paged.inspect / paged.get, and edits with paged.set and the structural authoring functions. Every property write returns a boolean so a script can branch on success.

Reads return JSON strings — parse them. paged.selection(), paged.tree(), paged.stories() and every other read return a JSON string, not a live value. Call JSON.parse(...) before you index into the result. The parsed elements are { kind, id } objects; address one as the string `${kind}:${id}` (e.g. textFrame:u3) when you pass it to paged.set / paged.inspect.

// Reads return JSON strings — parse them.
const [el] = JSON.parse(paged.selection());
if (el) {
  const ref = `${el.kind}:${el.id}`;            // e.g. "textFrame:u3"
  paged.set(ref, "frameFillColor", "Color/Red"); // a real settable path
  paged.set(ref, "frameRotationAngle", 12);      // rotate 12°
}

Try it

Edit the script and press Run — it executes in the real Paged editor on the right, and the canvas updates live. Console output appears below.

A first paged.* script — read the selection, then fill the frame red
Open ↗paged.* · seed: one-text-frame-selected
Loading editor…
Look for: The text frame on the page turns red and rotates 12°.
Console
Run a script to see console output here.

The playground runs against play.paged.media. It needs that app deployed with the editable-script bridge and a cross-origin-isolated (COOP/COEP) page — both are wired here; see constraints for the sandbox model.

What's here

  • Host functionsProIII· referenceevery paged.* function, grouped by kind (read, write, author, history, console).
  • Settable pathsProIII· referencethe property names you can pass to paged.set, plus the id grammar for addressing elements.
  • ConstraintsProIII· referencethe sandbox rules and execution budgets.
  • textFrame:<id> e.g. textFrame:u123 — A text frame. Same scheme: rectangle:/oval:/polygon:/graphicLine:/group:.
  • rectangle:<id> e.g. rectangle:u12 — A rectangle (graphic frame).
  • oval:<id> e.g. oval:u13 — An oval.
  • polygon:<id> e.g. polygon:u14 — A polygon or open path.
  • graphicLine:<id> e.g. graphicLine:u15 — A graphic line.
  • group:<id> e.g. group:u88 — A group. `paged.set("group:<id>", "groupTransform", [a,b,c,d,tx,ty])` moves it as a unit.
  • frame:<id> e.g. frame:u123 — Any page item, kind unknown (alias). paged.address / paged.query resolve it to the kind-specific form.
  • storyRange:<storyId>@<start>..<end> e.g. storyRange:Story/u1@0..6 — A character range within a story (half-open). storyId comes from paged.stories()[].selfId. Alias: story:<storyId>@<start>..<end>.
  • doc e.g. doc — The document itself.
  • page:<id> e.g. page:u1a2 — A body page, by its Self id (paged.pages()[].selfId), or page:#<n> for the n-th page (1-based).
  • spread:<id> e.g. spread:u1a1 — A spread, by its Self id.
  • layer:<id> e.g. layer:ub3 — A layer, by its Self id (paged.layers()).
  • master:<id> e.g. master:ua9 — A master spread. `master:<id> > textFrame:<id>` names an item on it.
  • story:<id> e.g. story:Story/u1 — A story, by its Self id.
  • field:<storyId>@<offset> e.g. field:Story/u1@12 — A text field anchored at a story character offset (paged.placeholders / RequestDocumentPlaceholders).
  • table:<id> e.g. table:u2f — A table, by its Self id (unique per document).
  • cell:<tableId>/<row>,<col> e.g. cell:u2f/0,1 — A table cell, zero-based row and column.
  • style:<family>/<selfId> e.g. style:paragraph/ParagraphStyle/Body — A style; family is paragraph | character | object | cell | table. The display name is accepted in place of the Self id.
  • swatch:<id> e.g. swatch:Color/Red — A colour or swatch, by its Self id.
  • gradient:<id> e.g. gradient:Gradient/u1 — A gradient, by its Self id.
  • colorGroup:<id> e.g. colorGroup:ColorGroup/u7 — A colour group.
  • numberingList:<id> e.g. numberingList:NumberingList/Steps — A numbering list.
  • guide:<id> e.g. guide:u5c — A ruler guide.
  • condition:<id> e.g. condition:Condition/Draft — A text condition.
  • conditionSet:<id> e.g. conditionSet:u3d — A condition set.
  • section:<id> e.g. section:u4e — A numbering section.
  • hyperlink:<id> e.g. hyperlink:u6a — A hyperlink.
  • textVariable:<id> e.g. textVariable:dTextVariablenFile Name — A text variable, by its Self id (the designmap's TextVariable). Its name is accepted in a selector: textVariable[name="Running Head"].
  • plugin:<pluginId>/<kind>/<id> e.g. plugin:paged.image/layer/7 — An object a plugin owns. Opaque to core and carried through unchanged.
  • $h:<name> e.g. $h:newFrame — A batch handle bound earlier in the same batch.

On this page