# Next.js

Use Plandalf in client-rendered parts of your Next.js app. Load the organization SDK with `next/script`, render normal React buttons with Plandalf attributes, and keep identity or API work on the server.

> [!NOTE]
> **The SDK runs in the browser**
> Checkout buttons, inline mounts, and promo widgets are browser behavior. Server routes are useful for signing identity tokens or creating backend records, not for opening checkout frames.

## The path

1.  Load the SDK after hydration

    Use `next/script` with `afterInteractive` in your root layout or the route that contains checkout.

2.  Render one client-side buying action

    Start with a normal button that has `data-plandalf-present`.

3.  Move identity to the server

    If checkout should know the logged-in customer, sign a JWT in a route handler or server action, then pass it to a client component.

4.  Test mode before live traffic

    Add `data-plandalf-mode="test"` or call `present()` with `{ mode: "test" }` while validating the route.

## App Router setup

<scalar-tabs default="layout.tsx">
<scalar-tab title="layout.tsx">

```tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <Script
          src="https://acme.plandalf.dev/js/plandalf-sdk.js"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
```

</scalar-tab>
<scalar-tab title="BuyButton.tsx">

```tsx
"use client";

export function BuyButton() {
  return (
    <button
      data-plandalf-present="pro-plan"
      data-plandalf-frame="slideout"
      data-plandalf-mode="test"
    >
      Buy Pro
    </button>
  );
}
```

</scalar-tab>
<scalar-tab title="identity.ts">

```ts
// Application-owned server helper; see the JWT signing guide below.
export async function createPlandalfIdentity(user: {
  id: string;
  email: string;
}) {
  return signPlandalfJwt({
    external_id: user.id,
    email: user.email
  });
}
```

</scalar-tab>
</scalar-tabs>

## Programmatic checkout

Use direct SDK calls when a click needs app logic before checkout opens.

```tsx
"use client";

export function UpgradeButton({ userJwt }: { userJwt?: string }) {
  async function upgrade() {
    const flow = plandalf.present("pro-plan", {
      user: userJwt,
      frame: "modal",
      mode: "test"
    });

    for await (const event of flow.events) {
      console.log(event.type);
    }

    await flow;
  }

  return <button onClick={upgrade}>Upgrade</button>;
}
```

Next.js boundaries

- `Server routes` (API keys and JWT signing): Keep API credentials and identity signing off the browser.

- `Client components` (checkout UI): Render buttons, inline checkout containers, and SDK method calls from browser code.

- `Environment` (test | live | preview): Use test mode before you expose the route to real buyers.

## Related docs

- [Identify customers](https://plandalf.com/docs/sdk/identify) — Pass server-signed identity into browser checkout.

- [React SDK](https://plandalf.com/docs/packages/react) — Use provider and hooks when your app should manage SDK state through React.

- [Live events](https://plandalf.com/docs/packages/sdk/interfaces/FlowEvent) — Listen to FlowHandle events after checkout opens.

Source: https://plandalf.com/docs/product-guides/platforms/nextjs
