This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/web/release-notes/1-15.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. 1.15 release notes

1.15 release notes

RSS

Nutrient Web SDK 1.15 introduces a structured headless annotation API namespace, refines the UI customization slot system, and expands instance.search() with whitespace-tolerant matching for multiline phrases. See the changelog for full details.

Breaking changes

This release includes two breaking changes. Review the impact and restoration steps below before upgrading.

Document loading screen is now the skeleton UI

Pre-1.15 versions showed a hardcoded progress spinner/bar while documents loaded, with no API to configure it. 1.15 introduces the new ui.loader option together with a new skeleton loader — a realistic placeholder of the viewer layout that reduces perceived load time and makes the skeleton the default. Any integration upgrading from 1.14 or earlier will see the skeleton during document load instead of the previous spinner, without changing any code.

Impact: No code change is required for the new behavior, but the loading UI users see during NutrientViewer.load() is visually different. Custom CSS or visual regression tests that asserted against the previous spinner may need updates.

Restoring previous behavior: Pass { type: "progress" } to keep the pre-1.15 spinner:

await NutrientViewer.load({
// ...your existing configuration
ui: { loader: { type: "progress" } },
});

Refer to configurable loader UI for the full set of options, including custom slot callbacks.

UI customization slot callbacks now receive getInstance()

The first argument to every ui.* slot callback changed from a captured instance reference to a getInstance() accessor. Call getInstance() at the point of use — typically inside render or an event handler — to read the latest viewer instance.

Impact: Existing ui.* slot callbacks that used the first argument as a synchronous instance reference will break at runtime once upgraded. Preload slots (ui.loader, ui.passwordPrompt) previously received null here because the viewer hadn’t finished loading; with getInstance(), the same callback can read the live instance from any render call or event handler that fires after NutrientViewer.load() resolves.

Migration: Update each callback to call getInstance() at the point of use.

Before:

NutrientViewer.load({
ui: {
tools: {
main: (instance, id) => ({
render: () => createToolbar(instance),
}),
},
},
});

After:

NutrientViewer.load({
ui: {
tools: {
main: (getInstance, id) => ({
render: () => createToolbar(getInstance()),
}),
},
},
});

The change applies to every ui.* slot, including:

  • Preload slots — ui.loader, ui.passwordPrompt.
  • Postload slots — ui.tools.main, ui.tools.contextual, ui.annotations.*, ui.signatures.*, ui.search, ui.documentEditor, ui.commentThread, ui.sidebar.*.

Headless annotation APIs

This release introduces an annotations.* namespace on instance for working with annotations programmatically, organized by annotation type. Each sub-namespace exposes type-specific operations and shares a common selection, note, and clipboard infrastructure — usable without mounting the full viewer UI:

  • annotations.ink
  • annotations.link
  • annotations.measurement
  • annotations.redaction
  • annotations.shape
  • annotations.textMarkup
  • annotations.text

The shared infrastructure is extensible — additional annotation types can plug into the same primitives. This is the foundation for richer headless and automation workflows. For more information, refer to the headless annotations overview, headless measurement annotations, and headless redaction annotations. Let us know through our support form(opens in a new tab) which patterns you’d like to see expanded next.

Cancelable load and conversion operations

NutrientViewer.load(), convertToPDF(), convertToOffice(), and populateDocumentTemplate() now accept an AbortSignal(opens in a new tab) to cancel in-flight operations. This is useful when users navigate away mid-load or you need to terminate a slow conversion:

const controller = new AbortController();
const instance = await NutrientViewer.load({
// ...your existing configuration
signal: controller.signal,
});
// Later, to cancel:
controller.abort();

For more information, refer to the viewer troubleshooting, Office-to-PDF conversion, PDF-to-Office conversion, and Word template generation guides.

Configurable loader UI

A new ui.loader option controls what users see while a document loads. Three forms are supported:

skeleton (default) — A realistic placeholder of the viewer layout that reduces perceived load time:

await NutrientViewer.load({
// ...your existing configuration
ui: { loader: { type: "skeleton" } },
});

progress — The indeterminate spinner with a determinate progress bar (the pre-1.15 default):

await NutrientViewer.load({
// ...your existing configuration
ui: { loader: { type: "progress" } },
});

Slot callback — Fully replace the loader with custom DOM. Because the loader renders before NutrientViewer.load() resolves, getInstance() may return null inside this slot; use it for loading UI only:

await NutrientViewer.load({
// ...your existing configuration
ui: {
loader: (getInstance, id) => ({
render: () => {
const div = document.createElement("div");
div.innerText = "Loading your document...";
return div;
},
}),
},
});

To hide the loader entirely, return null from render: (getInstance, id) => ({ render: () => null }).

A new opt-in, SearchType.WORD_BASED, makes instance.search() resilient to whitespace inconsistencies in extracted PDF text. The mode strips Unicode space variants (NBSP, em/en/thin spaces, ideographic space, etc.) plus tab/newline/CR from both the query and the document before matching, so multiline phrases that cross tables, columns, or line wraps with stray whitespace match cleanly. Annotation contents are matched with the same algorithm. Punctuation is preserved on both sides, and case-insensitive search (the default) now case-folds non-ASCII letters too — "MÖCHTEN" matches "möchten".

const results = await instance.search("Smith, John", {
searchType: NutrientViewer.SearchType.WORD_BASED,
});

Default instance.search() behavior is unchanged. Additionally, the existing smart-search regex now tolerates a single space immediately before a line break, fixing cases where PDF text extraction inserts a trailing space at line wraps and a clean-newline query failed to match.

SearchType.WORD_BASED is available in Web SDK standalone mode immediately. Server-backed mode requires Document Engine 1.16.x.

For more information, refer to the text search and built-in search UI guides.

Performance, fonts, and stability

  • Dynamic font downloading and font substitution now work for linearized PDF loads, eliminating font-related fallbacks during progressive loading.
  • A new API lets you control the visual rendering order of annotations on a page via a custom comparator function.
  • Document Crop mode now supports keyboard input — arrow keys draw the crop region, Enter confirms, and Escape cancels.
  • The standalone JWT signing service now forwards the flatten flag consistently from prepareSign to the /sign_hash request, producing valid signatures when instance.signDocument() is called with flatten: true.
  • Fixes a regression introduced in 1.14.0 where cross-user updates to non-comment annotations could be rejected by Document Engine with invalid_anonymity_update, blocking collaborative editing of existing annotations.
  • Additional fixes across RTL viewer trackpad scrolling and scrollbar visibility, IME composition in custom stamp text fields, content editor text drag-selection on Windows, ligature text selection, redaction font sizing, Arabic rich-text free text appearance streams, and several content editor and form creator edge cases.

For more information, refer to the font substitution, linearized downloads, crop, and annotation customization guides.

Minimum Document Engine version required: 1.5.6

For more information, refer to the UI customization introduction, supported slots reference, and slot examples guides.

For a complete list of changes, bug fixes, and improvements, refer to the changelog. For previous release notes, refer to the Web SDK 1.14 release notes. We appreciate your feedback and contributions as we continue to enhance Nutrient Web SDK.