Streaming Text Prediction
Simulates LLM streaming with real-time height prediction — smooth layout as tokens arrive.
When an LLM streams tokens, the container height is unknown until all text arrives. Without prediction, the container jumps on each new line. With Pretext, you can instantly compute the final height from the full text and show a 'ghost' container that smoothly converges to the actual height. This side-by-side comparison demonstrates the practical value of O(1) layout computation for streaming UIs.
prepare()layout() What this demonstrates
Practical height prediction for streaming text. The left panel shows the "traditional" approach where the container jumps on each new line. The right panel uses Pretext to predict the final height upfront, creating a smooth, non-jumpy experience.
Relevant Pretext API
prepare()— analyze text (both partial and full)layout()— compute height at any width instantly
Why this matters
LLM streaming UIs suffer from layout jank as new tokens arrive and create new lines. Pretext solves this by computing the final layout dimensions before all text has arrived, enabling pre-allocated containers that eliminate visual jumps.
Quick start
import { prepare, layout, buildFont } from '@chenglou/pretext';
// Setup: split the full LLM response into tokens (words)
const fullText = "The complete response that will stream in...";
const words = fullText.split(/\s+/);
const font = buildFont(15);
const lineHeight = 15 * 1.6;
const containerWidth = 500;
// KEY INSIGHT: prepare the full text once BEFORE streaming starts.
// prepare() is the expensive step, but layout() is pure arithmetic.
// So we can predict the final height before a single token arrives.
let preparedFull = prepare(fullText, font);
let predictedHeight = layout(preparedFull, containerWidth, lineHeight).height;
// Streaming loop: add tokens one by one
let currentWordIndex = 0;
const speed = 15; // tokens per second
function onNewToken() {
currentWordIndex++;
const currentText = words.slice(0, currentWordIndex).join(' ');
// Actual height of text so far (cheap — just prepare + layout)
const currentPrepared = prepare(currentText, font);
const currentHeight = layout(currentPrepared, containerWidth, lineHeight).height;
// Accuracy: how close is predicted to actual at this moment
const accuracy = Math.round(
(1 - Math.abs(predictedHeight - currentHeight) / predictedHeight) * 100
);
// WITHOUT PREDICTION: container height = currentHeight (jumps on each new line)
jumpyContainer.style.height = currentHeight + 'px';
// WITH PREDICTION: container pre-allocated to predictedHeight (no jumps)
smoothContainer.style.minHeight = predictedHeight + 'px';
// Ghost container: dashed border showing where the text will end up
ghostContainer.style.height = predictedHeight + 'px';
// opacity: 0.3, border: 2px dashed accent color
// The predicted height is 100% accurate once all tokens arrive,
// and starts at 100% before any text (empty = 0, predicted = final).
// In between, accuracy tracks how close the partial layout is to final.
}
// If containerWidth changes mid-stream, just re-call layout() on both:
// layout(preparedFull, newWidth, lineHeight) — still instant
// No need to re-prepare, which is what makes this approach practical