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

# Next.js Minimal Boilerplate

> Clone the Next.js minimal boilerplate to get a pricing page, checkout sessions, a webhook handler, and a Customer Portal link wired to Dodo Payments.

## Overview

The Next.js minimal boilerplate is a starter app with Dodo Payments already connected. Add your API keys and product IDs, and you get a pricing page that opens checkout, a webhook endpoint for payment events, and a link to the Customer Portal.

<Info>
  This boilerplate uses the Next.js 16 App Router with TypeScript, Tailwind CSS 4, and the `@dodopayments/nextjs` adaptor. To add the same route handlers to an existing app, see the [Next.js Adaptor](/developer-resources/nextjs-adaptor).
</Info>

### Features

The boilerplate includes:

* **Quick Setup**: Go from clone to a running pricing page in about five minutes.
* **Checkout**: A pre-configured checkout flow built on `@dodopayments/nextjs`.
* **Pricing Page**: A dark-themed pricing page styled with Tailwind CSS.
* **Webhook Handler**: An endpoint that verifies each webhook signature and runs your code for the event.
* **Customer Portal**: A header link that opens the Customer Portal, where customers manage their subscriptions.
* **TypeScript**: Typed product definitions and handlers.
* **Pre-filled Checkout**: Passes the customer's name and email to checkout, so the customer doesn't retype them.

## Prerequisites

Before you begin, you need:

* **Node.js 20.9 or later**, which Next.js 16 requires.
* **A Dodo Payments account**, to create an API key and a webhook signing secret in the dashboard.

## Quick Start

<Steps>
  <Step title="Clone the Repository">
    ```bash theme={null}
    git clone https://github.com/dodopayments/dodo-nextjs-minimal-boilerplate.git
    cd dodo-nextjs-minimal-boilerplate
    ```
  </Step>

  <Step title="Install Dependencies">
    ```bash theme={null}
    npm install
    ```
  </Step>

  <Step title="Get API Credentials">
    Sign up at [Dodo Payments](https://dodopayments.com/), then get your credentials from the dashboard:

    * **API Key:** Create a key under [Dashboard → Developer → API Keys](https://app.dodopayments.com/developer/api-keys).
    * **Webhook Key:** Add an endpoint under [Dashboard → Developer → Webhooks](https://app.dodopayments.com/developer/webhooks), then copy its signing secret. The endpoint URL must be public and use HTTPS. To receive events on your machine, see [Webhook Events](#webhook-events).

    <Tip>
      Create both while the **Live Mode** switch in the sidebar is off. A test mode key works only with `DODO_PAYMENTS_ENVIRONMENT=test_mode`, and test mode payments don't move real money.
    </Tip>
  </Step>

  <Step title="Configure Environment Variables">
    Copy the example file to create a `.env` file in the root directory:

    ```bash theme={null}
    cp .env.example .env
    ```

    Set the values to your Dodo Payments credentials:

    ```env theme={null}
    DODO_PAYMENTS_API_KEY=your_api_key_here
    DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_signing_key_here
    DODO_PAYMENTS_RETURN_URL=http://localhost:3000
    DODO_PAYMENTS_ENVIRONMENT=test_mode
    ```

    The route handlers read these variables:

    * `DODO_PAYMENTS_API_KEY` authenticates the checkout and Customer Portal handlers.
    * `DODO_PAYMENTS_WEBHOOK_KEY` verifies webhook signatures.
    * `DODO_PAYMENTS_RETURN_URL` is where checkout sends the customer after payment.
    * `DODO_PAYMENTS_ENVIRONMENT` is `test_mode` or `live_mode`.

    <Warning>
      Don't commit your `.env` file to version control. The repository's `.gitignore` already excludes it.
    </Warning>
  </Step>

  <Step title="Add Your Products">
    Replace the sample products in `src/lib/products.ts` with your own. Set each `product_id` to the ID of a product under **Products** in your dashboard:

    ```typescript theme={null}
    export const products: Product[] = [
      {
        product_id: "pdt_001", // Replace with your product ID
        name: "Basic Plan",
        description: "Get access to basic features and support",
        price: 9999, // in cents
        features: [
          "Access to basic features",
          "Email support",
          "1 Team member",
          "Basic analytics",
        ],
      },
      // ... add more products
    ];
    ```

    The pricing page displays `name`, `description`, `price`, and `features` from this file. Checkout charges the price set on the product in Dodo Payments, so keep `price` in sync with it.
  </Step>

  <Step title="Run the Development Server">
    ```bash theme={null}
    npm run dev
    ```

    Open [http://localhost:3000](http://localhost:3000) to see your pricing page.
  </Step>
</Steps>

## Project Structure

The checkout, Customer Portal, and webhook route handlers live under `src/app/api/`:

```text theme={null}
src/
├── app/
│   ├── api/
│   │   ├── checkout/          # Checkout session handler
│   │   ├── customer-portal/   # Customer portal redirect
│   │   └── webhook/           # Webhook event handler
│   ├── components/
│   │   ├── Footer.tsx         # Reusable footer
│   │   ├── Header.tsx         # Navigation header
│   │   └── ProductCard.tsx    # Product pricing card
│   ├── globals.css            # Global styles
│   ├── layout.tsx             # Root layout
│   └── page.tsx               # Pricing page (home)
└── lib/
    └── products.ts            # Product definitions
```

## Customization

### Update Product Information

Edit `src/lib/products.ts` to change:

* Product IDs, from **Products** in your Dodo Payments dashboard
* Prices
* Features
* Descriptions

### Pre-fill Customer Data

`src/app/components/ProductCard.tsx` sends a hardcoded name and email with each checkout request. Replace them with the signed-in user's details:

```typescript theme={null}
customer: {
  name: "John Doe",
  email: "john@example.com",
},
```

### Update Customer Portal

The **Customer Portal** link in `src/app/components/Header.tsx` opens `/api/customer-portal` with a hardcoded customer ID. Replace it with the signed-in user's Dodo Payments customer ID:

```typescript theme={null}
const CUSTOMER_ID = "cus_001"; // Replace with actual customer ID
```

To get a customer ID for testing, complete a test purchase, then copy the customer's ID from **Customers** in the dashboard. In production, fetch the ID from your backend.

## Webhook Events

The handler in `src/app/api/webhook/route.ts` verifies each request with `DODO_PAYMENTS_WEBHOOK_KEY`, then handles two events:

* `onSubscriptionActive` runs when a subscription becomes active (`subscription.active`).
* `onPaymentSucceeded` runs when a payment succeeds (`payment.succeeded`).

Add your business logic inside these handlers:

```typescript theme={null}
onSubscriptionActive: async (payload) => {
  // Grant access to your product
  // Update user database
  // Send welcome email
},
```

To handle more events, add their handlers, such as `onSubscriptionCancelled`. The [Next.js Adaptor](/developer-resources/nextjs-adaptor#supported-webhook-event-handlers) lists every supported handler.

Dodo Payments can't reach `localhost`. For local development, use a tunnel such as [ngrok](https://ngrok.com/) to expose your local server, and use the tunnel URL as your webhook endpoint.

## Deployment

### Build for Production

```bash theme={null}
npm run build
npm start
```

### Deploy to Vercel

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/dodopayments/dodo-nextjs-minimal-boilerplate)

Add the four environment variables in the Vercel dashboard, and set `DODO_PAYMENTS_RETURN_URL` to your production URL.

### Update Webhook URL

After deploying, add your production webhook URL in the [Dodo Payments Dashboard](https://app.dodopayments.com/developer/webhooks), with your domain in place of `example.com`:

```text theme={null}
https://example.com/api/webhook
```

Each endpoint has its own signing secret. Copy the new endpoint's secret into `DODO_PAYMENTS_WEBHOOK_KEY` in your production environment.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Module not found or build errors">
    Delete `node_modules` and `package-lock.json`, then reinstall dependencies:

    ```bash theme={null}
    rm -rf node_modules package-lock.json
    npm install
    ```
  </Accordion>

  <Accordion title="Checkout redirect fails">
    Check for these common causes:

    * The product ID doesn't exist in your Dodo Payments dashboard.
    * The API key or `DODO_PAYMENTS_ENVIRONMENT` in `.env` is wrong. A test mode key works only with `test_mode`.

    Look for the error in the browser console and in the terminal that runs `npm run dev`.
  </Accordion>

  <Accordion title="Webhooks not receiving events">
    For local testing, use [ngrok](https://ngrok.com) to expose your server:

    ```bash theme={null}
    ngrok http 3000
    ```

    In your [Dodo dashboard](https://app.dodopayments.com/developer/webhooks), add an endpoint with the ngrok HTTPS URL followed by `/api/webhook`. Copy that endpoint's signing secret into `DODO_PAYMENTS_WEBHOOK_KEY` in your `.env` file.
  </Accordion>

  <Accordion title="Customer portal link doesn't work">
    Replace the hardcoded `CUSTOMER_ID` in `src/app/components/Header.tsx` with the ID of a customer in your Dodo Payments dashboard.

    In production, get the customer ID from your authentication system and database instead.
  </Accordion>
</AccordionGroup>

## Learn More

* [Dodo Payments Documentation](https://docs.dodopayments.com/)
* [Checkout Sessions Documentation](https://docs.dodopayments.com/developer-resources/checkout-session)
* [Webhooks Documentation](https://docs.dodopayments.com/developer-resources/webhooks)
* [Next.js Adaptor](/developer-resources/nextjs-adaptor): options for the `Checkout`, `CustomerPortal`, and `Webhooks` handlers

## Support

For help with the boilerplate:

* Ask questions in the [Discord community](https://discord.gg/bYqAp4ayYh).
* Report issues and follow updates in the [GitHub repository](https://github.com/dodopayments/dodo-nextjs-minimal-boilerplate).
* Email the [support team](mailto:support@dodopayments.com).


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