Skip to content

prd: web preview for large posts #4

@leandronsp

Description

@leandronsp

Date: 2026-04-11
Status: Draft

Problem

Writers drafting long-form posts in DevTUI lose their live web preview the moment the article grows past a certain length. The embedded Chrome preview silently clips, showing blank space or a truncated render, while short posts render fine. The breakage is invisible until the writer scrolls and wonders where the content went. Long-form is exactly the use case that benefits most from a real browser preview, and exactly the case where it currently fails.

Background

DevTUI's web preview renders the published HTML of a post inside the terminal by launching headless Chrome, capturing a screenshot of the page, and drawing that screenshot directly in the terminal via the Kitty graphics protocol (with tmux passthrough). It is bound to Ctrl+P, triggers on :w, and today feels fast: fast typing is debounced, stale sends are discarded, and the preview updates on save within a couple of hundred milliseconds.

The feature was hard to build. It crosses four stacks: headless Chrome subprocess, HTML generation from markdown, the Kitty image protocol, and tmux escape-sequence passthrough. It works well for posts up to roughly the height of a terminal viewport scaled a few times. Beyond that, large posts render but the bottom is lost. The writer sees a clean image that is a lie: the end of the article simply is not there.

The speed budget is non-negotiable. Whatever fix we ship must not slow down the save-to-preview cycle for small and medium posts, which is the common case.

Requirements

Must Have

  • Writers can preview posts of any realistic length (a 30k-word long-form article) in the embedded web preview without clipping or missing content.
  • The end of the rendered post is reachable via the existing Ctrl+J / Ctrl+K scroll controls.
  • The save-to-first-pixel latency for short and medium posts stays within the current feel. No visible regression.
  • The tmux passthrough path keeps working.
  • When the writer is editing at a given line in vim, scrolling the preview follows the cursor ratio as it does today.

Should Have

  • A visible indicator if the preview is still rendering the tail of a very large post, so the writer knows the scroll will reach more content.
  • Graceful fallback if a post is pathologically large (e.g. a 200k-word dump): render what we can, warn the writer, never crash.

Out of Scope

  • Switching away from Chrome as the rendering engine.
  • Replacing the Kitty graphics protocol with an alternative (sixel, iTerm inline images).
  • Live-as-you-type preview. Save-triggered refresh stays.
  • Interactive preview (clicks, form input, JS debugging). This is a read-only render.
  • A second HTTP server or network dependency for the preview pipeline.

Constraints

  • The Kitty graphics protocol image-scroll mechanism has a fixed upper bound on how many terminal rows a single image can address. Long posts exceed this limit, which is the direct cause of the clipping. Any fix must work within or around this limit.
  • Chrome is launched with a fixed window height today. The capture path must adapt to the actual content height of the rendered post.
  • The writer's environment may or may not be inside tmux. Both must keep working.
  • We cannot block the TUI event loop during rendering. Chrome work must stay on its background thread.
  • We inherit the "speed first" philosophy of the project. Removing complexity is preferred over adding it.

Acceptance Criteria

Rendering a long post

  • Given a post that renders to a page taller than the current clipping threshold, when the writer saves, then the preview shows the full post with no missing tail.
  • Given a post of 30,000 words with images and code blocks, when the writer saves, then the preview completes and is scrollable end to end.
  • Given a post that is shorter than one viewport, when the writer saves, then the preview updates at the same perceived speed as today.

Scrolling

  • Given a long post is previewed, when the writer presses Ctrl+J repeatedly, then the preview scrolls through the entire post and reaches the last line of content.
  • Given the writer moves the vim cursor to the bottom of the source, when the preview refreshes, then the preview is scrolled near the bottom of the rendered output.

Speed

  • Given a typical blog post (1,000 to 3,000 words), when the writer saves, then the time from :w to the first visible preview update is not slower than the current implementation.
  • Given the writer saves repeatedly in quick succession, when renders pile up, then only the latest render is shown and intermediate work is discarded, as today.

tmux

  • Given DevTUI runs inside tmux, when the writer previews a long post, then the image renders correctly with no visible escape-sequence leakage.

Failure modes

  • Given Chrome fails or crashes mid-render, when the writer saves, then the preview pane shows a clear error and the editor keeps working.
  • Given a post is pathologically large, when the writer saves, then the preview either renders a truncated view with a visible warning or falls back to the text preview, but never hangs the TUI.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1: highHigh priorityprdProduct Requirements Document

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions