> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trycurious.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Server SDK examples

> Complete server SDK examples for Next.js, a Cloudflare Worker, a Supabase Edge Function and a Node job, each with a decision, an event and the right flush.

Each example reads the secret key from `CURIOUS_SECRET_KEY`, serves one decision with a fallback, reports one event, and hands the flush to the runtime so nothing is lost when it exits or freezes.

## Next.js (App Router)

```ts theme={null}
// lib/curious.ts
import { Curious } from "@trycurious/node";

export const curious = new Curious({ apiKey: process.env.CURIOUS_SECRET_KEY! });
```

```tsx theme={null}
// app/pricing/page.tsx
import { curious } from "@/lib/curious";
import { currentUser } from "@/lib/auth";

export default async function PricingPage() {
  const user = await currentUser();
  const hero = await curious.decide({
    element: "pricing_hero",
    userId: user?.id ?? anonymousIdFromCookie(),
    fallback: "Ship better experiments without manual analysis",
    attributes: user ? { plan: user.plan } : undefined,
    context: { page: "/pricing" },
  });

  return <h1>{hero.content}</h1>;
}
```

```ts theme={null}
// app/api/signup/route.ts
import { after } from "next/server";
import { curious } from "@/lib/curious";

export async function POST(request: Request) {
  const { userId, anonymousId } = await createAccount(request);
  await curious.identify({ userId, anonymousId });        // link before the next decision
  curious.track({ userId, name: "signed_up" });
  after(() => curious.flush());                           // deliver after the response
  return Response.json({ ok: true });
}
```

Decide in server components and route handlers, where the key is secret and the user's attributes are at hand. The page's own text is the natural fallback.

## Cloudflare Worker

```ts theme={null}
import { Curious } from "@trycurious/node";

export default {
  async fetch(request: Request, env: { CURIOUS_SECRET_KEY: string }, ctx: ExecutionContext) {
    const curious = new Curious({ apiKey: env.CURIOUS_SECRET_KEY });
    const userId = userIdFrom(request);

    const banner = await curious.decide({
      element: "upgrade_banner",
      userId,
      fallback: { headline: "Upgrade today", cta: "See plans" },
      context: { country: request.cf?.country },
    });

    curious.track({ userId, name: "upgrade_banner_viewed" });
    ctx.waitUntil(curious.flush());

    return Response.json(banner.content);
  },
};
```

Workers end when the response is sent; `ctx.waitUntil(curious.flush())` keeps the event delivery alive past it.

## Supabase Edge Function

```ts theme={null}
import { Curious } from "npm:@trycurious/node@0";

const curious = new Curious({ apiKey: Deno.env.get("CURIOUS_SECRET_KEY")! });

Deno.serve(async (req) => {
  const { userId } = await req.json();

  const decision = await curious.decide({
    element: "upgrade_prompt",
    userId,
    fallback: { headline: "Upgrade today" },
  });

  curious.track({ userId, name: "upgrade_prompt_viewed" });
  EdgeRuntime.waitUntil(curious.flush());

  return Response.json(decision.content);
});
```

Set the secret with `supabase secrets set CURIOUS_SECRET_KEY=…`. Pin an exact package version in production.

## A Node job

```ts theme={null}
import { Curious } from "@trycurious/node";

const curious = new Curious({ apiKey: process.env.CURIOUS_SECRET_KEY! });

for (const recipient of await dueRecipients()) {
  const subject = await curious.decide({
    element: "weekly_digest_subject",
    userId: recipient.id,
    fallback: "Your week in review",
    identifiers: { first_name: recipient.firstName },
    idempotencyKey: `digest_${runId}_${recipient.id}`, // a rerun replays, never re-decides
  });
  await sendEmail(recipient, subject.content);
}

await curious.flush(); // before the process exits
```

Server-initiated channels decide once per send, which is the natural exposure. The idempotency key makes a crashed-and-rerun job safe.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.