narev-nextjs-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNarev Next.js Patterns
Narev Next.js 实践模式
Use this skill when adding or reviewing Narev usage-based billing inside a Next.js App Router app, especially route handlers that call , , or another Vercel AI SDK method that reaches a provider API.
generateTextstreamTextFor raw Pricing API lookup and cost calculation, use . For committed pricing snapshots, use .
narev-lookup-llm-pricingnarev-update-llm-pricing当你在Next.js App Router应用中添加或审核基于Narev用量的计费功能时,可参考本实践,尤其是调用、或其他调用提供商API的Vercel AI SDK方法的路由处理器场景。
generateTextstreamText若需进行原始定价API查询和成本计算,请使用。若需提交定价快照,请使用。
narev-lookup-llm-pricingnarev-update-llm-pricingWhat Do You Need?
所需参考资料
| Task | Reference |
|---|---|
| Bill a Next.js route handler | references/api-routes.md |
| Pick provider middleware | references/provider-middleware.md |
| Resolve model prices with Narev | references/price-resolvers.md |
| Send usage to destinations and tag customers | references/destinations-and-tags.md |
| Production-safe setup | references/production-setup.md |
| Full-stack Polar integration (existing chatbot) | references/polar-integration.md |
| 任务 | 参考文档 |
|---|---|
| 为Next.js路由处理器实现计费 | references/api-routes.md |
| 选择提供商中间件 | references/provider-middleware.md |
| 通过Narev解析模型价格 | references/price-resolvers.md |
| 将用量数据发送至目标端并标记客户 | references/destinations-and-tags.md |
| 生产环境安全配置 | references/production-setup.md |
| 全栈Polar集成(现有聊天机器人) | references/polar-integration.md |
Mental Model
核心思路
Narev billing lives on the server, next to the AI provider call:
- Create the provider model with .
@ai-sdk/<provider> - Create a provider-specific middleware.
@ai-billing/<provider> - Give that middleware a when it needs live Narev rates.
createNarevPriceResolver() - Add one or more destinations, such as while developing or a billing destination in production.
consoleDestination() - Wrap the language model with before passing it to
wrapLanguageModel()orgenerateText.streamText - Add with stable customer, user, organization, chat, or plan identifiers.
providerOptions['ai-billing-tags']
Keep API keys, billing destinations, and wrapped model factories out of Client Components.
AI Gateway variant: When the app uses from the Vercel AI Gateway, substitute from in place of a provider-specific middleware. The Gateway already resolves per-token pricing, so no is needed. See for the complete end-to-end pattern including customer creation, rate limiting, cost streaming to the browser, and a usage dashboard.
gateway.languageModel()createGatewayV3Middleware@ai-billing/gatewaypriceResolverreferences/polar-integration.mdNarev计费逻辑部署在服务器端,与AI提供商的调用代码相邻:
- 使用创建提供商模型。
@ai-sdk/<provider> - 创建特定于提供商的中间件。
@ai-billing/<provider> - 当需要实时Narev费率时,为该中间件配置。
createNarevPriceResolver() - 添加一个或多个数据输出目标,比如开发阶段使用,生产阶段使用计费目标端。
consoleDestination() - 在将语言模型传入或
generateText之前,先用streamText进行包装。wrapLanguageModel() - 添加,传入稳定的客户、用户、组织、对话或套餐标识。
providerOptions['ai-billing-tags']
请勿将API密钥、计费目标端和包装后的模型工厂暴露在客户端组件中。
AI网关变体: 当应用使用Vercel AI Gateway的时,用中的替代特定于提供商的中间件。网关已内置每令牌定价解析,因此无需配置。如需完整的端到端模式(包括客户创建、速率限制、向浏览器流式传输成本以及用量仪表盘),请查看。
gateway.languageModel()@ai-billing/gatewaycreateGatewayV3MiddlewarepriceResolverreferences/polar-integration.mdMinimal Pattern
最简实践示例
typescript
import { createOpenAI } from '@ai-sdk/openai';
import { createOpenAIMiddleware } from '@ai-billing/openai';
import { consoleDestination, createNarevPriceResolver } from '@ai-billing/core';
import { convertToModelMessages, generateText, wrapLanguageModel } from 'ai';
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
const billingMiddleware = createOpenAIMiddleware({
destinations: [consoleDestination()],
priceResolver: createNarevPriceResolver({
apiKey: process.env.NAREV_API_KEY ?? '',
}),
});
export async function POST(request: Request) {
const { messages, userId } = await request.json();
const modelId = 'gpt-4o';
const result = await generateText({
model: wrapLanguageModel({
model: openai(modelId),
middleware: billingMiddleware,
}),
messages: await convertToModelMessages(messages),
providerOptions: {
'ai-billing-tags': {
userId,
modelId,
},
},
});
return Response.json(result);
}typescript
import { createOpenAI } from '@ai-sdk/openai';
import { createOpenAIMiddleware } from '@ai-billing/openai';
import { consoleDestination, createNarevPriceResolver } from '@ai-billing/core';
import { convertToModelMessages, generateText, wrapLanguageModel } from 'ai';
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
const billingMiddleware = createOpenAIMiddleware({
destinations: [consoleDestination()],
priceResolver: createNarevPriceResolver({
apiKey: process.env.NAREV_API_KEY ?? '',
}),
});
export async function POST(request: Request) {
const { messages, userId } = await request.json();
const modelId = 'gpt-4o';
const result = await generateText({
model: wrapLanguageModel({
model: openai(modelId),
middleware: billingMiddleware,
}),
messages: await convertToModelMessages(messages),
providerOptions: {
'ai-billing-tags': {
userId,
modelId,
},
},
});
return Response.json(result);
}Common Pitfalls
常见问题
| Symptom | Cause | Fix |
|---|---|---|
| Usage is not recorded | Raw provider model is passed to | Pass the |
| Secret leaks into browser bundle | Billing code imported by a Client Component | Keep billing setup in route handlers or server-only modules |
| Model cost is missing or wrong | No | Use the provider-specific middleware and |
| Usage cannot be attributed | Missing tags | Set |
| Tests fail or emit billing events | Middleware initialized during tests | Return the raw model in test environments |
| Cold starts do extra work | Middleware created inside every request | Cache middleware or wrapped-model helpers at module scope |
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 用量未被记录 | 原始提供商模型直接传入 | 传入 |
| 密钥泄露到浏览器包中 | 计费代码被客户端组件导入 | 将计费配置放在路由处理器或仅服务器端模块中 |
| 模型成本缺失或错误 | 未配置 | 使用特定于提供商的中间件和 |
| 用量无法归属 | 缺少标签 | 设置 |
| 测试失败或触发计费事件 | 测试期间初始化了中间件 | 在测试环境中返回原始模型 |
| 冷启动时额外耗时 | 每次请求都创建中间件 | 在模块级别缓存中间件或包装后的模型助手 |
Package Map
包映射
| Provider | AI SDK package | Billing package |
|---|---|---|
| OpenAI | | |
| Groq | | |
| Anthropic | | |
| | |
| Gateway | AI Gateway provider | |
| OpenRouter | | |
Use the middleware package that matches the model provider passed to the Vercel AI SDK. Do not share one provider's billing middleware with another provider's model.
Polar destination packages: When routing billing events to Polar, also install (destination adapter) and (Polar API client for customer management). For prebuilt usage dashboard UI, install .
@ai-billing/polar@polar-sh/sdk@ai-billing/nextjs| 提供商 | AI SDK包 | 计费包 |
|---|---|---|
| OpenAI | | |
| Groq | | |
| Anthropic | | |
| | |
| Gateway | AI Gateway provider | |
| OpenRouter | | |
请使用与传入Vercel AI SDK的模型提供商匹配的中间件包。请勿将一个提供商的计费中间件用于另一个提供商的模型。
Polar目标端包: 当将计费事件路由到Polar时,还需安装(目标端适配器)和(用于客户管理的Polar API客户端)。如需预构建的用量仪表盘UI,请安装。
@ai-billing/polar@polar-sh/sdk@ai-billing/nextjsSee Also
相关参考
- - Router for Narev Cloud, SDK, and billing questions
narev - - Public Pricing API reference
narev-lookup-llm-pricing - - Pin pricing snapshots into a repo
narev-update-llm-pricing
- - Narev Cloud、SDK和计费问题的路由工具
narev - - 公开定价API参考
narev-lookup-llm-pricing - - 将定价快照固定到代码仓库中
narev-update-llm-pricing