Skip to content

v0.8.0

Choose a tag to compare

@danmolitor danmolitor released this 30 Mar 03:04
· 649 commits to main since this release

Forme 0.8.0

March 29, 2026 — 55 files changed, ~10,900 lines added across engine, SDKs, and docs.

0.8.0 is the forms, accessibility, and signing release. It adds four new component types for interactive PDF forms, PDF/UA-1 accessibility compliance, PDF/A archival conformance, PKCS#7 digital signatures, a Go SDK, and a published Rust crate. Together these features make Forme suitable for regulated industries — legal, finance, healthcare, government — where fillable forms, accessibility, archival, and cryptographic signatures are requirements, not nice-to-haves.


AcroForms — Interactive Fillable PDFs

Four new components create native PDF form fields that users can fill in any PDF viewer:

Component Description
<TextField> Single-line or multiline text input with optional placeholder, font size, password mode, and read-only
<Checkbox> Checkable box with checkmark appearance
<Dropdown> Select menu with a list of string options
<RadioButton> Grouped radio buttons — multiple buttons sharing a name form a mutually exclusive group
<TextField name="company" placeholder="Acme Corp" width={200} height={28} />
<Checkbox name="agree" checked={false} />
<Dropdown name="country" options={["US", "UK", "DE"]} width={150} height={24} />
<RadioButton name="plan" value="pro" />
<RadioButton name="plan" value="enterprise" checked />

All form fields support readOnly, custom dimensions, font size, and border/background colors. Radio groups enforce mutual exclusivity at the PDF level.

Form flattening converts interactive fields to static content — useful for generating final copies that can't be edited:

const pdf = await renderDocument(<MyForm />, { flattenForms: true });

When flattening, filled values render as black text and empty fields show placeholder text in grey. The /v1/render/:slug?flattenForms=true query parameter enables flattening via the hosted API.

Available in: @formepdf/react, @formepdf/core, Python SDK, Go SDK.


Digital Signatures — PKCS#7 with X.509 Certificates

Sign PDFs at render time or sign existing PDFs after the fact. Signatures are PKCS#7 detached (SHA-256 + RSA PKCS#1 v1.5), compatible with Adobe Acrobat, Preview, and all major PDF validators.

Render-time signing:

<Document
  signature={{
    certificatePem: readFileSync('./cert.pem', 'utf-8'),
    privateKeyPem: readFileSync('./key.pem', 'utf-8'),
    reason: 'Approved',
    location: 'San Francisco, CA',
    contact: 'legal@acme.com',
  }}
>

Post-render signing via POST /v1/sign — sign any PDF, not just ones rendered by Forme.

Visible signatures — set visible: true with x, y, width, height to render the signer's Common Name, date, and reason on the page.

Double-signing is supported — each signature gets a unique field name (Signature1, Signature2, ...) and existing AcroForm metadata (/NeedAppearances, /DA) is preserved across incremental updates.

Limitations: RSA keys only, leaf certificate only (no intermediate chain), no TSA timestamps, no LTV/CRL/OCSP embedding. See docs.formepdf.com/digital-signatures for full details.


PDF/UA-1 Accessibility

<Document pdfUa> produces PDFs that conform to PDF/UA-1 (ISO 14289-1):

  • Structure tree — every layout element is tagged with a semantic role (P, Span, Table, TR, TH, TD, Figure, Form, Div)
  • Tab order — /Tabs /S on every page for logical keyboard navigation
  • Role map — comprehensive mapping of all 45+ PDF 1.7 standard structure roles
  • Document language — <Document lang="en-US"> propagates to both Catalog /Lang and StructTreeRoot /Lang
  • Alt text — <Image alt="..."> and <Svg alt="..."> flow to /Alt entries in structure elements
  • Artifact tagging — watermarks, fixed headers/footers, and decorative content are marked as /Artifact so screen readers skip them
  • Form field tagging — form components are tagged with the /Form role (required by PDF/UA for interactive fields)
  • XMP metadata — pdfuaid:part=1 in the document metadata stream
  • ViewerPreferences — /DisplayDocTitle true for accessible title display

PDF/A Archival Compliance

<Document pdfa="2b"> produces PDFs that conform to PDF/A (ISO 19005) for long-term preservation:

Level Description
2b Visual reproduction guarantee
2a Visual + full structure tree tagging (equivalent to combining pdfa="2b" with pdfUa)
<Document pdfa="2b">  {/* archival, visual guarantee */}
<Document pdfa="2a">  {/* archival + full tagging */}

PDF/A mode enforces full font embedding, embeds an sRGB output intent ICC profile, includes XMP metadata with pdfaid:part and pdfaid:conformance, and prohibits encryption.


Go SDK

New first-party Go client — zero third-party dependencies, stdlib only:

import forme "github.com/formepdf/forme-go"
 
client := forme.New("forme_sk_...")
pdf, _ := client.Render("invoice", map[string]any{"customer": "Acme"})

Methods: Render, RenderWithOptions, RenderS3, RenderAsync, GetJob, Merge, Extract, Sign. Functional options pattern (WithBaseURL, WithHTTPClient). Structured errors via *FormeError with status code and message. Native template DSL in templates sub-package. 98 tests (26 client + 72 templates).

go get github.com/formepdf/forme-go@v0.8.0

Rust Crate on crates.io

The engine is now published as forme-pdf:

cargo add forme-pdf
let pdf_bytes = forme_pdf::render(&document_json)?;

Exports: render(), render_json(), render_with_layout(), render_template().


Bug Fixes

  • Checkbox appearance — Checked checkboxes now render a checkmark instead of an X, in both interactive and flattened modes. Radio buttons use a filled circle.
  • DER length parsing — extract_cn_from_cert_der() now correctly handles multi-byte DER lengths (CN strings > 127 bytes). Previously returned "Unknown".
  • Document identity check — serialize() now uses __formeType: 'Document' marker instead of React component reference equality, fixing Top-level element must be <Document> errors when multiple package versions are installed.
  • Placeholder rendering — flattenForms: true now renders placeholder text in grey when a field has no value, instead of leaving the field blank.
  • AcroForm metadata preservation — Signing a PDF that already contains form fields now preserves /NeedAppearances and /DA from the original AcroForm dictionary.

Breaking Changes

  • SignatureConfig.page removed — This field was accepted but silently ignored (signatures always land on the first page). Removed from both Rust and TypeScript types. Remove it from any existing signature configs.
  • Signature prop names corrected — certificatePem and privateKeyPem are the correct field names. contact replaces contactInfo. Visible signatures use flat props (visible, x, y, width, height) — there is no nested appearance object.

Stats

  • 55 files changed across engine, React, Go SDK, Python SDK, and docs
  • ~10,900 lines added
  • 411 engine tests (235 integration + 176 unit), all passing
  • 98 Go SDK tests (26 client + 72 templates), all passing

Upgrading

npm install @formepdf/react@0.8.0 @formepdf/core@0.8.0
 
# Go SDK
go get github.com/formepdf/forme-go@v0.8.0
 
# Rust crate
cargo add forme-pdf@0.8.0

No migration required for existing documents. The only breaking change is the removal of the unused page field from SignatureConfig and the correction of signature prop names — both only affect users who integrated digital signatures in a pre-release build.