Takumi

Links, outline & metadata

Add clickable PDF links, a table of contents, heading bookmarks, and document metadata.

Add links with <a href>, bookmarks with outline, and document properties with metadata.

An <a> with an href becomes a clickable link on every page its box touches:

Link to a website
import {  } from "takumi-pdf";

const  = await (
  <>
    Pay online at < ="https://example.com/pay/1042">example.com/pay/1042</>.
  </>,
);

An inline link is clickable on each line it wraps across. A block-level link covers its whole box.

http, https, mailto, and tel links open outside the document. An href that starts with # jumps to the element with that id:

Link within the document
import {  } from "takumi-pdf";

const  = await (
  <>
    < ="#appendix">Jump to the appendix</>
    < ="appendix">Appendix</>
  </>,
);

A link to a missing id or with another URL scheme gets no annotation.

Table of contents

<TargetPageNumber /> prints the page number of an internal link's target. Put it inside an <a href="#id">, or pass href so it renders its own link. In HTML input, put an element with the targetPageNumber class inside the link.

Build a table of contents
import {  } from "takumi-pdf";
import {  } from "takumi-pdf/primitives";

const  = await (
  <>
    < ="#results" ="flex items-baseline gap-2">
      <>Results</>
      < ="flex-1 border-b border-dotted border-gray-400" />
      < ="w-8 shrink-0 text-right" />
    </>
    < ="results" ={{ : "page" }}>
      Results
    </>
  </>,
);

The stretched span draws the dot leader. format takes any counter style, so format="upper-roman" prints IV for page 4.

A fragment that names no element prints nothing, the same rule links follow.

Reserve space for page numbers

A page number exists only after pagination. Takumi paginates, fills the numbers in, and lays the document out again. A number that widens its line can move a page break, and the moved break can renumber the entry. The render repeats this up to three times, then keeps the last result.

The example reserves width with w-8 shrink-0 text-right, so a number cannot change the entry's width. Widen it if your document needs more digits.

Headers and footers are laid out per page, outside this loop. A <TargetPageNumber /> in a band renders nothing.

Outline

Set outline: true to build PDF bookmarks from h1–h6. A deeper heading nests under the shallower heading before it. tagged: "ua1" and "ua2" turn the outline on, since PDF/UA requires one:

Generate PDF bookmarks
import {  } from "takumi-pdf";

const  = await (, { : true });

Clicking a bookmark jumps to the page and position of its heading.

Document metadata

metadata fills the PDF document properties. lang also sets the document language:

Set document metadata
import {  } from "takumi-pdf";

const  = await (, {
  : "en",
  : {
    : "Annual report 2026",
    : "Consolidated results for fiscal year 2026",
    : ["Acme Inc."],
    : ["annual report", "2026"],
    : "acme-reporting",
  },
});
FieldWritten as
titleDocument title
descriptionSubject
authorsAuthor
keywordsKeywords
creatorCreator: the tool that made the source
creationDateCreation date, UTC YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS
xmpCustom XMP schemas, such as Factur-X's fx: block

Every field is optional for plain PDF output. PDF/A and PDF/UA require some of them. Set a fixed creationDate for reproducible output.

Last updated on