Day 3 builds a production-ready Express chat server with session management, conversation history, and streaming — everything a real chat app needs.
Express Chat Server: Multi-User Conversations is one of the most important topics in JavaScript + AI APIs. This lesson builds the foundation you need before moving to more advanced concepts — take time with each example and run the code yourself.
import express from 'express';
import Anthropic from '@anthropic-ai/sdk';
import * as dotenv from 'dotenv';
import crypto from 'crypto';
dotenv.config();
const app = express();
const client = new Anthropic();
const sessions = new Map();
app.use(express.json());
app.use(express.static('public'));
// Create or retrieve session
app.post('/session', (req, res) => { const sessionId = crypto.randomUUID(); sessions.set(sessionId, { messages: [], createdAt: Date.now() }); res.json({ sessionId });
});
// Streaming chat endpoint
app.post('/chat', async (req, res) => { const { message, sessionId } = req.body; if (!sessions.has(sessionId)) { return res.status(400).json({ error: 'Invalid session' }); } const session = sessions.get(sessionId); session.messages.push({ role: 'user', content: message }); res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); let fullResponse = ''; try { const stream = await client.messages.stream({ model: 'claude-opus-4-5', max_tokens: 2048, system: 'You are a helpful assistant. Be clear and concise.', messages: session.messages }); for await (const chunk of stream) { if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') { fullResponse += chunk.delta.text; res.write(`data: ${JSON.stringify({ text: chunk.delta.text })}
`); } } session.messages.push({ role: 'assistant', content: fullResponse }); res.write('data: [DONE]
'); } catch (error) { res.write(`data: ${JSON.stringify({ error: error.message })}
`); } res.end();
});
// Clear session history
app.delete('/session/:id', (req, res) => { sessions.delete(req.params.id); res.json({ success: true });
});
// Cleanup old sessions every hour
setInterval(() => { const cutoff = Date.now() - 60 * 60 * 1000; for (const [id, session] of sessions.entries()) { if (session.createdAt < cutoff) sessions.delete(id); }
}, 60 * 60 * 1000);
app.listen(3000, () => console.log('Chat server on port 3000')); Before moving on, make sure you can answer these without looking: