Your application receives text from the model. Smoothstream presents the complete Markdown received so far. Pass a growing string and set receiving to true while more text may arrive, then set it to false when input ends.
The contract is shared by every framework: React uses children, Vue uses markdown, and the DOM adapter uses update().
Accumulate the incoming text
Each update includes the previous text:
Sending only "world" on the second update would replace the response. Within one instance, input must be append-only: the new string must start with the previous string. An identical snapshot is also valid.
Packet boundaries have no Markdown meaning. Whether your transport delivers "Hello " and "world", or "H" and "ello world", Smoothstream applies the same structural and pacing rules. A network pause can still delay content that has not arrived. Updates within a frame can be coalesced into the latest snapshot.
Close input and let presentation finish
receiving describes input, while mode describes presentation:
| Situation | receiving | mode |
|---|---|---|
| A live answer is arriving | true | "streaming" |
| Input has ended; the answer may still be revealing | false | Keep "streaming" |
| A complete string should play through the reveal | false | "streaming" |
| A stored answer should appear immediately | false | "static" |
The defaults are receiving={false} and mode="streaming".
An unchanged string might mean the network has paused, or that the answer is finished. Smoothstream cannot infer which. Closing input confirms the final word and any unfinished Markdown so the remaining content can be scheduled. It does not skip the reveal queue.
To show follow-up controls when the final unit appears, or wait until its entrance finishes, use the completion callbacks.
Connect a stream
This example assumes your backend returns raw UTF-8 text in the response body. It preserves characters split across network chunks and releases the reader when finished.
If you use SSE, WebSockets, or a model SDK, decode that protocol first and pass its text deltas through the same accumulation pattern. SSE event fields and JSON envelopes are not Markdown. If your SDK already supplies accumulated text, pass that string directly instead of appending it again.
Stop, retry, or edit an answer
The examples’ Stop buttons abort the network request, keep the text already received, and close input in finally. That partial answer is now treated as complete Markdown. A request error follows the same rendering lifecycle, with the error shown separately.
This stops receiving, not the queued visual reveal. There is no public pause, seek, or flush method. Removing the component or destroying the controller removes the response entirely.
A retry or regeneration needs a new response ID and a new instance. Editing earlier text also requires a new instance, even in static mode. Source positions identify already-scheduled content; changing that content in place would invalidate those identities.
Render chat history
Use static mode for messages that are already complete when they mount. For example, in React:
Keep the current response in its original mounted position after its request ends. Moving it into a different history subtree can remount it even if its key is unchanged. A message loaded as history on a later visit can mount in static mode immediately. Vue uses the same lifecycle with :key and mode="static"; the DOM adapter uses separate controllers.
Smoothstream renders one Markdown response. Your application owns the conversation layout, message controls, and scrolling. If you implement bottom following, observe changes to rendered content: the response can keep growing after the last network chunk, and images can load later.
Accessibility and next steps
Keep the Markdown subtree outside live regions such as role="log". Streaming instances provide their own completion announcement; see Accessibility for integration details.
- Markdown behavior explains why some content waits before appearing.
- Reveal and timing covers pacing and reduced motion.
- Troubleshooting covers missing tails, replay, and lifecycle errors.