> ## 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.

# Astro Minimal Boilerplate

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

## Overview

The Astro 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 Astro 5 with TypeScript, Tailwind CSS 4, and the `@dodopayments/astro` adaptor. To add the same API routes to an existing app, see the [Astro Adaptor](/developer-resources/astro-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/astro`.
* **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:

* **A Node.js LTS version**, which Astro 5 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-astro-minimal-boilerplate.git
    cd dodo-astro-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:4321/
    DODO_PAYMENTS_ENVIRONMENT=test_mode
    ```

    `.env.example` sets `DODO_PAYMENTS_RETURN_URL` to port `3000`. Change it to `4321`, the port the Astro dev server uses, so that checkout returns the customer to your app.

    The API routes read these variables:

    * `DODO_PAYMENTS_API_KEY` authenticates the checkout and Customer Portal routes.
    * `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:4321](http://localhost:4321) to see your pricing page.
  </Step>
</Steps>

## Project Structure

The checkout, Customer Portal, and webhook API routes live under `src/pages/api/`:

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

## 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

The checkout script in `src/components/ProductCard.astro` 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/components/Header.astro` opens `/api/customer-portal` with a hardcoded customer ID. Replace it with the customer ID from your authentication system or database:

```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.

## Webhook Events

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

* `onSubscriptionActive` runs when a subscription becomes active (`subscription.active`).
* `onSubscriptionCancelled` runs when a subscription is cancelled (`subscription.cancelled`).

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 `onPaymentSucceeded`. The [Astro Adaptor](/developer-resources/astro-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

Astro builds the pages as static output, and each API route sets `export const prerender = false` so that it renders on demand. On-demand routes need an Astro adapter for your deployment platform:

| Platform | Guide |
| - | - |
| Vercel | [Deploy to Vercel](https://docs.astro.build/en/guides/deploy/vercel/) |
| Netlify | [Deploy to Netlify](https://docs.astro.build/en/guides/deploy/netlify/) |
| Cloudflare | [Deploy to Cloudflare](https://docs.astro.build/en/guides/deploy/cloudflare/) |

For other platforms, see [Astro's deployment guides](https://docs.astro.build/en/guides/deploy/). In your hosting platform, add the four environment variables 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):

```text theme={null}
https://your-domain.com/api/webhook
```

Each endpoint has its own signing secret. Set `DODO_PAYMENTS_WEBHOOK_KEY` in your production environment to the signing secret of this endpoint.

## 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 4321
    ```

    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/components/Header.astro` 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>

  <Accordion title="Build fails with adapter error">
    The API routes render on demand, and the repository doesn't include a deployment adapter. Install the Astro adapter for your platform before you build for production.

    See [Astro's deployment guides](https://docs.astro.build/en/guides/deploy/) for details.
  </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)
* [Astro Adaptor](/developer-resources/astro-adaptor): options for the `Checkout`, `CustomerPortal`, and `Webhooks` handlers
* [Astro Documentation](https://docs.astro.build/)

## 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-astro-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.