liveBook · Manning

Streamable UI component

As explained in Build AI-Enhanced Web Apps

A streamable UI is a React UI representation whose content can be incrementally replaced, appended, completed, or replaced with an error state.

A streamable UI component lets a React interface show server-generated content as it arrives. A server action can use `streamUI` to turn an LLM response into React nodes, then return its `value` for display in a client component. The response can appear and change without a page reload or polling. section 4.1.5

Choose `streamUI` when the model response drives the component: its `text` callback can render generated content in a chat bubble, while tool calls can produce more complex UI. Choose `createStreamableUI` when application code needs to control successive updates. Unlike `streamUI`, it does not call the LLM provider with a prompt. section 4.1.5 section 4.1.6

A `createStreamableUI` value supports four operations:

  • `update` replaces the current content; use it for a changing status or the latest accumulated response. section 4.1.6 section 6.1.2
  • `append` adds content, such as another completed step, without replacing earlier steps. section 4.1.6
  • `done` marks the stream complete; `error` handles a failure or displays an error component. section 4.1.6

Show progress during a server-side process

Create a streamable UI, call `update` with “Starting process…”, then `append` a message as each step finishes. Replace the progress messages with “Process complete!” and call `done`; call `error` if processing fails. Users see progress before the whole process finishes. section 4.1.6

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',
  };
}

For a streamed weather report, a LangChain chain fetches data and generates text. The server accumulates each output chunk, replaces a `ChatBubble` through `createStreamableUI`, then marks the UI stream complete. section 6.1.2

How Build AI-Enhanced Web Apps covers it

How deep it goes
Works through server actions, client rendering, four stream operations, and a chain integration; does not detail streaming internals.
Examples
Uses a streaming chat bubble, a two-step progress display, and a weather-report chain.
What it assumes
Assumes familiarity with React components and server actions while introducing the stream helpers through examples.
What you can do after
Apply it via the Vercel AI SDK to render incremental React updates and handle completion or errors.
How it connects
Connects React components and server actions with LLM responses, tool calls, conversation history, and LangChain.js streams.

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.