Fictitious cast-iron & camp kitchen shop demo with Ember, an Anthropic-powered product support agent.
- Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4
@anthropic-ai/sdk,zod,nanoid
npm install
cp .env.example .env.local
# Add your Anthropic key to .env.local
npm run devOpen http://localhost:3000.
| Variable | Required | Description |
|---|---|---|
ANTHROPIC_API_KEY |
Yes (for chat) | Anthropic API key. Without it, POST /api/chat returns 503 with { code: "config" }. |
POST /api/chat
Request
{
"messages": [
{ "role": "user", "content": "How do I season a skillet?" }
]
}Roles must be user or assistant only. Client system prompts are rejected.
Success (200)
{
"message": { "role": "assistant", "content": "…" },
"turnsRemaining": 5
}Errors
Customer-facing error strings steer shoppers back to product support (care, shipping, gear picks). Shape: { "error": string, "code": "…" }
| HTTP | code |
When |
|---|---|---|
| 400 | validation |
Bad JSON, empty/oversized messages, invalid roles, client system prompt |
| 429 | turn_limit |
Session used all 6 user turns |
| 429 | rate_limit |
IP exceeded request budget |
| 503 | config |
Missing ANTHROPIC_API_KEY |
| 502 | upstream |
Anthropic API failure / empty reply |
| Limit | Value |
|---|---|
| User turns / session | 6 (httpOnly cookie oe_chat_turns) |
| Message length | ~400 characters |
| Rate limit | ~8 requests / IP / 10 minutes (in-memory Map) |
| History | Capped to last 12 messages (turn budget × 2) |
| System prompt | Hard-coded on the server; client overrides ignored |
Client-side turn counters are UX only — these server checks are the real controls.
Caveats: The IP rate-limit Map is per-process and resets on cold starts or across multiple instances (fine for a local/demo deploy). Clearing cookies resets the turn counter; rate limiting still applies.
npm run dev # development
npm run build # production build
npm run start # serve production build