The AI SDK core has no Next.js dependency. On Express you pipe the stream to the response; in scripts you iterate the stream directly.
Express:
import { convertToModelMessages, streamText } from 'ai';
app.post('/api/chat', async (req, res) => {
const { messages } = req.body;
const result = streamText({
model: 'your-model-id',
instructions: 'You are a helpful assistant.',
messages: await convertToModelMessages(messages),
abortSignal: req.signal,
});
result.pipeUIMessageStreamToResponse(res);
});
Plain Node script:
import { streamText } from 'ai';
const { textStream } = streamText({ model: 'your-model-id', prompt: 'Write a haiku.' });
for await (const textPart of textStream) {
process.stdout.write(textPart);
}
Checklist:
1. Install only ai (plus zod for tools and dotenv for keys): pnpm add ai zod dotenv, dev deps tsx and typescript to run it. No Next.js, no react package needed.
2. Keys come from environment variables (OPENAI_API_KEY etc.). Load them with dotenv in scripts; on servers use the platform env.
3. For a chat UI talking to Express, the frontend still uses useChat with DefaultChatTransport({ api: 'https://your-host/api/chat' }). The wire protocol is framework-agnostic.
4. Wrap streaming calls in try/catch. For simple text streams errors throw as regular errors; for UI message streams, handle 'error' parts on result.stream too.
5. Node 22+ is the documented baseline. Older Node versions lack the fetch/Response globals the SDK builds on.
6. If you need the full typed part stream (tool calls, reasoning, sources), iterate result.stream instead of textStream and switch on part.type.