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.
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.
Many governments mandate OpenDocument Format (ODF) per ISO/IEC 26300. Generate permits, notices, tax documents, and citizen correspondence in the required open standard format.
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.
Design templates in LibreOffice with {placeholders}, then fill them with data from your database. Generate grant reports, donor letters, transcripts, and certificates at scale.
Fill contract templates with client data, loop over line items, conditionally include clauses. Produce vendor-independent files in the ISO document standard.
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.
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.
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("")); }
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.
Fill existing .odt templates with {placeholders}. Loops for repeating content, conditionals for optional sections, dot notation for nested data.
Bold, italic, underline, strikethrough, superscript, subscript. Custom fonts, sizes, colors, and highlights.
Column widths, cell borders, backgrounds, merged cells (colspan & rowspan). Formatted text inside cells.
Page size, margins, orientation. Headers and footers with page numbers. Page breaks.
Bullet and numbered lists with up to 6 levels of nesting. Formatted items via builder callback.
Embedded PNG, JPEG, GIF, SVG, WebP, BMP, TIFF. Standalone or inline. Sized and anchored.
External hyperlinks, internal bookmark links. Formatted link text. Named anchor points.
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.
Single runtime dependency (fflate). No XML parsers, no heavy frameworks. Lightweight and audit-friendly.
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 JS/TS ecosystem had no maintained, full-featured library for OpenDocument Format generation. odf-kit fills that gap.
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.
Only fflate at runtime — zero transitive dependencies. Lightweight and audit-friendly for enterprise and government projects.
Generates proper ZIP-packaged .odt files per the ODF international standard. Opens in LibreOffice, Google Docs, and any compliant application.
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.
Simple things are one-liners. Complex output uses builder callbacks. Both bold: true and fontWeight: "bold" work. Flexible and forgiving.
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.
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 |
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.
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.
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.
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.
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.
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.
.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.
We have detailed guides for common tasks:
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.