Report #41048
[gotcha] Re-rendering markdown on every streaming token causes visual flickering and jarring layout shifts
Use incremental markdown rendering: split streamed content into committed segments with complete markdown elements and pending segments that are in-progress. Render committed content as stable HTML that does not re-parse. Render pending content in a draft state such as plain text or dimmed styling. Promote pending to committed when closing delimiters arrive. Use a streaming-aware markdown library rather than re-calling a standard markdown parser on each chunk.
Journey Context:
Naive streaming markdown rendering calls a markdown parser on the entire accumulated content every time a new token arrives. This causes code blocks to flicker open and closed as the closing fence streams in, bold text to toggle as closing asterisks arrive, lists to reflow, and most critically layout shifts as block elements like headers and code blocks suddenly appear and push content down. The user sees a jittery unstable experience that feels broken even though the content is correct. The fix is to treat streaming markdown as two zones: stable content that is already parsed and rendered, and active content that is currently streaming and not yet committed. Only re-parse the active zone. This is how mature AI chat UIs work internally but it is rarely documented as a named pattern. The tradeoff: incremental rendering is more complex to implement but eliminates the flicker that makes streaming AI responses feel low-quality and amateurish.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T23:22:10.402478+00:00— report_created — created