v0.5.0 · Apache 2.0 · TypeScript + JavaScript

Generate, fill, and read OpenDocument
files with odf-kit

Create .odt documents from scratch, fill existing templates with data, or convert .odt files to HTML — all in pure JavaScript. Build reports, invoices, letters, and contracts with tables, formatting, images, loops, and conditionals — in Node.js or directly in the browser.

$ npm install odf-kit

Who generates ODF documents from code?

Any application — server-side or in the browser — that needs to create formatted documents as files. Not PDFs, not proprietary formats — the open standard that LibreOffice, governments, and schools actually use.

Government & Public Sector

Compliance document generation

Many governments mandate OpenDocument Format (ODF) per ISO/IEC 26300. Generate permits, notices, tax documents, and citizen correspondence in the required open standard format.

SaaS & Web Apps

Report and invoice export

Add "Export as .odt" to your web application. Generate invoices and reports server-side, or directly in the browser — user data never leaves the page. Files open in LibreOffice or Word.

Nonprofits & Education

Template-driven mail merge

Design templates in LibreOffice with {placeholders}, then fill them with data from your database. Generate grant reports, donor letters, transcripts, and certificates at scale.

Legal & HR

Contract and document assembly

Fill contract templates with client data, loop over line items, conditionally include clauses. Produce vendor-independent files in the ISO document standard.

DevOps & CI/CD

Build pipeline document generation

Generate changelogs, release notes, test reports, and documentation as .odt files in your build pipeline. No desktop software required — odf-kit runs in Node.js, browsers, Deno, and Bun.

Civic Tech

Community organization tools

Build tools for food banks, legal aid, refugee services, and community groups. Generate case files, intake forms, and service records in a format that works with free office software.

Three ways to work with .odt files

Build documents from scratch, fill existing templates, or read and convert existing .odt files to HTML — all in pure JavaScript.

import { OdtDocument } from "odf-kit";

const doc = new OdtDocument();
doc.setMetadata({ title: "Quarterly Report" });
doc.setFooter("Page ###");

doc.addHeading("Q4 Results", 1);
doc.addParagraph("Revenue exceeded expectations across all regions.");

doc.addTable([
  ["Region",  "Revenue",   "Growth"],
  ["North",   "$2.1M",     "+12%"],
  ["South",   "$1.8M",     "+8%"],
], { border: "0.5pt solid #000" });

doc.addParagraph((p) => {
  p.addText("Status: ");
  p.addText("Approved", { bold: true, color: "green" });
});

const bytes = await doc.save();
// → Uint8Array — valid .odt, opens in LibreOffice
import { fillTemplate } from "odf-kit";
import { readFileSync, writeFileSync } from "fs";

// Load a .odt template created in LibreOffice
const template = readFileSync("invoice-template.odt");

const result = fillTemplate(template, {
  customer: "Acme Corp",
  date: "2026-02-23",

  // Loops — repeats content for each item
  items: [
    { product: "Widget", qty: 5, price: "$125" },
    { product: "Gadget", qty: 3, price: "$120" },
  ],

  // Conditionals — include or remove sections
  showNotes: true,
  notes: "Net 30",

  // Dot notation — nested data access
  company: { name: "Acme Corp", address: "123 Main St" },
});

writeFileSync("invoice.odt", result);
// → Valid .odt with all {placeholders} replaced
import { readOdt, odtToHtml } from "odf-kit/reader";
import { readFileSync } from "node:fs";

const bytes = new Uint8Array(readFileSync("document.odt"));

// Convert to HTML in one call
const html = odtToHtml(bytes, { fragment: true });

// Or parse to a structured document model
const doc = readOdt(bytes);
console.log(doc.metadata.title);    // title from meta.xml
console.log(doc.body.length);        // paragraphs, headings, tables...

// Walk the document model
for (const node of doc.body) {
  if (node.kind === "heading") console.log(`h${node.level}:`, node.spans[0].text);
  if (node.kind === "paragraph") console.log(node.spans.map(s => s.text).join(""));
}

Everything you need to generate .odt files

Built from the ground up for the ODF 1.2+ specification. Every feature validated against LibreOffice 24.2. Works in Node.js and modern browsers.

📋

Template Engine

Fill existing .odt templates with {placeholders}. Loops for repeating content, conditionals for optional sections, dot notation for nested data.

✏️

Text Formatting

Bold, italic, underline, strikethrough, superscript, subscript. Custom fonts, sizes, colors, and highlights.

📊

Tables

Column widths, cell borders, backgrounds, merged cells (colspan & rowspan). Formatted text inside cells.

📄

Page Layout

Page size, margins, orientation. Headers and footers with page numbers. Page breaks.

📝

Lists

Bullet and numbered lists with up to 6 levels of nesting. Formatted items via builder callback.

🖼️

Images

Embedded PNG, JPEG, GIF, SVG, WebP, BMP, TIFF. Standalone or inline. Sized and anchored.

🔗

Hyperlinks & Bookmarks

External hyperlinks, internal bookmark links. Formatted link text. Named anchor points.

📖

Read & Convert to HTML

Parse existing .odt files into a structured document model. Convert to HTML with odtToHtml(). Paragraphs, headings, tables, lists, formatting, hyperlinks. Pure JavaScript, no LibreOffice needed.

Zero Transitive Dependencies

Single runtime dependency (fflate). No XML parsers, no heavy frameworks. Lightweight and audit-friendly.

🌐

Node.js & Browser

Same API everywhere. Generate documents server-side in Node.js or client-side in the browser. Also works in Deno, Bun, and Cloudflare Workers.

The JavaScript ODF library that was missing

The JS/TS ecosystem had no maintained, full-featured library for OpenDocument Format generation. odf-kit fills that gap.

Three modes, one library, every platform

Build documents from scratch, fill existing .odt templates with data, or read and convert .odt files to HTML. Same API in Node.js and browsers — no LibreOffice, no server dependencies required.

Zero transitive dependencies

Only fflate at runtime — zero transitive dependencies. Lightweight and audit-friendly for enterprise and government projects.

ODF 1.2+ and ISO/IEC 26300

Generates proper ZIP-packaged .odt files per the ODF international standard. Opens in LibreOffice, Google Docs, and any compliant application.

Open standards, open source

ODF is the ISO standard used by the EU, governments, schools, and nonprofits worldwide. odf-kit is Apache 2.0 — use it anywhere, commercial or not.

Developer-friendly API

Simple things are one-liners. Complex output uses builder callbacks. Both bold: true and fontWeight: "bold" work. Flexible and forgiving.

Replaces simple-odf

The only prior JS library (simple-odf) was abandoned in 2021. It had no table support and only generated flat XML. odf-kit produces proper .odt files with full formatting.

odf-kit vs. simple-odf

If you've been searching for a simple-odf alternative or replacement, here's what odf-kit does differently.

Feature odf-kit simple-odf
Maintained Active (2026) Abandoned (2021)
Output format Proper .odt ZIP packages Flat XML only (.fodt)
Template engine Loops, conditionals, dot notation Not supported
Tables Full support with merging Not supported
Images Embedded in ZIP Not supported
Lists Bullet & numbered, nested Partial
Page layout Margins, headers, footers Not supported
Hyperlinks & bookmarks External and internal Partial
TypeScript Written in TypeScript Written in TypeScript
Browser support Node.js and browsers Node.js only
313
Tests passing
0
Transitive dependencies
7
Development phases
0
External XML parsers

Common questions

How do I generate an ODF document in JavaScript or Node.js?

Install odf-kit with npm install odf-kit, then use the OdtDocument class to build documents from scratch, or use fillTemplate() to fill existing .odt templates with data. Works in Node.js and browsers. Call save() to get a Uint8Array, then write it to disk or trigger a browser download. See the step-by-step guide.

Can I fill an existing .odt template with data?

Yes. Create a template in LibreOffice with {placeholders} in the text, then use fillTemplate(templateBytes, data). It supports simple replacement, loops for repeating content ({#items}...{/items}), conditionals for optional sections, and dot notation for nested objects ({company.name}). The engine automatically handles LibreOffice's XML fragmentation of placeholder text. See the template guide for a full walkthrough.

Is odf-kit a replacement for simple-odf?

Yes. simple-odf was abandoned in 2021 and only produced flat XML files (.fodt), not proper .odt ZIP packages. It had no support for tables, images, page layout, templates, or bookmarks. odf-kit is a modern, actively maintained alternative that generates compliant .odt files with comprehensive formatting support. See the migration guide for a side-by-side comparison.

Does odf-kit work for government ODF compliance requirements?

odf-kit generates ODF 1.2+ documents per ISO/IEC 26300, the international standard mandated by the European Union, many national governments, and public sector organizations. The output opens in LibreOffice and any ODF-compliant application. See the government compliance guide for a full list of mandates and implementation details.

Can I use odf-kit to create LibreOffice documents from my web application?

Yes. odf-kit works both server-side in Node.js and client-side in the browser. You can generate .odt files on your backend and serve them as downloads, or generate them entirely in the browser — user data never leaves the page. The files open natively in LibreOffice Writer, and also work in Google Docs, Microsoft Word, and other applications that support ODF. See the browser generation guide for a complete walkthrough.

Can I read or convert an existing .odt file to HTML?

Yes. Import readOdt() or odtToHtml() from odf-kit/reader to parse existing .odt files. readOdt() returns a structured document model with metadata, paragraphs, headings, tables, lists, and text formatting. odtToHtml() converts directly to HTML. Works in Node.js and browsers with zero dependencies — no LibreOffice required. See the ODT ecosystem guide for a full comparison of parsing options.

What's the difference between .odt and .docx?

.odt is the OpenDocument Format — an ISO international standard (ISO/IEC 26300) that's vendor-independent and open. .docx is Microsoft's Office Open XML format. ODF is required by many governments and organizations that need vendor independence. odf-kit generates .odt files; if you need .docx, look at the docx package.

Where can I find step-by-step tutorials?

We have detailed guides for common tasks:

Start generating ODF documents

Install odf-kit and create your first .odt file in under a minute. Works in Node.js and browsers. Build from scratch, fill templates, or read existing .odt files.

$ npm install odf-kit