Learn how to build a full payment system using the modern stack of Payload CMS, Next.js API Routes, and Lemon Squeezy, including a deep dive into debugging common API errors.
Integrating payments into an application can be a complex task, especially when you're working with a modern headless stack. How do you handle server-side logic securely when your CMS is embedded in a Next.js app?
In this guide (and the embedded video), we'll build a complete, production-ready payment system from start to finish using Payload CMS, Lemon Squeezy, and the power of Next.js API Routes.
The Architectural Shift: Why Next.js API Routes?
If you've used older versions of Payload, you might be familiar with creating custom endpoints directly within the CMS config. The game has changed. With Payload's deep integration into Next.js, the modern, recommended approach is to handle all custom server-side logic using Next.js API Routes.
This gives you:
- Seamless Integration: Your backend logic lives alongside your frontend code in a familiar structure (
/pages/api
or/app/api
). - Serverless-Ready: Perfectly aligns with deploying on serverless platforms like Vercel.
- Unified Tooling: No need to context-switch. You're in a Next.js environment from top to bottom.
The Full Video Tutorial
This video is a comprehensive walkthrough of the entire process. I cover everything from the initial setup to handling the final webhook confirmation.
What We'll Cover in the Video
I've structured the tutorial to be a step-by-step guide, covering every critical stage:
- โ Initial Setup: Configuring products in Lemon Squeezy and collections in Payload CMS.
- ๐จโ๐ป Building the Client: Creating a reusable client to communicate with the Lemon Squeezy API.
- ๐ Coding the API Routes: We'll build two key serverless functions in Next.js:
- A Checkout API Route to generate payment links.
- A Webhook Handler API Route to process order confirmations from Lemon Squeezy.
- ๐ Testing Locally: Using
ngrok
to expose our local API routes to the internet so Lemon Squeezy can send webhooks to our machine. - ๐ Real-World Debugging: I hit real errors during the recording, and I'll show you exactly how to fix them.
Don't Skip the Debugging Chapter!
Things rarely work perfectly the first time. Instead of editing it out, I dedicated a full chapter to troubleshooting the integration. We'll fix frustrating, real-world errors related to:
- Missing Store ID parameters.
- Incorrect custom data types (the classic string vs. number issue).
- Other common API request errors that can leave you stuck for hours.
Wrapping Up
By the end of this tutorial, you'll not only have a functional payment system but also a solid understanding of the modern architecture for building server-side logic with Payload CMS and Next.js.
I hope this helps you out! If you have any questions, drop a comment below or on the video. Happy coding!
๐ USEFUL RESOURCES
GitHub Repository: https://github.com/aaronksaunders/payload-lemon-1
Payload CMS Documentation: https://payloadcms.com/docs
Lemon Squeezy API Docs: https://docs.lemonsqueezy.com
ngrok Setup Guide: https://ngrok.com/docs
Source Code
aaronksaunders
/
payload-lemon-1
Payload CMS + LemonSqueezy Integration Example
Payload Lemon - E-commerce with Payload CMS & Lemon Squeezy
A modern e-commerce solution built with Payload CMS 3.x and Lemon Squeezy payment processing, featuring custom checkout creation and webhook handling.
๐ Features
- Payload CMS 3.x - Headless CMS with Next.js integration
- Lemon Squeezy Integration - Payment processing and checkout creation
- Custom API Routes - Next.js API routes for checkout and webhook handling
- TypeScript - Full type safety throughout the application
- SQLite Database - Local development with easy deployment options
- Webhook Support - Handle Lemon Squeezy order events
๐ Prerequisites
- Node.js 18.20.2 or higher
- pnpm 9 or higher
- Lemon Squeezy account
- ngrok account (for webhook testing)
๐ ๏ธ Installation
1. Clone and Install Dependencies
git clone <your-repo-url>
cd payload-lemon
pnpm install
2. Environment Setup
Create a .env.local
file in the project root:
# Payload CMS Configuration
PAYLOAD_SECRET=your-super-secret-payload-key-here
DATABASE_URI=file:./payload-lemon.db
# Lemon Squeezy Configuration
LEMON_SQUEEZY_API_KEY=your-lemon-squeezy-api-key
LEMON_SQUEEZY_STORE_ID=your-store-id
LEMON_SQUEEZY_WEBHOOK_SECRET=your-webhook-secret
# Next.js Configuration
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
โฆ
Top comments (0)