An original inspection note ends with a table of pressure readings. The technician needs a reliable place to type the next instruction below it. The product team chooses to keep a final paragraph in the saved note, even while that paragraph is still empty.
Make the final-node policy explicit
For an existing compatible Tiptap editor with paragraph support, add this configured extension once:
import { TrailingNode } from '@tiptap/extensions';
const inspectionEnding = TrailingNode.configure({
node: 'paragraph',
notAfter: ['paragraph']
});
Merge inspectionEnding into the application's current extension list. If another bundled extension already registers TrailingNode, configure that registration instead of adding a duplicate. Keep the table extension and the rest of the document schema.
The node option identifies the type inserted at the end. When it is omitted, current documentation describes a fallback chosen through the ProseMirror schema, usually the default block node. An explicit paragraph is clearer for this inspection-note policy, provided the custom document structure allows it there.
The default notAfter list contains paragraph. It prevents repeatedly adding another trailing paragraph merely because the document already ends in one. Replacing this list changes the policy; it does not append entries to the default automatically.
Decide whether a heading really counts as a finished ending
Suppose the note ends in a heading called “Follow-up action.” If you include heading in notAfter, the extension will not add the paragraph after that heading. That may be appropriate for another product, but it defeats this note's need for an immediate place to write the action.
Keep notAfter: ['paragraph'] for the inspection note so a final table or heading can receive a paragraph. Check the actual schema rather than assuming any node can follow any other node. A custom document requiring a particular final section may need a different allowed trailing type.
An empty paragraph is real model content. Include it in decisions about serialization, “empty document” indicators, and export. A blank line in the reader page can be a consequence of the product's chosen ending policy, rather than a mysterious editor decoration.
Distinguish a paragraph from a gap selection
A gap-cursor plugin offers a selection at eligible positions beside block nodes. It does not require storing a permanent empty paragraph after every final block. The ProseMirror gap-cursor guide covers that selection-based alternative.
For this inspection note, a stored final paragraph is deliberate: the technician can immediately enter “Retest after the seal change.” For a tightly structured document that should contain no unused final paragraph, investigate selection access and schema constraints before adding TrailingNode as a blanket fix.
Current TrailingNode also supports a transaction-specific skipTrailingNode metadata flag. Set it on the actual transaction that intentionally needs to avoid automatic insertion. An unrelated no-op transaction does not establish that a later document edit will be skipped.
Test the ending through editing and storage
In the running development editor, load a test note ending with a pressure-reading table. Inspect the resulting model and place the cursor in the following paragraph. Type the retest instruction and confirm it becomes ordinary text after the table.
Repeat with a note that already ends in a paragraph. It should not acquire an accumulating series of empty paragraphs under this configuration. Also exercise deleting the final paragraph, Undo, and the application's normal record-loading path: these operations can reveal when the insertion policy runs in the installed version.
Save and reopen the note through its actual storage route. Confirm that the readings remain in their original table and that the retest instruction remains below it. The Tiptap table guide covers maintaining the table itself. Finish by reading the instruction in the final reader view, where the editor's cursor and selection decorations are absent.