Challenge 4.2: Chat ID
How does your backend know which chat a new message belongs to?
OVERVIEW
Section titled “OVERVIEW”Every chat needs a unique ID. The frontend generates it when starting a new chat and sends it along with every request. The backend uses the ID to assign messages, load history, and manage sessions.
Without Chat ID: Every message is a new, anonymous request for your backend. There is no connection between “Hello” and the follow-up question “What do you mean by that?”. You cannot load history, resume a session, or build chat management.
With Chat ID: Every message belongs to an identifiable chat. You can load history, append new messages, manage multiple parallel chats, and offer the user a chat history.
WALKTHROUGH
Section titled “WALKTHROUGH”Layer 1: Generating a Chat ID
Section titled “Layer 1: Generating a Chat ID”A chat ID is a unique string. The standard: crypto.randomUUID() — generates a UUID v4:
// In the frontend: New chat ID at startconst chatId = crypto.randomUUID();// → "a1b2c3d4-e5f6-7890-abcd-ef1234567890"crypto.randomUUID() is available in Node.js (from v19) and all modern browsers. The probability of a collision is practically zero (2^122 possible values).
Layer 2: Sending the Chat ID in the Request
Section titled “Layer 2: Sending the Chat ID in the Request”The frontend sends the chat ID together with the messages to the backend:
// Frontend: Request to the APIconst response = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chatId, // ← Send chat ID along messages: [ { role: 'user', content: 'Was ist TypeScript?' }, ], }),});The chat ID stays the same for the entire conversation. New messages are sent with the same ID. A new chat gets a new ID.
Layer 3: Reading the Chat ID in the Backend
Section titled “Layer 3: Reading the Chat ID in the Backend”The backend extracts the chat ID from the request and uses it for assignment:
// Backend: API Handler (e.g. Express, Next.js Route Handler)async function handleChatRequest(req: Request): Promise<Response> { const { chatId, messages } = await req.json(); // ← Read chat ID
console.log(`Chat ${chatId}: ${messages.length} neue Message(s)`);
// Messages are now assigned to a chat // → Load history, append new messages, save return new Response(JSON.stringify({ chatId, status: 'ok' }));}Layer 4: Managing Multiple Chats
Section titled “Layer 4: Managing Multiple Chats”With chat IDs you can manage multiple parallel chats:
// Simulated chat managementconst chatSessions = new Map<string, Array<{ role: string; content: string }>>();
function getOrCreateChat(chatId: string) { if (!chatSessions.has(chatId)) { chatSessions.set(chatId, []); // ← New chat console.log(`Neuer Chat erstellt: ${chatId}`); } return chatSessions.get(chatId)!;}
function addMessage(chatId: string, role: string, content: string) { const chat = getOrCreateChat(chatId); chat.push({ role, content }); // ← Assign message console.log(`Chat ${chatId}: ${chat.length} Messages`);}
// Three different chatsconst chat1 = crypto.randomUUID();const chat2 = crypto.randomUUID();
addMessage(chat1, 'user', 'Was ist TypeScript?');addMessage(chat2, 'user', 'Erklaere mir React.');addMessage(chat1, 'user', 'Und worin unterscheidet es sich von JavaScript?');
// chat1 has 2 messages, chat2 has 1 message — cleanly separatedTask: Build a minimal API handler that reads chatId and messages from a request and logs them grouped by chat ID.
Create a file challenge-4-2.ts:
// Simulated "database"const chatStore = new Map<string, Array<{ role: string; content: string }>>();
// TODO 1: Write a function handleChat(chatId: string, messages: Array<{ role: string; content: string }>)// - If the chat doesn't exist yet: create a new entry in chatStore// - Append messages to the existing chat// - Log: Chat ID (truncated to 8 characters), number of new messages, total message count
// TODO 2: Simulate 3 requests:// - Chat A: User asks "Was ist TypeScript?"// - Chat B: User asks "Erklaere React."// - Chat A: User asks "Und was ist der Unterschied zu JavaScript?"
// TODO 3: Log the contents of chatStore — how many chats, how many messages per chat?Checklist:
-
handleChatfunction created - New chats are created automatically
- Messages are assigned to the correct chat
- Chat A has 2 messages, Chat B has 1 message
- Log shows chat ID and message count
Run with: npx tsx challenge-4-2.ts
Show solution
const chatStore = new Map<string, Array<{ role: string; content: string }>>();
function handleChat( chatId: string, messages: Array<{ role: string; content: string }>,) { if (!chatStore.has(chatId)) { chatStore.set(chatId, []); console.log(`Neuer Chat: ${chatId.substring(0, 8)}...`); }
const chat = chatStore.get(chatId)!; chat.push(...messages);
console.log( `Chat ${chatId.substring(0, 8)}...: +${messages.length} Message(s), gesamt: ${chat.length}`, );}
// Simulate 3 requestsconst chatA = crypto.randomUUID();const chatB = crypto.randomUUID();
handleChat(chatA, [{ role: 'user', content: 'Was ist TypeScript?' }]);handleChat(chatB, [{ role: 'user', content: 'Erklaere React.' }]);handleChat(chatA, [ { role: 'user', content: 'Und was ist der Unterschied zu JavaScript?' },]);
// Statusconsole.log(`\n--- Chat Store ---`);console.log(`Anzahl Chats: ${chatStore.size}`);for (const [id, messages] of chatStore) { console.log(`Chat ${id.substring(0, 8)}...: ${messages.length} Messages`);}Expected output (chat IDs will vary):
Neuer Chat: a1b2c3d4...Chat a1b2c3d4...: +1 Message(s), gesamt: 1Neuer Chat: e5f6a7b8...Chat e5f6a7b8...: +1 Message(s), gesamt: 1Chat a1b2c3d4...: +1 Message(s), gesamt: 2
--- Chat Store ---Anzahl Chats: 2Chat a1b2c3d4...: 2 MessagesChat e5f6a7b8...: 1 MessagesExplanation: crypto.randomUUID() generates unique IDs. The Map stores messages grouped by chat ID. By truncating the ID in the log, the output remains readable. Chat A has two messages, Chat B has one — cleanly separated.
COMBINE
Section titled “COMBINE”Exercise: Connect Chat ID with onFinish — save the assistant response in the onFinish callback, grouped by chat ID.
- Create a
chatStoreasMap<string, Array<{ role: string; content: string }>> - Write a
chatfunction that takeschatIdanduserMessage - Save the user message in the store
- Call
generateTextwith thechatStorehistory asmessages - In the
onFinishcallback: Save the assistant response in the store under the samechatId - Run 2 messages in the same chat and log the history
Optional Stretch Goal: Build a listChats() function that displays all chat IDs with creation date and message count.