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

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has multiple environments and each environment has its own API keys; start with Test.
> Templates and journeys can be built in the Courier app or created through the API; either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.

# Send notifications with Next.js

> Send from a Server Action and add a real-time in-app inbox to a Next.js App Router app.

The [Node.js quickstart](/docs/quickstarts/node) covers the calls themselves: create a user, send a notification, route it, start a journey. This page is the Next.js wiring around them. Where the Courier client lives in an App Router app, how to send from a Server Action, and how to add an in-app inbox that updates live, with the API key never leaving the server. It follows the [Next.js quickstart repo](https://github.com/trycourier/courier-nextjs-quickstart), which you can clone and run in about five minutes.

**What you need**

* The [Node.js quickstart](/docs/quickstarts/node) done, or at least a Courier API key in `COURIER_API_KEY` and a user in Courier.
* A Next.js App Router app on Node 20.9 or newer, with `@trycourier/courier` installed. Add `@trycourier/courier-react` for the inbox.

## 1. Send from a Server Action

`@trycourier/courier` is a server SDK and your API key is a server secret, so every Courier call belongs in a Server Action, a Route Handler, or a server component. `new Courier()` reads `COURIER_API_KEY` from the environment. The template lives in Design Studio, so the copy and the channel routing change without a deploy.

```typescript theme={null}
"use server";

import Courier from "@trycourier/courier";

const courier = new Courier();

export async function sendWelcome(userId: string, plan: string) {
  const { requestId } = await courier.send.message(
    {
      message: {
        template: "welcome",
        to: { user_id: userId },
        data: { plan },
      },
    },
    { idempotencyKey: `welcome-${userId}` }
  );

  return requestId;
}
```

## 2. Mint an inbox token in a Route Handler

The in-app inbox runs in the browser, so it needs a token that is safe to send there: a JWT scoped to one user and expiring, signed by your API key on the server. The repo does this in `app/api/courier/token/route.ts`, and reads the user id from the session rather than from the request, because a caller who can name any user can read that user's inbox.

```typescript theme={null}
// app/api/courier/token/route.ts
import Courier from "@trycourier/courier";

export async function GET() {
  // Read the user id from your own session (NextAuth, Clerk, Supabase, a cookie).
  // Never take it from the request.
  const userId = "sarah-bennett";

  const client = new Courier({ apiKey: process.env.COURIER_API_KEY });

  const { token } = await client.auth.issueToken({
    scope: `user_id:${userId} inbox:read:messages inbox:write:events`,
    // Always set this. Omitting it mints a token that never expires.
    expires_in: "1 day",
  });

  return Response.json({ userId, token });
}
```

## 3. Render the inbox as a client component

`<CourierInbox />` uses hooks and renders as a custom element, so it needs `"use client"`. It does not need `next/dynamic` with `ssr: false`. Sign in inside an effect, and guard it, because React runs effects twice in development and a second sign-in would sign the first user out.

```tsx theme={null}
// components/courier-inbox.tsx
"use client";

import { useEffect, useRef } from "react";
import { CourierInbox, useCourier } from "@trycourier/courier-react";

export function Inbox() {
  const courier = useCourier();
  const signedIn = useRef(false);

  useEffect(() => {
    if (signedIn.current) return;
    signedIn.current = true;

    fetch("/api/courier/token")
      .then((response) => response.json())
      .then((body) => courier.shared.signIn({ userId: body.userId, jwt: body.token }));
  }, [courier]);

  return <CourierInbox />;
}
```

Render `<Inbox />` in a page, then send to that user with the `inbox` channel. The message appears without a refresh.

## Next steps

* [Next.js quickstart repo](https://github.com/trycourier/courier-nextjs-quickstart): clone it, add a key, run `npm run dev` and `npm run send`.
* [Node.js quickstart](/docs/quickstarts/node): users, routing, journeys, delivery status.
* [In-app inbox](/docs/platform/inbox/inbox-overview): scopes, tenants, and the rest of the inbox.
* [Node.js SDK reference](/docs/sdk-libraries/node).
* [React SDK reference](/docs/sdk-libraries/courier-react-web).
