Live demo of the Whirlwind template, as shippedStripe test mode: card 4242 4242 4242 4242, any future date, any CVCGet Whirlwind →

AI Overview

AIClient: Claude, OpenAI and Gemini behind one interface, with pinned model IDs.

One client, three providers

lib/ai-client.js exports AIClient. It is server-only; never import it in a client component. - claude: Anthropic, default model claude-sonnet-5, override with ANTHROPIC_MODEL - openai: default gpt-5-mini, override with OPENAI_MODEL - gemini: Google through its OpenAI-compatible endpoint, default gemini-3.6-flash, override with GEMINI_MODEL

Usage

import AIClient from "@/lib/ai-client";

const ai = new AIClient("claude");   // "claude" | "openai" | "gemini"
const { text, usage } = await ai.chat(
  [{ role: "user", content: "Explain RLS in two sentences." }],
  { maxTokens: 300 },
);

Retired model IDs

Providers retire models on their own schedule, and a retired ID returns an error that looks like an auth failure. Model IDs are pinned in one place at the top of lib/ai-client.js and can be overridden per environment without a deploy. npm run doctor -- --deep sends a one-token request to every configured model so you find out before your users do.