Apex DOCX PDF

Apex DOCX PDF

Word or Google Docs.
Deterministic PDFs.

Create templates in Word or Google Docs, export DOCX, bind typed JSON, and produce searchable PDFs in TypeScript—without LibreOffice, Chromium, or a conversion service.

playground · local worker

Choose an example to inspect the template, data, and output together.

Example document

Template

.docx

{{client.legalName}}
{{invoice.total:number | currency:"ZAR"}}

Data

JSON

{
  "client": { "legalName": "Mokoena & Associates" },
  "invoice": { "total": 1480 }
}

Output

1 page · searchable

Invoice

Bill to

Mokoena & Associates

Professional servicesR 1 480.00
DisbursementsR 0.00
Total dueR 1 480.00

Why Apex

A renderer you can put in a CI pipeline.

Layout and PDF generation are owned by the engine—not by an opaque office binary. Determinism is defined by an explicit, documented input tuple.

  • 01

    No office binary

    Interprets a documented OOXML profile directly. Nothing shells out to Word or LibreOffice.

  • 02

    Byte-stable output

    Stable object ordering, fonts, and metadata. Re-render the same inputs and get the same PDF.

  • 03

    One pipeline

    A Bun-first package graph with explicit Uint8Array boundaries for Node.js and browser-worker adapters.

  • 04

    Known limits

    ZIP, XML, expression, image, font, and page ceilings are explicit—and enforced.

Implemented profile

The document features that business templates need.

Phase 7 is implemented and locally verified within the published support matrix. Production deployment remains future work.

  • Template

    Placeholders and schema

    Extract nested typed placeholders into a manifest, Draft 2020-12 JSON Schema, and deterministic starter data.

  • Template

    Loops and conditions

    Nested whole-paragraph conditions, optional else branches, and bounded each loops bind typed data.

  • Tables

    Fixed-layout tables

    Deterministic grids, borders, merges, repeating headers, template rows, and row fragmentation continue across pages.

  • Numbering

    Legal numbering

    Relationship-owned DOCX numbering preserves deterministic multilevel list labels and counters.

  • Typography

    Embedded fonts

    Caller-supplied TrueType programs are shaped and embedded without system-font discovery or network fetches.

  • Browser

    Worker rendering

    The browser adapter compiles and renders in a module worker so document work stays off the UI thread.

  • Pages

    Headers and footers

    Inherited default headers and footers repeat with supported template values and decimal page fields.

  • Inspection

    Source-linked diagnostics

    Warnings and errors carry stable codes and, where available, DOCX source locations and node IDs.

  • Hosting

    Vercel-friendly boundaries

    Browser-worker rendering and direct storage seams avoid buffering document bytes in a server function; deployment is not yet verified.

  • Output

    Searchable PDFs

    Deterministic display lists become searchable PDF bytes with explicit metadata and optional layout traces.

Pipeline

Six stages. No hidden steps.

Every stage emits a typed intermediate. Pagination, fonts, and drawing decisions stay inspectable in tests and traces.

Read the architecture notes
  1. 01

    DOCX

    Validate the package and relationships.

  2. 02

    Parse

    Build a typed semantic document.

  3. 03

    Compile

    Bind placeholders and control flow.

  4. 04

    Resolve

    Apply data with locale context.

  5. 05

    Layout

    Paginate with integer twips.

  6. 06

    PDF

    Emit searchable page content.

API

Compile once. Render many times.

Locale, time zone, fonts, and resource limits are call-site arguments—not ambient environment state.

  1. 01

    once

    createDocxPdfEngine()

    Configure explicit fonts and limits. Runtime adapters pass the same bounded byte-oriented inputs into the engine.

  2. 02

    once / template

    engine.compile()

    Parse and compile the DOCX template into a reusable artifact for high-volume rendering.

  3. 03

    per document

    engine.render()

    Bind typed data with an explicit locale and time zone, then emit a searchable PDF.

usage

bun add @apex-docx-pdf/engine

TypeScript

const engine = await createDocxPdfEngine({
  fonts,
})

const compiled = await engine.compile(docxBytes)

const result = await engine.render(compiled, data, {
  locale: "en-ZA",
  timeZone: "Africa/Johannesburg",
})

// result.pdf — searchable, byte-stable

Packages are private workspaces today. The install command applies after the planned prerelease publication.

Compatibility

A published support matrix.

Features are marked supported only when fixtures, layout traces, and PDF output agree. Unsupported Word content is diagnosed with a source location—not silently omitted.

View support matrix

Open source

Apache-2.0.

Architecture decisions, tests, limitations, and the roadmap are public. Bug reports, focused pull requests, and adversarial redistributable fixtures are welcome.