liveBook · Manning

createStreamableUI

As explained in Build AI-Enhanced Web Apps

createStreamableUI is a Vercel AI SDK helper function that creates a streamable user-interface value whose contents can be updated incrementally.

`createStreamableUI` creates a streamable React UI value that server-side code can change as work progresses. It does not call an LLM provider itself. Use it when a server action or another stream produces updates that should appear immediately in the client. section 4.1.6 section 6.1.2

The returned object controls the UI stream:

  • `update(content)` replaces the current content. section 4.1.6
  • `append(content)` adds content to what is already shown. section 4.1.6
  • `done()` marks the stream complete; `error(error)` handles a streaming failure. section 4.1.6

Show progress through a two-step process

Create the stream, show an initial message, then append each completed step. Replace the progress messages with a final result and close the stream. Handle failures rather than leaving the UI waiting: ```jsx const ui = createStreamableUI(); ui.update(<p>Starting process...</p>); try { await firstStep(); ui.append(<p>Step 1 complete</p>); await secondStep(); ui.append(<p>Step 2 complete</p>); ui.update(<p>Process complete!</p>); ui.done(); } catch (error) { ui.error(error); } return ui; ``` `firstStep` and `secondStep` stand for the application’s asynchronous work. section 4.1.6

For a LangChain.js workflow, call `chain.stream()`, create the UI stream, and iterate over the chain’s results. Accumulate response text and pass an updated React component to `update()` for each result; call `done()` when iteration finishes. This separates chain execution from rendering because `streamUI` cannot directly use the LangChain.js chain in this integration. section 6.1.2

Listing 6.4 Integrating the chain into the conversation chain
export async function getChainStream(city) {
  const chain = RunnableLambda.from(fetchWeatherData) #1
                              .pipe(promptTemplate)
                              .pipe(llm)
                              .pipe(new StringOutputParser());

  const stream = await chain.stream({ city });    #2
  return stream;
}

export async function continueConversation(input) {
  const aiState = getMutableAIState();
  const stream = createStreamableUI();    #3

  stream.update(<div>Processing your request...</div>);
  const aiResponseStream = await getChainStream(input);
  let textContent = '';
  for await (const item of aiResponseStream) {    #4
    textContent += item;
    stream.update(<ChatBubble role="assistant" 
text={textContent} className={`mr-auto border-none`} />);
  }
  stream.done();
  aiState.done({    #5
    ...aiState.get(),
    messages: [
      ...aiState.get().messages,
      {
        id: generateId(),
        role: 'assistant',
        content: textContent,
      },
    ],
  });

  return {
    id: generateId(),
    display: stream.value,
    role: 'assistant',
  };
}

The listing connects a weather-data chain to a conversation handler: each streamed item updates the assistant chat bubble, followed by stream completion. section 6.1.2

How Build AI-Enhanced Web Apps covers it

How deep it goes
Explains update, append, done, and error with a two-step example, then wires updates to a chain stream without detailing transport internals.
Examples
Uses a two-step progress display and a weather-data chain that updates an assistant chat bubble.
What it assumes
Assumes familiarity with React components and server-side actions; introduces the stream object's update methods explicitly.
What you can do after
Apply it via the Vercel AI SDK to show partial results, complete a UI stream, and handle failures.
How it connects
Connects React components and server actions to streamUI, LangChain.js chains, and AI state.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build AI-Enhanced Web Apps. The section links point to the parts of the book it draws on.