Complete response to the 22-page feature audit. Every finding triaged, genuine bugs fixed, pushback where warranted.
mainRoot cause: The shadow DOM viewer was overwriting region content with stale data during Liveblocks sync, which reset the cursor position to the start of the contenteditable element.
Fix: Added a guard that compares incoming region content against the current DOM state before applying overwrites. If the region is actively being edited and the content hasn't meaningfully changed, the overwrite is skipped — preserving cursor position.
16f632apackages/editor/src/viewer/shadow-dom-viewer.tsxRoot cause: The structural undo handler intercepted Cmd+Z even when the user's most recent edit was character-level (typing or paste). It used a 30-second timeout heuristic: if the structural undo stack had any entries — even from a block operation done minutes ago — it would pop a stale snapshot and revert far more than the paste.
Fix: Replaced the timeout heuristic with a precise charEditsSinceStructuralRef flag. A new onInputActivity callback fires from every character-level input event. When the flag is set, Cmd+Z falls through to the browser's native undo, which correctly handles paste reversal. Structural ops reset the flag.
components/document-viewer.tsx, packages/editor/src/viewer/shadow-dom-viewer.tsxRoot cause: <DocumentToolbar /> was rendered without onUndo or onRedo props. The buttons appeared but did nothing on click. Keyboard shortcuts (Cmd+Z) worked separately through the shadow DOM viewer's keydown handler — the toolbar was just never connected.
Fix: Wired onUndo and onRedo callbacks that try structural undo/redo first, then fall back to document.execCommand('undo'/'redo') in the active contenteditable region for character-level edits.
components/document-viewer.tsxRoot cause: The comment resolution logic only allowed the comment author to resolve their own comments. Collaborators with edit access were blocked.
Fix: Updated the server action to allow any authenticated collaborator (with edit permissions) to resolve comments, not just the original author.
5fbf65dlib/actions/comments.tsRoot cause: Both Google Docs import and Generative AI creation used window.open() to open the resulting document. Ad blockers and browser settings silently block this, leaving users stranded.
Fix: Added popup-blocked detection. When the popup fails, an in-app fallback banner appears with a direct link to the new document. Users are never silently stuck.
0170ee8components/import-dialog.tsx, components/generate-ai-dialog.tsxRoot cause: In edit mode, contenteditable swallows normal link clicks. There was no tooltip or alternative interaction path for links.
Fix: Added a link tooltip on hover (showing the URL) and Cmd+click to open. Links also get proper visual styling (underline, color) to indicate they're interactive.
ae16850packages/editor/src/viewer/shadow-dom-viewer.tsxRoot cause: Portal elements created by the Docsmith panel weren't being cleaned up on unmount, leaving a small floating UI element visible in the corner.
Fix: Added proper cleanup in the panel's unmount lifecycle to remove all portal elements.
ad68f60components/chat/chat-panel.tsxRoot cause: The visual association between a comment and its highlighted text was minimal — no persistent background, no hover state linking them.
Fix: Strengthened the highlight with a persistent active background state on the text span associated with the selected comment. Hovering a comment in the panel highlights its text, and vice versa.
8fca5bfpackages/editor/src/viewer/shadow-dom-viewer.tsxRoot cause: The HTML validator threw an error and rejected the entire beautified output if the LLM included any <script>, <link rel="stylesheet">, <iframe>, <object>, or <embed> tags — even though the prompt already forbids them. LLMs don't always comply, especially when user instructions push toward interactivity ("form intake", "easy to copy paste").
Fix: Both validators (validateGeneratedHtml and validateGeneratedHtmlRich) now strip offending tags instead of throwing. The beautified HTML goes through with all its styling intact, minus the disallowed elements. Google Fonts links are still preserved in the rich variant.
lib/actions/documents.tsRoot cause: The inactive Docsmith icon was monochrome, blending in with other UI elements and reducing discoverability of the platform's flagship feature.
Fix: Added a subtle accent tint to the inactive icon so it stands out without being obnoxious. Active and inactive states are now visually distinct.
c339a31components/chat/chat-panel.tsxRoot cause: Email invitations and link-sharing controls were mixed together in one view. Users couldn't tell which permission (View/Edit) applied to which sharing method.
Fix: Added a visual divider and clear section labels ("Invite by email" / "Anyone with the link") to separate the two sharing mechanisms and their permission controls.
c973646components/share-dialog.tsxRoot cause: Long Supabase storage URLs were token-expensive for the LLM and easily dropped or mangled during the beautify/redesign transform.
Fix: New image preservation pipeline: images are extracted and replaced with short placeholders before the LLM call, then restored after. A safety net re-inserts any images still missing. Affects all callers: beautify, Google Docs/Slides import, PDF import, paste-to-document.
26f053clib/image-preservation.ts (new), lib/actions/documents.tsThe audit reports that content pasted from ChatGPT or Claude "can be difficult to edit." This is too vague to act on without a specific reproduction case. Paste behavior depends on the clipboard format (HTML vs. plain text), the source app's clipboard serialization, and how the block parser handles the incoming HTML. Need a specific paste source + content sample to debug.
The audit says heading transitions "do not behave as expected" and H2 doesn't reliably convert back to normal text. This likely involves the block type-convert logic in the toolbar. Need specific steps: which heading levels fail, in which direction, and whether it's a toolbar issue or a keyboard shortcut issue.
"Working in some cases but failing or behaving unpredictably in others." No specifics given. Could be related to block nesting, pasted content, or specific list-to-paragraph transitions. Need concrete steps to reproduce.
Too vague. Could be a CSS transform scaling issue, or the auditor may be confusing browser zoom with in-app zoom controls. Need to know which zoom levels fail and on which browser/OS.
The audit mentions that increasing/decreasing indentation introduces spacing changes that can't be fully reversed. This is likely a CSS margin/padding issue in the block model. Need to know: is this tab indentation, list nesting, or paragraph-level indent? Which toolbar action triggers it?
This is a design choice, not a deficit. The block-based architecture enables editable regions, targeted comments, Docsmith section awareness, and the new view-first mode. html-docs is a web publishing platform with AI — not a Google Docs clone. Chasing free-form editing parity would mean abandoning the structural model that powers every differentiating feature.
Same root cause as above — a known tradeoff of the region system. Bold/italic across multiple blocks could be added as a P2 convenience layer, but it's an architectural constraint, not a regression. Each region is independently editable and commentable; that's the whole point.
This is a third-party browser extension interacting with a custom contenteditable implementation inside a shadow DOM. Every non-standard editor (Notion, Figma, Coda, Linear) has this problem. Grammarly uses MutationObserver on the main document — shadow DOM boundaries break its assumptions. Not our bug to fix.
Multi-image layout (grid, side-by-side) is a feature request, not a bug. The current editor handles single images within blocks. A layout system for image grids would be a meaningful feature addition, but it's not a regression or a broken expectation — no promise of this exists in the product today.
5 of the 12 fixes touch packages/editor/ — the @html-docs/editor npm package. These changes are committed to main but won't reach production until the editor package is republished. Specifically:
onInputActivity callback)The other 8 fixes (comment permissions, popup handling, Docsmith cleanup, Docsmith icon, share dialog, beautify validation, undo/redo buttons, image preservation) deploy to Vercel automatically on the next build.
| Issue | Priority | Status | Commit |
|---|---|---|---|
| Cursor jumping during editing | P0 | Fixed | 16f632a |
| Undo/redo data loss on large paste | P0 | Fixed | 373eb6a |
| Undo/redo toolbar buttons broken | P0 | Fixed | 3050160 |
| Can't resolve others' comments | P0 | Fixed | 5fbf65d |
| Popup blockers break import/generate | P1 | Fixed | 0170ee8 |
| Dead hyperlinks in edit mode | P1 | Fixed | ae16850 |
| Docsmith UI remnant on close | P1 | Fixed | ad68f60 |
| Comment-to-text highlighting | P1 | Fixed | 8fca5bf |
| Beautify "unsupported resources" error | P1 | Fixed | 3c4519a |
| Docsmith icon discoverability | P2 | Fixed | c339a31 |
| Share dialog permission clarity | P2 | Fixed | c973646 |
| Images lost during beautify | P1 | Fixed | 26f053c |
| Pasted AI content hard to edit | — | Needs repro | — |
| Heading reversion (H2 → Normal) | — | Needs repro | — |
| Bullet point inconsistency | — | Needs repro | — |
| Zoom controls not reflecting changes | — | Needs repro | — |
| Indentation hard to reverse | — | Needs repro | — |
| Block-based editing learning curve | — | By design | — |
| Cross-block formatting | — | By design | — |
| Grammarly misalignment | — | Third-party | — |
| Image side-by-side layout | — | Feature request | — |