Variants
One snippet in many frameworks, setups, and scenarios.
A snippet that comes in several forms declares dimensions, plus one entry in variants for each combination you show:
import { defineSnippet, p } from "@copybook/core";
export const chat = defineSnippet({
id: "ai-gateway.try-it.chat",
placements: ["console/ai-gateway/model"],
params: {
model: p.enum(MODELS).example("claude-haiku-5-5"),
token: p.secret({
env: "NEON_AI_GATEWAY_TOKEN",
placeholder: "<your-token>",
}),
},
dimensions: {
framework: [
{ value: "ai-sdk", label: "AI SDK" },
{ value: "python", label: "Python" },
{ value: "curl", label: "cURL" },
],
},
variants: [
{
when: { framework: "ai-sdk" },
lang: "ts",
deps: { npm: ["ai", "@neondatabase/ai-sdk-provider"] },
template: (t, { model }) => t`
const { text } = await generateText({ model: neon("${model}"), prompt: "Hi" });
`,
},
{
when: { framework: "curl" },
lang: "bash",
template: (t, { token }) => t`curl -H "Authorization: Bearer ${token}" …`,
},
],
});Options are an array of { value, label }, in display order. An array keeps that order even under lint rules that sort object keys.
Keys
Each variant gets a canonical key, with dimensions in declaration order: framework=ai-sdk, or framework=ai-sdk;setup=env when there are several dimensions. Select one when rendering, by key or by dimensions:
render(chat, values, { variant: { framework: "curl" } });
render(chat, values, { variant: "framework=curl" });Without a selection, the first variant renders. Matrices can be sparse: declare only the combinations you show.
Avoiding the matrix explosion
The Neon AI Gateway shows models × scenarios × frameworks. Model it like this:
- Model is a param, not a dimension. Only one string changes between models.
- Scenario and framework are dimensions. Their code really is different.
- Use a collection only when per-item content truly differs. See Collections.
That turns hundreds of near-copies into about 15 hand-written variants.
Dependencies
deps lists what a variant needs to run. The test runner installs these packages into its sandbox before typechecking or running the variant.