Command Palette

Search for a command to run...

Hectal
Phase 4Intermediate5 of 16 in AI Frontend

Conversation State

A chat is more than a string: messages with ids and stages, a reducer, resent history, saved chats, edits and branches, and the races that corrupt them.

Until now Mitra answered one question at a time. A real assistant holds a conversation: many messages, some still arriving, some failed, some edited, in several chats the user can switch between. This phase is about the data behind that screen, and about keeping it correct while streams, clicks and page loads all change it at once.

You will give every message an id and a stage, move every change through one reducer, work out what really gets sent to the model each turn (the whole history, trimmed to fit), save chats so they survive a reload, and handle edits, branches and the races that appear when two things happen at the same time.

Every example runs real browser code against a scripted stand-in model, so it needs no key and prints the same thing every time. The model side of context windows and memory is taught in /llm-engineering; this phase covers what the screen and the browser must do about it. By the end, Mitra remembers: it holds several saved chats, trims its history safely and survives a reload.

0/8 · 0%
8 topics ~4 h 18 code blocks & diagrams
Start with the first topic
1
4.1

The Message Model

A chat message is a small record: a unique id, a role, its content, a stage (waiting, streaming, done, failed, stopped) and a time. The id lets code and React find the right message while its text is still growing; the record you store is not the same as the shape you send to the model.

25 min 2 code practice

2
4.2

A Reducer for Chat

A reducer is one pure function that takes the current chat and an action (send, token, done, error, stop) and returns the next chat. Moving every change through it keeps one source of truth and makes impossible states, like two answers streaming at once, impossible to reach.

30 min 2 code practice

3
4.3

Sending History and the Context Window

A model remembers nothing between requests. Its "memory" is the conversation your client resends every time, so each request grows, costs more, and eventually hits the context window. You trim or summarise the old turns, and tell the user when the model can no longer see them.

30 min 3 code practice

4
4.4

Saving and Restoring Conversations

Chat state lives in memory and dies on reload. localStorage can keep it, but it is small, synchronous and string-only, it can fail or hold old, corrupt or foreign data, and two tabs can overwrite each other. Version what you save, validate what you load, and never restore a half-finished answer as if it were running.

32 min 3 code practice

5
4.5

Many Conversations

Users keep several chats. Each chat has its own messages and its own stage, a title made from its first question, and a place in a list. The hard part is a stream that is still running in one chat while the user opens, deletes or starts another: every token must land in the chat it was asked in.

28 min 2 code practice

6
4.6

Editing a Message and Branching

When a user edits an earlier question or asks for another answer, nothing should be destroyed. Store messages as a tree: an edit or a regenerated answer is a new sibling of the old one, the screen follows one path through the tree, and arrows let the user flip between versions.

27 min 2 code practice

7
4.7

Races and Double Submits

A race is two things happening at once whose order you don't control: two sends in a row, a stream finishing after the user moved on. The fixes are a guard that answers instantly (a ref), a request id or abort signal so stale pieces are ignored, and cancelling the old request.

26 min 2 code practice

8
4.8

Build: Mitra Remembers

Mitra becomes a real multi-turn assistant: a reducer holds each chat, every request sends a trimmed history, several chats are listed and can be switched while an answer streams, and the conversations are saved and survive a reload.

38 min 2 code practice

Practise this phase

Hands-on exercises: write the code, see your page live, and press Check to have it tested automatically.