# Removed in v2

> Every v1 import and editor internal that no longer works in SuperDoc v2, and what replaces it.





Upgrading breaks three things, and they surface at different times. Removed subpaths always fail module resolution. Removed root exports fail the build under ESM and TypeScript, but a CommonJS `require` binds them to `undefined` and fails later at the call site. Configuration and editor internals that v2 no longer honors fail only once the editor is running, often without naming SuperDoc at all.

Work through them in that order. The import failures are the loudest, and fixing them tells you where the rest of the work is.

This page describes `superdoc@2.0.0-next.36` compared against `superdoc@1.45.0`. A machine-readable version is available at [`/migration/v1-to-v2.json`](/migration/v1-to-v2.json).

## How to read the Migration column [#how-to-read-the-migration-column]

* **Mechanical** — A direct substitution with equivalent behavior. Safe to apply mechanically, and required to be backed by a compiled fixture before it carries this label.
* **Redesign** — A replacement exists, but the semantics differ. Read the replacement and re-verify the behavior; do not apply it as a find-and-replace.
* **No equivalent** — No v2 equivalent. The capability must be removed or rebuilt outside SuperDoc.

Nothing here is currently classified as Mechanical, so this page is an inventory and a decision aid, not a codemod. Do not apply any of it as an automated find-and-replace.

## Search the reference [#search-the-reference]

> **Searchable migration reference.**
>
> The interactive explorer filters the same entries listed in the tables below,
> by symbol name, by when the failure surfaces, and by how much work the migration is.
> A machine-readable version of every entry is published at `/migration/v1-to-v2.json`.


Every entry is also listed in full below, grouped by when the failure surfaces. The tables are the canonical form: they work without JavaScript and are what `llms.txt` and search engines read.

## Your application no longer imports [#your-application-no-longer-imports]

### Removed package subpaths [#removed-package-subpaths]

v1 published 10 code subpaths. v2 publishes 3: `superdoc/collaboration-upgrade-engine`, `superdoc/ui`, `superdoc/ui/react`.

| v1                                | v2                      | Migration     | Notes                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------------------------- | ----------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `superdoc/types`                  | `superdoc`              | Redesign      | Not a path rename. v1 re-exported 116 names here, almost all of them ProseMirror and schema types, and none of them exist on the v2 root. Integration types such as `Config`, `DocumentMode`, `User`, and `DocumentApi` are exported from `superdoc`; types describing ProseMirror nodes, marks, commands, and transactions have no v2 equivalent because the model they described is gone. [Read more](/document-api/mental-model) |
| `superdoc/super-editor`           | `superdoc.activeEditor` | Redesign      | v2 has no importable editor class. Reach the active document through the `SuperDoc` instance and its Document API facade. [Read more](/document-api/mental-model)                                                                                                                                                                                                                                                                   |
| `superdoc/converter`              | *None*                  | No equivalent | v2 owns DOCX parsing and serialization internally. Load documents through `document` and produce output through `export()`. [Read more](/editor/load-and-save-documents)                                                                                                                                                                                                                                                            |
| `superdoc/docx-zipper`            | *None*                  | No equivalent | No public archive surface in v2. Use the supported load and export workflow.                                                                                                                                                                                                                                                                                                                                                        |
| `superdoc/file-zipper`            | *None*                  | No equivalent | No public archive surface in v2. Use the supported load and export workflow.                                                                                                                                                                                                                                                                                                                                                        |
| `superdoc/headless-toolbar`       | `superdoc.ui`           | Redesign      | `superdoc.ui` is a getter that lazily creates and owns the controller. It returns `BorrowedSuperDocUI`, which omits `destroy()` because `superdoc.destroy()` owns teardown. Call `createSuperDocUI({ superdoc })` from `superdoc/ui` only when you want an independently owned controller to dispose yourself. [Read more](/editor/custom-ui/overview)                                                                              |
| `superdoc/headless-toolbar/react` | `superdoc/ui/react`     | Redesign      | Hooks and providers moved and now bind to the instance-owned controller. [Read more](/editor/custom-ui/overview)                                                                                                                                                                                                                                                                                                                    |
| `superdoc/headless-toolbar/vue`   | `superdoc.ui`           | Redesign      | v2 ships no Vue-specific bindings. Build on the framework-agnostic controller. [Read more](/editor/custom-ui/overview)                                                                                                                                                                                                                                                                                                              |

A removed subpath fails module resolution in every module system, because it is absent from the package's exports map. Do not work around it by importing an internal package: names such as `@superdoc/v2-host` and `@superdoc/document-api-v2-adapter` are implementation details with no compatibility guarantee.

### Removed root exports [#removed-root-exports]

v1 exported 41 runtime values from the package root. v2 exports 10: `BlankDOCX`, `DOCX`, `HTML`, `PDF`, `SuperDoc`, `buildTheme`, `compareVersions`, `createTheme`, `defineSuperDocExtension`, `getFileObject`.

Everything below was removed. `defineSuperDocExtension` is the one value v2 adds.

#### Editor internals [#editor-internals]

| v1                          | v2                                       | Migration     | Notes                                                                                                                                                                                                                                                                                                                           |
| --------------------------- | ---------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Editor`                    | `superdoc.activeEditor`                  | Redesign      | v2 exposes no editor constructor. Mount through `SuperDoc` and read the active document via its Document API facade. [Read more](/document-api/mental-model)                                                                                                                                                                    |
| `PresentationEditor`        | *None*                                   | No equivalent | v2 owns rendering internally. There is no public presentation-editor surface.                                                                                                                                                                                                                                                   |
| `SuperEditor`               | `SuperDoc`                               | Redesign      | The mounting capability survives, the component does not. v1 rendered a Vue component taking `fileSource`, `documentId`, `state`, and `options` props; v2 mounts imperatively with `new SuperDoc({ selector, document })`. A React or Vue wrapper is now application code around that instance. [Read more](/editor/quickstart) |
| `SuperInput`                | *None*                                   | No equivalent | v2 ships no importable single-line input component, and no v2 surface is a drop-in equivalent. Build the control in your application.                                                                                                                                                                                           |
| `superEditorHelpers`        | `superdoc.activeEditor.doc`              | Redesign      | Helper bags are replaced by explicit Document API operations. [Read more](/document-api/mental-model)                                                                                                                                                                                                                           |
| `trackChangesHelpers`       | `superdoc.activeEditor.doc.trackChanges` | Redesign      | Helper bag replaced by explicit Document API operations for listing, navigating, and deciding tracked changes. [Read more](/document-api/tracked-changes)                                                                                                                                                                       |
| `fieldAnnotationHelpers`    | `superdoc.activeEditor.doc`              | Redesign      | Field and annotation work moves to Document API operations.                                                                                                                                                                                                                                                                     |
| `AnnotatorHelpers`          | `superdoc.activeEditor.doc`              | Redesign      | Helper bag replaced by explicit Document API operations. Field and annotation work goes through `doc`, not a helper namespace.                                                                                                                                                                                                  |
| `SectionHelpers`            | `superdoc.activeEditor.doc.sections`     | Redesign      | Verify coverage before migrating: linked-section workflows may not have full v2 equivalents.                                                                                                                                                                                                                                    |
| `getAllowedImageDimensions` | *None*                                   | No equivalent | No public sizing helper in v2. Compute the constraint in your application, or let the engine apply its own bounds on insert.                                                                                                                                                                                                    |
| `CommentsPluginKey`         | `superdoc.activeEditor.doc.comments`     | Redesign      | v2 exposes no ProseMirror plugin keys. Use the Document API comments operations. [Read more](/document-api/comments)                                                                                                                                                                                                            |
| `TrackChangesBasePluginKey` | `superdoc.activeEditor.doc.trackChanges` | Redesign      | v2 exposes no ProseMirror plugin keys. [Read more](/document-api/tracked-changes)                                                                                                                                                                                                                                               |

#### Converter and archives [#converter-and-archives]

| v1               | v2     | Migration     | Notes                                                                                                                                                     |
| ---------------- | ------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SuperConverter` | *None* | No equivalent | DOCX conversion is internal to the v2 engine. Load through `document` and produce output through `export()`. [Read more](/editor/load-and-save-documents) |
| `DocxZipper`     | *None* | No equivalent | No public archive surface in v2.                                                                                                                          |
| `createZip`      | *None* | No equivalent | No public archive surface in v2.                                                                                                                          |

#### Custom UI [#custom-ui]

| v1                      | v2                  | Migration     | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ----------------------- | ------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SuperToolbar`          | `config.toolbar`    | Redesign      | For the built-in toolbar, pass a container through `toolbar` in the config. For a custom toolbar, drive `superdoc.ui`. [Read more](/editor/built-in-ui/configure-the-toolbar)                                                                                                                                                                               |
| `Toolbar`               | `config.toolbar`    | Redesign      | The built-in toolbar is configured, not imported and rendered by the consumer. [Read more](/editor/built-in-ui/configure-the-toolbar)                                                                                                                                                                                                                       |
| `ContextMenu`           | *None*              | No equivalent | `getV2FeatureMatrix()` reports `shell.context-menu` as not-shipped: the v2 shell disables the legacy context menu. A `modules.contextMenu` config field exists but no v2 runtime renders it, so it is not a working replacement. Build an application-owned menu on `superdoc.ui` if you need one. [Read more](/editor/built-in-ui/links-and-context-menus) |
| `SlashMenu`             | *None*              | No equivalent | `modules.slashMenu` is marked deprecated in favor of `modules.contextMenu`, which is itself not-shipped. Do not migrate onto either; build an application-owned menu on `superdoc.ui`.                                                                                                                                                                      |
| `AIWriter`              | `config.modules.ai` | Redesign      | The built-in toolbar renders the AI writer when `modules.ai` is configured, and applies generated text through the Document API.                                                                                                                                                                                                                            |
| `getMarksFromSelection` | `superdoc.ui`       | Redesign      | Active formatting is published as reactive controller state rather than read from a selection. [Read more](/editor/custom-ui/overview)                                                                                                                                                                                                                      |
| `getActiveFormatting`   | `superdoc.ui`       | Redesign      | Active formatting is published as reactive controller state rather than read from a selection. [Read more](/editor/custom-ui/overview)                                                                                                                                                                                                                      |

#### Extensions [#extensions]

| v1                       | v2                        | Migration     | Notes                                                                                                                                                                                                                                                      |
| ------------------------ | ------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Extensions`             | `defineSuperDocExtension` | Redesign      | v2 extensions receive commands, anchors, and decorations. They do not receive ProseMirror state, custom schema, or mutable DOM, so extensions that defined custom nodes or marks may have no v2 equivalent. [Read more](/editor/custom-ui/custom-commands) |
| `defineNode`             | *None*                    | No equivalent | v2 has no custom-schema surface. Custom document nodes cannot be reproduced. [Read more](/editor/custom-ui/custom-commands)                                                                                                                                |
| `defineMark`             | *None*                    | No equivalent | v2 has no custom-schema surface. Custom marks cannot be reproduced. [Read more](/editor/custom-ui/custom-commands)                                                                                                                                         |
| `getStarterExtensions`   | *None*                    | No equivalent | v2 loads its own document capabilities. There is no consumer-assembled extension list.                                                                                                                                                                     |
| `getRichTextExtensions`  | *None*                    | No equivalent | v2 loads its own document capabilities. There is no consumer-assembled extension list.                                                                                                                                                                     |
| `isNodeType`             | *None*                    | No equivalent | ProseMirror node predicates have no v2 equivalent. Query structure through the Document API. [Read more](/document-api/query-content)                                                                                                                      |
| `assertNodeType`         | *None*                    | No equivalent | ProseMirror node predicates have no v2 equivalent. Query structure through the Document API. [Read more](/document-api/query-content)                                                                                                                      |
| `isMarkType`             | *None*                    | No equivalent | ProseMirror mark predicates have no v2 equivalent.                                                                                                                                                                                                         |
| `getSchemaIntrospection` | *None*                    | No equivalent | v2 exposes no ProseMirror schema to introspect.                                                                                                                                                                                                            |
| `registeredHandlers`     | *None*                    | No equivalent | Marked internal in v1 and removed in v2.                                                                                                                                                                                                                   |

A missing named export is only reliably caught at build time under ESM and TypeScript. In CommonJS, `const { Editor } = require('superdoc')` binds `undefined` and fails later wherever the value is used, so a CommonJS integration can appear to upgrade cleanly and then break at the call site.

### Names dropped from subpaths that still exist [#names-dropped-from-subpaths-that-still-exist]

A subpath surviving is not the same as its exports surviving. These paths still resolve, so only the named import fails.

| v1                         | v2            | Migration | What you see                                                                                                                                                          | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| -------------------------- | ------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `superdoc/ui type exports` | `superdoc/ui` | Redesign  | The import path still resolves, so only the named type fails. TypeScript reports the missing name; a plain JavaScript build sees nothing because these are type-only. | `ContextMenuContribution`, `ContextMenuWhenInput`, `DocumentExportInput`, `DynamicCommandHandle`, `PublicToolbarItemId`, `SelectionAnchorRectOptions`, `TextSegment`, `ToolbarCommandHandleState`, `UIToolbarCommandState`, `ViewportContextAtInput`, `ViewportEntityAtInput`, `ViewportPositionAtInput`, `ViewportPositionHit`, `ZoomMode`, `ZoomViewportMetrics`. v2 rebuilt `superdoc/ui` as a native controller rather than re-exporting v1, so these 15 type names did not carry over. Use the controller types v2 publishes from the same path. [Read more](/editor/custom-ui/overview) |

## Your application imports successfully, then fails when it runs [#your-application-imports-successfully-then-fails-when-it-runs]

These compile. Some of them typecheck against the v2 configuration. They fail, or do nothing, once the editor is running.

| v1                                                                                     | v2                                                           | Migration     | What you see                                                                                                                                                                                                                 | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `editor.commands`                                                                      | `superdoc.activeEditor.doc`                                  | Redesign      | A null-property error at the point of use. The message names the command, not SuperDoc, so it does not read as a migration failure.                                                                                          | The v2 facade exposes `commands` as null rather than removing it. Optional chaining converts the throw into a silent no-op, which is harder to notice. [Read more](/document-api/mental-model)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `editor.state`                                                                         | `superdoc.activeEditor.doc`                                  | Redesign      | A null-property error, or `undefined` when accessed with optional chaining.                                                                                                                                                  | There is no ProseMirror document model in v2. Positions expressed as numeric offsets have no equivalent; use addresses and targets. [Read more](/document-api/query-content)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `editor.view`                                                                          | *None*                                                       | No equivalent | A null-property error, or `undefined` when accessed with optional chaining.                                                                                                                                                  | v2 renders through its own engine and exposes no editor view or mutable DOM.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `superdoc.getDocumentRuntimeForDocument(documentId)`                                   | `superdoc.ui`                                                | Redesign      | The lookup returns `null`, and application code that treats the renderer as the ready UI surface throws an error such as `DocumentRuntime is not available`.                                                                 | V2 custom UI does not need to retrieve the renderer runtime. Read the instance-owned `superdoc.ui` controller after `onReady`; it publishes reactive feature state and routes UI actions without exposing the renderer object. `superdoc.ui` is a getter, not an import. The instance creates it once and owns its cleanup. [Read more](/editor/migrate-from-v1/overview)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `documentRuntime.scrollToElement(elementId)`                                           | `superdoc.ui.*.scrollTo / superdoc.scrollToElement`          | Redesign      | The preceding runtime lookup returns `null`, so navigation throws or is skipped even though the document is mounted.                                                                                                         | Route known entities through their feature handle: `ui.trackChanges.scrollTo(changeId)`, `ui.comments.scrollTo(commentId)`, or `ui.contentControls.scrollIntoView({ id })`. These methods resolve through the public host navigation surface and can reveal virtualized pages. Use `superdoc.scrollToElement(elementId)` when all you have is a stable block, comment, or tracked-change id. The root facade keeps the renderer object private and returns `false` when navigation cannot be routed. [Read more](/editor/migrate-from-v1/overview)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `editor.view.dispatch(tr.setSelection(...))`                                           | `superdoc.ui.selection.apply`                                | Redesign      | A null-property error on `view`, or `undefined` under optional chaining.                                                                                                                                                     | Setting the selection programmatically is supported. Pass a `SelectionTarget` to `selection.apply()` rather than dispatching a transaction. Read it from `selection.current().selectionTarget` or a query result; there is no ProseMirror position to hand it. [Read more](/editor/custom-ui/selection-and-viewport)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `editor.view.posAtCoords`                                                              | `superdoc.ui.viewport.entityAt`                              | Redesign      | A null-property error on `view`, or `undefined` under optional chaining.                                                                                                                                                     | Partial. `viewport.entityAt({ x, y })` resolves the public entities painted under a point (tracked changes, comments, content controls), innermost first, and returns `[]` over plain text. That covers hit-testing, which is what most `posAtCoords` callers wanted, but v2 ships no general point-to-document-position resolver, so a caller that needs an arbitrary position under the cursor has no equivalent. The legacy positional form `entityAt(x, y)` fails closed and returns `null`. [Read more](/editor/custom-ui/selection-and-viewport)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `editor.view.coordsAtPos`                                                              | `superdoc.ui.viewport.getRect`                               | Redesign      | A null-property error on `view`, or `undefined` under optional chaining.                                                                                                                                                     | The opposite direction from `entityAt`, and a different surface. `viewport.getRect({ target })` resolves painted geometry for a public target and returns `{ found, rects, rect, reason }`. It is keyed on a target, not a numeric position, so obtain one from `selection.capture()` or a query result first. [Read more](/editor/custom-ui/selection-and-viewport)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `manual tracked-change traversal through editor.state`                                 | `superdoc.ui.trackChanges.navigateNext`                      | Redesign      | A null-property error on `state`, or `undefined` under optional chaining.                                                                                                                                                    | Review navigation is supported. `trackChanges.navigateNext()` moves through changes and `trackChanges.list()` reads the catalog. The catalog resolves asynchronously, so observe the slice until `status` is `ready` before consuming `items`. [Read more](/editor/custom-ui/tracked-changes)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `editorExtensions`                                                                     | `extensions`                                                 | Redesign      | The config typechecks and the editor mounts, but the extensions never run. SuperDoc logs a console warning naming the field.                                                                                                 | A legacy ProseMirror concept that v2 ignores. Rebuild against `extensions` with `defineSuperDocExtension`; extensions defining custom nodes or marks may have no equivalent. [Read more](/editor/custom-ui/custom-commands)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `modules.collaboration`                                                                | `document.v2Collaboration`                                   | Redesign      | The config typechecks, then SuperDoc refuses to attach the provider and reports a terminal compatibility failure.                                                                                                            | v2 owns the provider and Y.Doc. This is a data migration, not a config change: v2 rooms use a different format and must not be pointed at an existing v1 room. [Read more](/editor/migrate-from-v1/overview)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `editor.commands.replaceWithFieldAnnotation (citation)`                                | `doc.citations.insert`                                       | Redesign      | A null-property error on `commands`, or a silent no-op under optional chaining.                                                                                                                                              | `editor.commands.replaceWithFieldAnnotation`. One v1 node type did two jobs and v2 splits them, so decide which this annotation was before porting it. This row is the citation branch: a marker backed by a source record is `citations.sources.insert()` followed by `citations.insert({ at, sourceIds })`, where `sourceIds` carries the canonical `sourceId` from the receipt rather than the source tag. Not a rename, and not a replacement either: v1 replaced its `from`/`to` range, while `citations.insert` resolves `at`, then prepends the field to the start of the containing paragraph and reports offset 0. The selected text is left where it was. Delete the range yourself if the citation is meant to stand in for it, and do not expect the citation to land at the offset you passed. If the annotation was application-owned data rather than a citation, use the `metadata.attach` row instead. [Read more](/document-api/reference/citations/insert)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `editor.commands.replaceWithFieldAnnotation (application annotation)`                  | `doc.metadata.attach`                                        | Redesign      | A null-property error on `commands`, or a silent no-op under optional chaining.                                                                                                                                              | `editor.commands.replaceWithFieldAnnotation`. The other half of the same v1 call. An annotation carrying application-owned data anchored to a range is `metadata.attach({ id, namespace, target, payload })`, and the entries it creates are not v1 field annotations: the ids, the payloads, and the anchoring model all differ, so treat this as remodelling rather than a rename. Read them back with `metadata.list({})` and `metadata.get({ id })`. If the annotation was a citation with a source record, use the `citations.insert` row instead. [Read more](/document-api/reference/metadata/attach)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `editor.state.doc.descendants (citation nodes)`                                        | `doc.citations.list`                                         | Redesign      | A null-property error on `state`, or `undefined` under optional chaining.                                                                                                                                                    | Reading citations no longer means walking a node tree. `citations.list()` returns the rows with their addresses and `sourceIds`. Item order can drive application-owned numbering, but that produces local UI labels only: it does not change the citation field result stored in the DOCX. The call is synchronous in some hosts and asynchronous in others, so shared browser and headless code should normalize with `await Promise.resolve(doc.citations.list())`. [Read more](/document-api/reference/citations/list)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `editor.helpers.fieldAnnotations.getAll()`                                             | `doc.metadata.list`                                          | Redesign      | A null-property error on `helpers`, or `undefined` under optional chaining.                                                                                                                                                  | A shape change, not a rename. `getAll()` returned v1 field annotations; `metadata.list({})` returns anchored-metadata entries whose ids, payloads, and anchoring model all differ. `metadata.list` is the discovery call and `metadata.get({ id })` reads one payload, so pair them when you need the collection. `get` returns null for an entry that disappeared between the two calls. Treat legacy field annotations as something to remodel rather than something this call returns. [Read more](/document-api/reference/metadata/list)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `tr.setNodeMarkup(pos, undefined, { resolvedText })`                                   | `doc.fields.insert`                                          | Redesign      | A null-property error reaching the transaction. Citations inserted through the citations API persist and export, but render with no visible text.                                                                            | The citations API cannot do this: `CitationInsertInput` accepts only `at` and `sourceIds`, `CitationUpdateInput.patch` accepts only `sourceIds`, and `displayText` is on `CitationInfo` as a read with no writer. `citations.bibliography.rebuild` is not it either; it rebuilds the bibliography from current sources at a `BibliographyAddress` and never touches inline citation text. The one public path is a level lower: `fields.insert({ at, instruction, mode: "raw", updatePolicy: "preserveCached", cachedResultText })` writes the visible result directly. Three costs come with it. You author the field instruction and keep the source records in step yourself, so you are outside the citation model rather than extending it. `fields.rebuild` recalculates a field and discards the preserved result. And the contract records `preserveCached` returning `CAPABILITY_UNAVAILABLE` on v1-backed sessions, so confirm it on your target runtime before depending on it. There is still no way to change the visible text of a citation the citations API already inserted. [Read more](/document-api/reference/fields/insert)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `.superdoc-text-run[data-pm-start] (citation pill styling)`                            | `ctx.visuals.highlight`                                      | Redesign      | Nothing breaks, which is the problem. The painter still stamps `data-pm-start` on runs, so the selector keeps matching and the code keeps mutating renderer-owned DOM.                                                       | This one does not fail on upgrade. `layout-engine/dom-contract` stamps `data-pm-start` and `data-pm-end` alongside the editor-neutral attributes specifically so v1 consumers keep working, and `.superdoc-text-run` is still the painted class. What you lose is the guarantee: the DOM shape is renderer-owned and carries no stability contract, so this is worth migrating before a paint change breaks it silently rather than after. The supported replacement is a painted class through `ctx.visuals.highlight(id, { className })`, or `ctx.decorations.register` underneath it. A `CitationAddress` is not itself a visual target, but converting one is mechanical rather than blocked, because both sides use the same coordinate system. `CitationAddress.anchor` is an `InlineAnchor` of `{ blockId, offset }` positions, and `Position.offset` is a 0-based offset into the block's flattened text, which is what `SuperDocTextAddress.range` expects: `{ kind: "text", blockId: anchor.start.blockId, range: { start: anchor.start.offset, end: anchor.end.offset } }`. The real limit is the class. `className` accepts paint properties only: background, color, text-decoration, outline, and box-shadow, explicitly not padding, margin, display, or position. Recolouring citation text works; a padded pill shape does not. Decorations are render-only and never reach the DOCX.                                                                                                                                                                                                                                          |
| `superdoc.on('fieldAnnotationClicked')`                                                | *None*                                                       | No equivalent | The subscription is accepted and the handler never fires.                                                                                                                                                                    | v2 emits no per-entity click events, and nothing recovers the identity this one carried. `superdoc.ui.viewport.entityAt` is the supported point lookup, but it collects only tracked changes, comments, and content controls, so it cannot return a field annotation and is not a replacement for this event. Whether hit-testing helps at all depends on what the annotation became: content controls are returned, citations and anchored metadata are not. Decide the v2 model for the annotation first, then pick the lookup that model supports.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `editor.state.selection`                                                               | `superdoc.ui.selection.current`                              | Redesign      | A null-property error on `state`, or `undefined` under optional chaining.                                                                                                                                                    | A v1 `Selection` was one live object used for both reading and preserving, and v2 splits those. To read the current selection use `selection.current()` or the observed snapshot; both describe a collapsed caret. To preserve a selection across something that moves focus, use `capture()` and then `restore()`. Do not reach for `capture()` as the general read: it returns null whenever the selection is empty, which includes a collapsed caret, so caret-dependent code migrated onto it loses the selection it was trying to keep. Either way the payload is document addresses rather than numeric positions. [Read more](/editor/custom-ui/selection-and-viewport)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `document.getSelection().getRangeAt(0).getBoundingClientRect()`                        | `superdoc.ui.selection.getAnchorRect`                        | Redesign      | The browser selection reflects rendered DOM rather than document state, so the rectangle is wrong or the call throws on an empty range.                                                                                      | `getAnchorRect()` resolves one rectangle from the document selection against the painted layout, and accepts `'start'`, `'end'`, or `'center'`. v1's `'union'` placement has no v2 value: use `selection.getRects()` when a bubble needs the full multi-line union.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `document.querySelector('[data-comment-id="..."]')`                                    | `superdoc.ui.viewport.getRect`                               | Redesign      | Depends on the sidebar, which is the trap. With the built-in comments UI enabled the selector matches a sidebar card and positions against the wrong element; with it disabled the same selector matches nothing.            | The painter stamps no singular `data-comment-id` on document content, but `FloatingComments.vue` binds one on each sidebar placeholder, so an integration running the built-in comments UI gets a match that is a panel card rather than the painted anchor. Code that scrolls or positions from it silently targets the sidebar. Turn the sidebar off and the same selector returns null, so the failure changes shape with configuration rather than being absent. There is a second near miss: the painter stamps `data-comment-ids`, plural and comma-separated, on `.superdoc-comment-highlight`, and retargeting the selector there puts you back on renderer-owned DOM with no stability contract. Read the comment through `ui.comments.getById()` and resolve its target with `viewport.getRect({ target })` instead. Treat a `null` from `getById()` as "not loaded yet" rather than "no such comment": it checks the loaded snapshot, then falls back to the Document API, and returns `null` when that fallback is a pending promise, which is the normal browser case. It does not prime the read either, unlike `contentControls.getById()`, and `comments.list()` returns `[]` on the same path. Gate on the observed comments slice, and gate on `listStatus` rather than `status`: `status` folds in the live selection read, so an unrelated selection change holds it at `pending` while the list is ready. Do not cache the rectangle as identity: geometry changes on scroll, zoom, resize, and pagination, and `viewport.observe()` is the signal to measure again. [Read more](/editor/custom-ui/selection-and-viewport) |
| `document.querySelector('[data-track-change-id="..."]').scrollIntoView()`              | `superdoc.ui.trackChanges.scrollTo`                          | Redesign      | Usually a match, and a `TypeError` when not. The call as written dereferences the result, so a change that is not painted takes down whatever runs it, and the same code works in a short document and throws in a long one. | This survives the upgrade, which is why it is worth migrating deliberately. The v2 painter still stamps `data-track-change-id` on painted runs, so the selector keeps resolving and nothing announces that it has become unreliable. It misses in two different ways. A change on a page that is not currently painted has no element at all, because `querySelector` sees only mounted DOM and virtualization leaves the rest of the document unrendered. And where several changes affect one marker, only one id lands in the singular attribute: the rest are in `data-track-change-ids`, comma-separated, so a secondary overlapping change is unreachable by the selector even while it is on screen. Both misses reach `.scrollIntoView()` on `null` and throw, unless the call is guarded. The attribute is renderer-owned and carries no stability contract either. `trackChanges.scrollTo(changeId)` takes the id rather than a selector, mounts the target page when it has to, resolves overlapping changes through the same catalog the review UI uses, and reports whether it succeeded. [Read more](/editor/custom-ui/tracked-changes)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `new MutationObserver(...) on the editor element`                                      | `superdoc.ui.viewport.observe`                               | Redesign      | The observer attaches and fires on repaints that do not correspond to document changes, or never fires for layout changes that produce no mutations.                                                                         | Watching the rendered DOM was always a proxy for the question consumers were asking. `viewport.observe()` fires when painted geometry is invalidated, including scroll, zoom, resize, pagination, and virtualized page mounts, which a subtree MutationObserver either misses or floods on. [Read more](/editor/custom-ui/selection-and-viewport)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `element.scrollIntoView() on a content-control element`                                | `superdoc.ui.contentControls.scrollIntoView`                 | Redesign      | There is no element to hold: the query that produced it matches nothing, so the call throws or is skipped.                                                                                                                   | Address the control by id rather than by element: `contentControls.scrollIntoView({ id, block })` resolves it through the host, including on pages that are not currently painted. A DOM-held reference cannot survive virtualization.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `editor.comments.filter((c) => c.isTrackedChange)`                                     | `superdoc.ui.trackChanges.list`                              | Redesign      | A null-property error on `comments`. Once ported, the more damaging failure is quiet: a document full of tracked changes reports none.                                                                                       | v2 separates tracked changes from comments instead of tagging one list. The trap is readiness, not the split: the catalog is an async read, so a synchronous `list()` on a controller that has not settled returns an empty snapshot rather than an error. Observe the slice and consume `items` once `status` is `ready`. `total` and `authors` come from the same slice and carry the same caveat. [Read more](/editor/custom-ui/tracked-changes)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `editor.presentationEditor`                                                            | `superdoc.activeEditor.pageMetrics`                          | Redesign      | A null-property error on `presentationEditor`, or `undefined` under optional chaining.                                                                                                                                       | `presentationEditor.getPages`, `presentationEditor.onLayoutUpdated`, `presentationEditor.element`. Page metrics survive as a capability. `pageMetrics` exposes `getSnapshot`, `subscribe`, `setZoom`, `scrollToPage`, `revealBodyTarget`, and `pageIndexForBodyTarget`, and `ui.viewport.getHost()` replaces reading `presentationEditor.element`. The facade types `pageMetrics` as `unknown`, so consuming it means declaring the shape yourself and re-verifying it on upgrade; it is not part of the typed public surface the rest of this catalog points at.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `.superdoc-page[data-page-index] (page element lookup)`                                | `superdoc.activeEditor.pageMetrics`                          | Redesign      | Usually nothing, which hides the two cases that matter. The painter still stamps `data-page-index` on `.superdoc-page`, so the selector keeps matching for mounted pages and returns null for virtualized ones.              | The DOM lookup survives the upgrade rather than breaking, so this migrates on correctness rather than on a build error. Page windowing means only mounted pages have elements, and a page outside the window returns null from the selector while still having metrics. Read the page from the metrics snapshot instead. The same untyped-surface caveat applies as for `presentationEditor`, and the painted DOM carries no stability contract even where it currently answers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `onTransaction`                                                                        | `defineSuperDocExtension + ctx.onMutation`                   | Redesign      | The config typechecks and the editor mounts, and the callback never fires.                                                                                                                                                   | v2 has no transactions to hand back. Declare an extension and subscribe through its activation context: `ctx.onMutation({ origin, sourceComplete, affects }, handler)`. The filter is the point of the redesign, because a v1 handler had to inspect every transaction and decide whether it mattered.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `editor.chain().insertPageBreak().run()`                                               | `doc.create.paragraph + doc.format.paragraph.setFlowOptions` | Redesign      | A null-property error on `chain`, or `undefined` under optional chaining.                                                                                                                                                    | Not a behavioral equivalent, and the difference decides the port. v1 broke at the caret. v2 creates a paragraph at an address you supply and sets `pageBreakBefore` on it, which starts that paragraph on a new page rather than inserting a standalone break character. A mid-paragraph caret has no address of its own, so code that broke mid-paragraph must split the paragraph first or accept a block boundary. Await the creation: its returned address is the target of the formatting call. [Read more](/document-api/reference/format/paragraph/set-flow-options)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `doc.extract({}) / doc.getMarkdown({}) / doc.selection.current({}) read synchronously` | `the same operations, awaited`                               | Redesign      | The call returns a Promise where the code expected a value, so reads look empty and downstream property access yields `undefined`.                                                                                           | The v2 browser facade can route reads and mutations through a worker even when the underlying operation is synchronous in headless Node, so the same code is sync in one host and async in the other. Await browser calls, or normalize shared browser and headless code with `await Promise.resolve(call)`, and keep author overrides or other scoped state active until an awaited mutation settles. [Read more](/document-api/mental-model)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `ui.createScope().register(...)`                                                       | `superdoc.ui.commands.register`                              | Redesign      | A null-property error on `createScope`, or `undefined` under optional chaining.                                                                                                                                              | Register on the instance-owned controller: `superdoc.ui` is created once on first read and reused, and its type omits `destroy()` because the instance owns teardown. The registration result is callable and also exposes `unregister()`; keep either and call it on unmount. Command callbacks receive the public `doc`, `ui`, selection, and mode rather than ProseMirror command state, and the selection should be read from `context.selection`, which is synchronous and always present, not through the deep-partial `context.doc`. [Read more](/editor/custom-ui/custom-commands)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `editor.on('selectionUpdate')`                                                         | `superdoc.ui.selection.subscribe`                            | Redesign      | The subscription is accepted and the handler never fires.                                                                                                                                                                    | `subscribe` fires immediately and passes `{ snapshot }`; `observe` is the value-shaped alias. Both return an unsubscribe function, where v1 required a matching `off`. The payload is a public selection slice with document addresses, not a ProseMirror selection, so handlers that read positions have to be rewritten rather than rebound.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `trackedChange.authorColor`                                                            | `superdoc.ui.trackChanges.list`                              | Redesign      | Present on some rows and absent on others. Rows without it render `undefined` as a color, and nothing errors.                                                                                                                | Conditional rather than removed. The row projection passes the v2 tracked-changes facade fields through, so `list()` returns `authorColor` for rows whose host supplies one. It is not declared on `TrackChangeInfo`, so it is not part of the typed public surface and reading it means asserting the shape yourself. `trackChanges.authors` is flattened to `readonly string[]` and drops the per-author color the facade returns, so it is not the fallback either. Keep an application-owned default rather than assuming the field is there, and do not mutate the readonly slice arrays to add one. [Read more](/editor/custom-ui/tracked-changes)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `editor.view.dom.addEventListener('paste', ...)`                                       | `the element your application passed as the SuperDoc host`   | Redesign      | A null-property error on `view`, or `undefined` under optional chaining.                                                                                                                                                     | The capability survives as ordinary DOM work, but the element does not: v2 owns and re-paints its internal DOM, so attach the listener to the stable host element you passed to SuperDoc and remove it on unmount. A bubbling listener is enough when validation only needs `preventDefault()`. This guards browser input only; programmatic Document API mutations emit no DOM paste events.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

The editor internals are the harder half. v2 exposes `commands`, `state`, and `view` as `null` rather than removing them, so reading a property off one raises a generic null-property error that names your command and not SuperDoc. Optional chaining is worse: it turns the same mistake into a silent no-op that never errors at all.

Exact error wording varies by browser, bundler, and minifier. Treat the "What you see" column as symptoms to recognize, not as strings to match on.

## Before you start [#before-you-start]

Collaboration is not a configuration change. v2 rooms use a different document format, v2 owns the provider and `Y.Doc`, and a v2 editor must never be pointed at an existing v1 room. If your application uses collaboration, plan that migration separately before upgrading anything else.

Continue with the [v1 migration guide](/editor/migrate-from-v1/overview) for the full upgrade path, or the [Document API mental model](/document-api/mental-model) to understand what replaces direct editor access.
