---
title: Configuration
description: Choose what the viewer offers with a mode, fine-tune it with features, shape the interface with ui options and hide single commands with disabledElements.
url: https://free-pdf-sdk.web.app/docs/configuration/
---

# Configuration

Free PDF SDK shows your users only what you allow. You describe that with four options, each
one more specific than the last:

1. **`mode`**: a preset that says what the viewer is for (`view`, `review`, `annotate`, `fill`,
   `sign`, `organize`, `edit` or `full`). The default is `view`, which is read-only.
2. **`features`**: switches that turn individual features on or off on top of the mode.
3. **`ui`**: which parts of the interface are shown (the Tools panel, the rails, the menu,
   right-hand panels).
4. **`disabledElements`**: single commands or tools to hide, such as one markup tool.

```ts
import { FreePdf } from "free-pdf-sdk";

const viewer = await FreePdf.init(document.getElementById("viewer")!, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/contract.pdf" },
  mode: "annotate",                              // 1. what the viewer is for
  features: { stamps: false, measurement: false }, // 2. adjust the preset
  ui: { quickToolbar: false, panels: { layers: false } }, // 3. interface
  disabledElements: ["tool:squiggly"],           // 4. single commands
});
```

Start with the mode closest to what you need, then adjust it with `features`. Reach for `ui`
when the features are right but the layout isn't, and for `disabledElements` only when you need
to remove one command while keeping the rest of its feature.

## What "hidden" means

A feature that is off is hidden **everywhere** in the viewer: menus, toolbars, the Tools panel,
right-hand panels, context menus and keyboard shortcuts. If an action is reached anyway, the
viewer refuses it. You don't need CSS or extra code to make a feature disappear.

When no feature that changes the document is on, the viewer is **read-only**: nothing can
change the document, and `getConfig()` reports `readOnly: true`. That is the case for `view`,
and for any other configuration where you turn every editing feature off.

## Modes

| Mode | What it is for | Features on |
|---|---|---|
| `view` | Read-only viewing: navigation, search, copy, print. Nothing can change the document. | `copy`, `documentInfo`, `help`, `palette`, `preferences`, `print`, `search`, `signaturePanel` |
| `review` | Notes, text boxes and text markup with replies and review status. Nothing else changes. | `comments`, `copy`, `documentInfo`, `help`, `history`, `markup`, `palette`, `preferences`, `print`, `save`, `search`, `signaturePanel` |
| `annotate` | Every kind of annotation: comments, markup, shapes, ink, stamps, measurement and Fill & Sign. No other edits. | `comments`, `copy`, `documentInfo`, `fillSign`, `help`, `history`, `ink`, `markup`, `measurement`, `palette`, `preferences`, `print`, `save`, `search`, `shapes`, `signaturePanel`, `stamps` |
| `fill` | Filling in forms and Fill & Sign. No comments, page or content changes. | `copy`, `documentInfo`, `fillSign`, `formFill`, `help`, `history`, `palette`, `preferences`, `print`, `save`, `search`, `signaturePanel` |
| `sign` | Form filling, Fill & Sign and digital signatures. | `copy`, `digitalSignatures`, `documentInfo`, `fillSign`, `formFill`, `help`, `history`, `palette`, `preferences`, `print`, `save`, `search`, `signaturePanel` |
| `organize` | Page organization and bookmarks, extracting and splitting pages, and export to other formats (Word, PowerPoint, images, HTML, text). No content or comment changes. | `bookmarks`, `copy`, `documentInfo`, `export`, `help`, `history`, `pages`, `palette`, `preferences`, `print`, `save`, `search`, `signaturePanel` |
| `edit` | Full authoring: annotations, forms, pages, content and accessibility. No security, redaction, digital signatures or JavaScript. | `accessibility`, `bookmarks`, `comments`, `copy`, `documentInfo`, `download`, `editContent`, `export`, `fillSign`, `flatten`, `formDesign`, `formFill`, `help`, `history`, `ink`, `markup`, `measurement`, `pages`, `palette`, `preferences`, `print`, `save`, `search`, `shapes`, `signaturePanel`, `stamps`, `standards` |
| `full` | Everything the viewer offers, except JavaScript (turn it on with features.javascript). | `accessibility`, `bookmarks`, `comments`, `copy`, `digitalSignatures`, `documentInfo`, `download`, `editContent`, `export`, `fillSign`, `flatten`, `formDesign`, `formFill`, `help`, `history`, `ink`, `markup`, `measurement`, `pages`, `palette`, `preferences`, `print`, `redaction`, `save`, `search`, `security`, `shapes`, `signaturePanel`, `stamps`, `standards` |

### Choose a mode

| You want users to... | Mode |
|---|---|
| Read, search and print, nothing else | `view` |
| Leave review comments: notes, text boxes, highlights | `review` |
| Mark up the document with any kind of annotation, including Fill & Sign, without changing anything else | `annotate` |
| Fill in a form | `fill` |
| Fill in a form and sign it with a digital ID | `sign` |
| Rearrange, insert, delete or rotate pages and edit bookmarks | `organize` |
| Author documents: content, forms, pages, accessibility | `edit` |
| Use everything the viewer offers | `full` |

Every mode includes the viewing basics: search, copy, print, document properties, help, the
command palette, preferences and the signature panel. Every mode except `view` also includes
undo/redo (`history`) and the viewer's own Save button (`save`).

`full` leaves `javascript` off. Turn it on explicitly if your documents need it:
`features: { javascript: true }`.

## Features

**Annotation**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `comments` | Sticky notes, text boxes, callouts, file attachments, replies, review status, the comment list and comment import/export. | yes | `review`, `annotate`, `edit`, `full` |
| `markup` | Highlight, underline, strikethrough, squiggly underline, insert (caret) and replace text. | yes | `review`, `annotate`, `edit`, `full` |
| `shapes` | Rectangles, ovals, lines, arrows, polygons, polylines and clouds. | yes | `annotate`, `edit`, `full` |
| `ink` | Freehand drawing and the eraser. | yes | `annotate`, `edit`, `full` |
| `stamps` | Standard and custom stamps. | yes | `annotate`, `edit`, `full` |
| `measurement` | Distance, perimeter and area measurements with a drawing scale. | yes | `annotate`, `edit`, `full` |

**Forms & signing**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `fillSign` | Typed text, checkmarks, crosses, dots, lines, dates, and drawn or typed signatures and initials placed on the page. | yes | `annotate`, `fill`, `sign`, `edit`, `full` |
| `formFill` | Filling in form fields, clearing a form, importing and exporting form data. | yes | `fill`, `sign`, `edit`, `full` |
| `formDesign` | Adding, editing and deleting form fields, tab order and field detection. | yes | `edit`, `full` |
| `digitalSignatures` | Signing and certifying with a digital ID (certificate). | yes | `sign`, `full` |
| `signaturePanel` | The signatures panel: viewing and validating existing digital signatures. | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |

**Pages & content**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `pages` | Insert, delete, rotate, move, duplicate, crop, replace and number pages. | yes | `organize`, `edit`, `full` |
| `bookmarks` | Adding, renaming, moving and deleting bookmarks (viewing them is always on). | yes | `organize`, `edit`, `full` |
| `editContent` | Editing text and images, links, headers and footers, watermarks, backgrounds, Bates numbers and document properties. | yes | `edit`, `full` |
| `flatten` | Flattening comments and form fields into the page content. | yes | `edit`, `full` |
| `redaction` | Marking and applying redactions, sanitizing and removing hidden information. | yes | `full` |
| `accessibility` | Accessibility checking, tags, reading order and alternate text. | yes | `edit`, `full` |
| `standards` | Converting to PDF/A. | yes | `edit`, `full` |
| `javascript` | Running the document's JavaScript, the console and editing scripts. Off unless you turn it on. | yes | none (opt in) |

**Security**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `security` | Adding or removing passwords and permissions. | yes | `full` |

**Editing**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `history` | Undo and redo of the changes the other features allow. | no | `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |

**Output**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `save` | The viewer's own Save button; the PDF goes to your page in the saveRequested event. | no | `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |
| `download` | Save As, saving optimized copies, attachments and reports from the viewer. | no | `edit`, `full` |
| `export` | Exporting to Word, PowerPoint, images, HTML and text; extracting and splitting pages. | no | `organize`, `edit`, `full` |
| `print` | Printing. | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |

**Viewing**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `search` | Finding text in the document. | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |
| `copy` | Copying text and images (when the document allows it). | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |
| `documentInfo` | The document properties dialog (read-only unless content editing is on) and word count. | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |

**Interface**

| Feature | What it controls | Changes the document | In modes |
|---|---|---|---|
| `help` | Keyboard shortcuts and About. | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |
| `palette` | The "Find tools and commands" box and palette (Ctrl/Cmd+K). | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |
| `preferences` | The preferences dialog, theme switching and rearranging panels. | no | `view`, `review`, `annotate`, `fill`, `sign`, `organize`, `edit`, `full` |

### Annotation

`comments`, `markup`, `shapes`, `ink`, `stamps` and `measurement` are the annotation tools.
`comments` also covers replies, review status and the comment list. Annotations are stored in
the PDF and travel as XFDF (see [Annotations and XFDF](/docs/annotations-and-xfdf/)).

### Forms & signing

`fillSign` places typed text, marks and drawn or typed signatures on the page (it works on any
PDF, not only forms). `formFill` fills real form fields, `formDesign` creates and edits them.
`digitalSignatures` signs with a certificate; `signaturePanel` only shows and validates
existing signatures and does not change the document.

### Pages & content

`pages` and `bookmarks` organize the document; `editContent` edits its text and images, links,
headers and footers, watermarks and properties. `flatten`, `redaction`,
`accessibility` and `standards` are specialised tools. `javascript` runs the document's own
scripts and is off in every mode.

### Security

`security` adds or removes passwords and permissions. It is only in `full`.

### Editing

`history` is undo and redo. It does not allow any change by itself: it undoes and redoes the
changes the other features allow.

### Output

`save` is the viewer's own Save button: the saved PDF goes to your page in the
`saveRequested` event, and the viewer never stores it anywhere. `download` (Save As and
copies), `export` (other formats, page extraction) and `print` control the other ways a
document leaves the viewer. `viewer.save()` from your code always works, whatever these
switches say.

### Viewing and Interface

`search`, `copy` and `documentInfo` are viewing aids; `help`, `palette` and `preferences` are
parts of the viewer's own interface. None of them changes the document.

## Recipes

### Annotations only, no other edits

`annotate` gives every kind of annotation and Fill & Sign, with undo/redo and Save, and nothing
that changes pages, content, forms or security:

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/artwork.pdf" },
  mode: "annotate",
  author: "Priya Raman",
});
```

To also remove stamps and measurement (and, if you like, Fill & Sign), switch them off:

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/artwork.pdf" },
  mode: "annotate",
  features: { stamps: false, measurement: false, fillSign: false },
});
```

The tools disappear from the Tools panel, the floating tool bar, the menus and the shortcuts.

### Review comments only

Notes, text boxes, callouts and text markup with replies and review status:

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/draft.pdf" },
  mode: "review",
  author: currentUser.name,
});
```

For sticky notes and replies without highlighting, add `features: { markup: false }`.

### Read-only, with print and download disabled

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/confidential.pdf" },
  mode: "view",
  features: { print: false, download: false, export: false, copy: false },
});
```

`download` and `export` are already off in `view`; naming them keeps them off if you later
switch mode, because overrides survive `setMode`. Remember that the viewer runs in the
user's browser: hiding these commands controls the viewer, it is not a way to keep a file from
someone who already has it.

### Forms only

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/forms/application.pdf" },
  mode: "fill",
  features: { fillSign: false },
});

viewer.on("saveRequested", async ({ name, data }) => {
  await fetch(`/api/forms/${encodeURIComponent(name)}`, { method: "PUT", body: data });
});
```

Without `fillSign:false`, users can also type and sign anywhere on the page, which is what you
want for PDFs that are not real forms.

### Page organizer

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/report.pdf" },
  mode: "organize",
  ui: { panels: { pages: true } },
});
```

`organize` includes `export` (extracting and splitting pages); add `features: { export: false }`
to keep users to rearranging.

### Everything

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/anything.pdf" },
  mode: "full",
  features: { javascript: true }, // only if you trust the documents' scripts
});
```

## Change the configuration at runtime

The mode, features, interface options and hidden elements can change after `init`, without
reloading the viewer or the document (so can the theme, author and language, with `setTheme`,
`setAuthor` and `setLocale`):

| Method | What it does |
|---|---|
| `setMode(mode)` | Switches the preset. Your feature overrides still apply on top of the new mode. |
| `setFeatures(features)` | **Replaces** the feature overrides. Pass `{}` to use the mode's features as they are. |
| `setUi(ui)` | **Merges**: options you leave out keep their value. Panels you name are changed, the others are kept. |
| `setDisabledElements(ids)` | Replaces the list of hidden elements. |
| `getConfig()` | Resolves to the configuration in effect. |

```ts
// Start read-only, let the user switch to annotating.
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  document: { url: "/files/artwork.pdf" },
  mode: "view",
  features: { print: false },
});

editButton.onclick = async () => {
  await viewer.setMode("annotate");        // print stays off: the override is kept
  await viewer.setFeatures({ print: false, stamps: false }); // the full list of overrides
  await viewer.setUi({ quickToolbar: false });               // other ui options unchanged

  const config = await viewer.getConfig();
  console.log(config.mode);              // "annotate"
  console.log(config.features.stamps);   // false
  console.log(config.features.ink);      // true
  console.log(config.readOnly);          // false
};
```

`getConfig()` resolves to a `ViewerConfig`: the `mode`, `features` with **every** feature
`true` or `false` (the mode's preset with your overrides applied), the full `ui` options with
the `panels` you set, `disabledElements`, and `readOnly`.

Because `setFeatures` replaces the overrides, keep your overrides in one place and always pass
the complete set:

```ts
const overrides = { print: false };
await viewer.setFeatures({ ...overrides, stamps: false });
```

The framework integrations do this for you: changing the `mode`, `features`, `ui` or
`disabledElements` prop calls the matching method (see [React](/docs/react/)).

Unknown feature keys, `ui` options, panel names and element ids are rejected with
`BAD_REQUEST`, both in `init` and in the `set*` methods.

## Interface options (`ui`)

| Option | Default | What it does |
|---|---|---|
| `toolsPanel` | `true` | The Tools panel on the left, listing the tool groups of the enabled features. |
| `toolsRail` | `true` | A slim rail that brings the Tools panel back once it is closed. |
| `quickToolbar` | `true` | The floating tool bar beside the page (Select, Hand and the enabled tools). |
| `rightRail` | `true` | The right-hand rail: panel buttons, page navigation and zoom. |
| `zoomControls` | `true` | Zoom and page display controls on the rail. |
| `pageNavigation` | `true` | Page navigation on the rail. |
| `menu` | `true` | The main menu button (File, Edit, View... with the enabled commands). |
| `searchBox` | `true` | The "Find tools and commands" box in the top bar (needs the palette feature). |
| `lockLayout` | `false` | Panels can't be moved, floated or closed from their tabs. |
| `showPlannedTools` | `false` | Also list tools that are planned but not available yet. |
| `externalLinks` | `true` | Links to web pages in documents may open (after a prompt). |

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  mode: "annotate",
  ui: {
    toolsPanel: true,
    quickToolbar: false,   // no floating tool bar beside the page
    searchBox: false,      // no "Find tools and commands" box
    lockLayout: true,      // panels stay where they are
    externalLinks: false,  // links to web pages in the document don't open
  },
});
```

A few options depend on others: `toolsRail` only matters while `toolsPanel` is on, and
`searchBox` only shows when the `palette` feature is on.

### Panels

`ui.panels` shows or hides the right-hand panels. A panel you don't list shows when its
feature is on; listing it as `false` hides it even then.

| Panel | What it shows |
|---|---|
| `comments` | The comment list |
| `bookmarks` | Bookmarks |
| `pages` | Page thumbnails |
| `fields` | Form fields |
| `layers` | Layers |
| `attachments` | File attachments |
| `signatures` | Digital signatures (needs signaturePanel) |
| `accessibility` | Accessibility checker (needs accessibility) |
| `tags` | Structure tags (needs accessibility) |
| `search` | Advanced search results (needs search) |

```ts
await viewer.setUi({ panels: { layers: false, attachments: false, comments: true } });
```

Setting a panel to `true` does not turn its feature on: the signatures panel still needs
`signaturePanel`, the accessibility and tags panels need `accessibility`.

## Hide single commands (`disabledElements`)

`disabledElements` hides individual commands and tools. Each id stands for one or more
commands in the viewer:

| Element id | Hides |
|---|---|
| `download` | `file.save_as`, `comment.export`, `form.export_data`, `measure.export`, `export.docx`, `export.html`, `export.image`, `export.pptx`, `export.rtf`, `export.text`, `export.all_images`, `group:export` |
| `save` | `file.save`, `file.save_as` |
| `print` | `print.dialog` |
| `open` | `file.open`, `file.open_recent`, `file.pin_folder`, `file.close`, `file.close_all`, `create.blank`, `group:create`, `group:combine` |
| `flatten` | `comment.flatten`, `form.flatten` |
| `settings` | `app.preferences` |
| `import` | `comment.import`, `form.import_data` |
| `tool:note` | `comment.note` |
| `tool:freetext` | `comment.freetext` |
| `tool:callout` | `comment.callout` |
| `tool:highlight` | `comment.highlight` |
| `tool:underline` | `comment.underline` |
| `tool:strikeout` | `comment.strikeout` |
| `tool:squiggly` | `comment.squiggly` |
| `tool:caret` | `comment.caret` |
| `tool:replace` | `comment.replace` |
| `tool:ink` | `comment.ink`, `comment.eraser` |
| `tool:line` | `comment.line` |
| `tool:arrow` | `comment.arrow` |
| `tool:square` | `comment.square` |
| `tool:circle` | `comment.circle` |
| `tool:polygon` | `comment.polygon` |
| `tool:polyline` | `comment.polyline` |
| `tool:cloud` | `comment.cloud` |
| `tool:attach` | `comment.attach` |
| `tool:stamp` | `comment.stamp`, `group:stamp` |
| `tool:image` | `edit.image` |
| `tool:link` | `edit.link`, `edit.links_from_urls` |
| `tool:measure` | `measure.distance`, `measure.perimeter`, `measure.area`, `measure.scale`, `measure.info`, `measure.snap`, `measure.export`, `group:measure` |
| `tool:fillsign` | `sign.fill.text`, `sign.fill.check`, `sign.fill.cross`, `sign.fill.dot`, `sign.fill.line`, `sign.fill.date`, `sign.fill.signature`, `sign.fill.initials`, `group:fill_sign` |
| `tool:signature` | `sign.fill.signature`, `sign.fill.initials` |

```ts
const viewer = await FreePdf.init(element, {
  baseUrl: "/free-pdf-sdk/",
  mode: "annotate",
  disabledElements: ["tool:squiggly", "tool:caret", "tool:replace", "settings"],
});

// Later: the list is replaced, not extended.
await viewer.setDisabledElements(["tool:squiggly"]);
```

### Features or disabledElements?

Prefer **features** whenever one matches what you want to remove:

- A feature removes a whole capability everywhere and the viewer refuses it if it is reached
  anyway. `features: { stamps: false }` is the reliable way to forbid stamps.
- A feature that is off changes what the viewer considers an edit: with every editing feature
  off, the viewer becomes read-only.
- `disabledElements` hides the listed commands from the interface and nothing else. Use it to
  remove one tool inside a feature you keep, for example squiggly underline while keeping the
  other markup tools, or the viewer's Save command while keeping undo.

Neither affects your own code: `disabledElements: ["import"]` hides the viewer's Import
commands, but `viewer.importXfdf()` still works. The API refuses `importXfdf` and
`deleteAllAnnotations` with `READ_ONLY` only when no annotation feature is on.

## Next steps

- [API reference](/docs/api/): every option, method, event and error code.
- [Annotations and XFDF](/docs/annotations-and-xfdf/): store and restore comments.
