Skip to main content
The Document API places elements directly on a page. You create a Document, build elements with the page factories, add them to the page or to a container, and call build. Elements flow top to bottom by default, or sit at exact coordinates when given a position.
import { Document } from "@nemu-ai/pdf";

const pdf = new Document({ page_size: "A4", margin: 50 });
const page = pdf.create_page();

page.add(
  page.text({ content: "Invoice", style: { font_size: 28, font_weight: "bold" } }),
  page.text({ content: "Thank you for your business.", style: { color: "#6b7280" } }),
);

await pdf.build("invoice.pdf");
Page factories like page.text build an element but do not place it. Add what you build with page.add or a container’s add, or it will not render.

The Document class

Construct a Document with an optional DocumentOptions object.
new Document(options?: DocumentOptions)

interface DocumentOptions {
  page_size?: "A4" | "Letter" | "Legal" | "Custom";
  custom_dimensions?: { width: number; height: number };
  margin?: number | MarginValues;
  parse_markdown?: boolean;
}
page_size
"A4" | "Letter" | "Legal" | "Custom"
The page format. Use "Custom" together with custom_dimensions for any other size.
custom_dimensions
{ width: number; height: number }
Width and height in points, used when you need a size outside the named formats.
margin
number | MarginValues
A single number for all sides, or per side values.
parse_markdown
boolean
Enables markdown parsing on text content. Individual text elements can override this.

Document methods

pdf.create_page(theme?: Theme): Page
pdf.add_page(): Page
pdf.set_theme(theme: Theme): void
pdf.load_font_sync(name: string, file_path: string, variable?: boolean): void
pdf.load_image_sync(name: string, file_path: string): void
await pdf.build(file_path: string): Promise<void>
create_page returns a fresh page and optionally applies a theme to it. add_page appends another page to the document. set_theme applies a theme document wide. load_font_sync registers a font by name, with variable: true to enable weight instancing for a custom variable font. load_image_sync registers an image by name so it can be referenced from page.image.

The build pipeline

build runs the engine in three passes. Measure computes each element’s intrinsic size from font metrics. Layout assigns positions from the page margin and header zone. Render draws every element in z index order.
await pdf.build(file_path: string): Promise<void>
await pdf.prepare_pdf(): Promise<any>
await pdf.render_to(file_path: string): Promise<void>
build is prepare_pdf followed by render_to. The split exists so a caller can measure before rendering, which is how the Doc API paginates.

Page factories

The page builds elements but does not place them. Add what you build with page.add or a container’s add.
page.text(options: CreateTextOptions): TextElement
page.rect(options: CreateRectOptions): RectElement
page.image(options: CreateImageOptions): ImageElement
page.table(options: CreateTableOptions): TableElement
page.create_container(options?: CreateContainerOptions): ContainerElement
page.header_container(options?: CreateContainerOptions): HeaderContainer
page.footer_container(options?: CreateContainerOptions): FooterContainer
page.add(...elements: BaseElement[]): this
header_container and footer_container are idempotent. Calling either again returns the existing zone rather than creating a new one.
The page also exposes get_content_width() and get_content_height(), which give the usable area inside the margins. They are handy for sizing full width containers and tables.

A complete example

import { Document } from "@nemu-ai/pdf";

const pdf = new Document({ page_size: "A4", margin: 50 });
const page = pdf.create_page();

const card = page.rect({
  width: page.get_content_width(),
  height: 120,
  shape_style: { fill_color: "#1a365d", border_radius: 10 },
});

page.add(
  page.text({ content: "Invoice", style: { font_size: 28, font_weight: "bold" } }),
  page.text({ content: "Thank you for your business.", style: { color: "#6b7280" } }),
  card,
);

await pdf.build("invoice.pdf");

Next steps

Elements

Text, rectangles, images, overlay children, and z index ordering.

Layout

Group children with flow and flex containers.

Themes

Centralize named colors and apply defaults by element type.

Tables

Build rows and columns with the low level table factory.