---
title: "Use document locations in Document Authoring"
canonical_url: "https://www.nutrient.io/guides/document-authoring/working-with-documents/document-locations/"
md_url: "https://www.nutrient.io/guides/document-authoring/working-with-documents/document-locations.md"
last_updated: "2026-09-24T00:00:00.000Z"
description: "Create portable document locations from search results or saved DocJSON. Navigate to text and add temporary visual highlights without changing document content."
---

# Use document locations

Use a document location to connect a search result or external reference to a paragraph or text range. Your application can navigate to that location or highlight it without editing the document.

A [document location](https://www.nutrient.io/api/document-authoring/types/documentlocation/) is a JSON-serializable value. You can create it from saved DocJSON in Node.js. Then use it with the same document model in a browser editor.

This guide covers how to:

- [Find and highlight text](#find-and-highlight-text) without opening the Find bar.

- [Create a location from saved DocJSON](#create-a-location-from-saved-docjson).

- [Handle locations that cannot be displayed](#handle-locations-that-cannot-be-displayed).

## Before you start

Document locations require Nutrient Document Authoring SDK 1.22.0 or later. The browser examples assume `editor` is an initialized editor with a document loaded. For setup, refer to the [getting started](https://www.nutrient.io/sdk/document-authoring/getting-started.md) guide.

For the Node.js example, refer to the [using Node.js](https://www.nutrient.io/sdk/document-authoring/getting-started/using-nodejs.md) guide first.

## Find and highlight text

Call [`editor.find.search()`](https://www.nutrient.io/api/document-authoring/types/findnamespace/#search) to search for literal text without opening or changing the Find bar. Each result contains a `location`.

Pass the location to [`editor.navigateTo()`](https://www.nutrient.io/api/document-authoring/types/docautheditor/#navigateto) to scroll to it without changing the selection or focus. Then call [`editor.addVisualHighlight()`](https://www.nutrient.io/api/document-authoring/types/docautheditor/#addvisualhighlight) to highlight the text range.

```js

async function showFirstMatch(editor, query) {
  try {
    const [match] = await editor.find.search(query);

    if (!match) {
      return null;
    }

    const navigation = await editor.navigateTo(match.location);
    if (!navigation.ok) {
      console.warn('Cannot navigate to the match:', navigation.reason);
      return null;
    }

    const result = await editor.addVisualHighlight(match.location, {
      color: '#fde047',

      opacity: 0.35,
    });
    if (!result.ok) {
      console.warn('Cannot highlight the match:', result.reason);
      return null;
    }

    return result.highlight;
  } catch (error) {
    console.error('Failed to find and highlight text.', error);
    return null;
  }
}

const highlight = await showFirstMatch(editor, 'review');

```

This example highlights the first match for `review`. If no match exists, it returns `null`.

The highlight is temporary: It doesn’t change text formatting and isn’t included in saved or exported documents. Adding it doesn’t scroll, move the selection, or focus the editor.

To remove it, call the returned handle’s [`remove()`](https://www.nutrient.io/api/document-authoring/types/visualhighlight/) method:

```js

highlight?.remove();

```

Removing the same highlight again is a no-op. The SDK also removes visual highlights when the document changes.

To select a search match instead of navigating without selection, call the result’s [`select()`](https://www.nutrient.io/api/document-authoring/types/findresult/) method. Refer to the [Find API reference](https://www.nutrient.io/api/document-authoring/types/findnamespace/) for details.

## Create a location from saved DocJSON

A location contains two required values and an optional range:

- `documentDigest` identifies the persisted document model. The SDK calculates this fingerprint; don’t substitute a saved-file hash.

- `pointer` identifies a paragraph in DocJSON using a JSON Pointer.

- `range`, when present, identifies a non-empty text range within that paragraph. Its `begin` offset is inclusive and its `end` offset is exclusive.

The range uses UTF-16 offsets, like JavaScript strings. A location without a range identifies the paragraph and supports navigation, but not a text highlight.

Use [`createDocumentLocation()`](https://www.nutrient.io/api/document-authoring/functions/createdocumentlocation/) with the saved DocJSON object and the target paragraph. It validates the pointer and range. Then it returns a location.

The following Node.js example creates a document containing `Please review this clause.` and writes the document and location to separate JSON files:

```js

import { writeFile } from 'node:fs/promises';
import {
  createDocAuthSystem,
  createDocumentLocation,
} from '@nutrient-sdk/document-authoring/node';

async function saveReviewLocation() {
  const system = await createDocAuthSystem();

  try {
    const document = await system.createDocumentFromPlaintext(
      'Please review this clause.',
    );
    const savedDocument = await document.saveDocument();
    const location = await createDocumentLocation(savedDocument, {
      pointer: '/container/document/body/elements/0',
      range: { begin: 7, end: 13 },
    });

    await writeFile('document.json', JSON.stringify(savedDocument), 'utf8');
    await writeFile('location.json', JSON.stringify(location), 'utf8');
  } finally {
    system.destroy();
  }
}

try {
  await saveReviewLocation();
} catch (error) {
  console.error('Failed to save the document and location.', error);
  process.exitCode = 1;
}

```

The pointer selects the first body paragraph in this example, and the range selects `review`. For another document, use its actual paragraph pointer and text offsets.

Load `document.json` in the browser as described in the [DocJSON](https://www.nutrient.io/guides/document-authoring/working-with-documents/docjson.md) guide. Parse `location.json` and pass the resulting object to `editor.navigateTo()` or `editor.addVisualHighlight()`.

Create locations from DocJSON saved by the current SDK. If you have older DocJSON, load and save it with the SDK before creating locations.

## Handle locations that cannot be displayed

Navigation and highlighting return a result with `ok: true` on success. Otherwise, check `reason`:

| Reason                 | Meaning                                                                                          | What to do                                                                  |
| ---------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| `document-mismatch`    | The current document model differs from the model used to create the location.                   | Load the matching document or create a new location from the current model. |
| `invalid-location`     | The location has an invalid shape, paragraph pointer, or text range.                             | Recreate it with `createDocumentLocation()` or use a fresh search result.   |
| `unsupported-location` | The editor cannot display the target for this operation. A text highlight also requires a range. | Use a rendered target and a ranged location for highlighting.               |

Creating a location validates the saved data, but it doesn’t guarantee that the editor can display the target. For example, comment text isn’t a navigable editor paragraph.

Check the result each time you navigate or add a highlight. Keep exception handling around asynchronous calls, as shown in the browser example.

## Keep locations with the matching document model

Locations describe a document model, not a bookmark that automatically follows edits. Text, structure, formatting, and resource-reference changes affect the fingerprint. Create a new location after those changes.

Image bytes and image availability don’t affect location identity. Replacing image bytes under the same resource ID leaves a location valid.

Creating and resolving locations never loads image resources. Saving a complete document still needs those resources and can fail if they’re unavailable.

The location fingerprint differs from the canonical saved-file hashes in transaction reports. Refer to the [transaction reports](https://www.nutrient.io/guides/document-authoring/editing-content/transaction-reports.md) guide for those hashes. Don’t compare `documentDigest` with a report’s `beforeDigest` or `afterDigest`.

## Learn more

Refer to these guides for related document and search workflows:

- [DocJSON](https://www.nutrient.io/guides/document-authoring/working-with-documents/docjson.md) — Load and save the document representation used by locations.

- [Find interface](https://www.nutrient.io/guides/document-authoring/customize/find-interface.md) — Open and customize the built-in Find bar.

- [Find and replace](https://www.nutrient.io/guides/document-authoring/editing-content/find-and-replace.md) — Modify text or apply saved formatting inside a transaction.

- [Document Authoring API reference](https://www.nutrient.io/api/document-authoring/)
---

## Related pages

- [First-class JSON support with DocJSON](/guides/document-authoring/working-with-documents/docjson.md)
- [Export documents](/guides/document-authoring/working-with-documents/export.md)
- [Import documents](/guides/document-authoring/working-with-documents/import.md)
- [Document data and formats](/guides/document-authoring/working-with-documents/overview.md)

