PhotoSwipe Pro - License Delivery & Distribution Setup Guide
Overview
This guide explains how to set up automated license delivery and Pro package distribution for paying customers.
✅ What's Implemented
1. License Delivery System
- ✅ Lemon Squeezy webhook handler (
/api/webhooks/lemonsqueezy) - ✅ Automated email delivery with license keys
- ✅ Beautiful HTML email template with installation instructions
- ✅ Download token generation for secure portal access
2. Pro Package Distribution
- ✅ Build script to create distributable
.tgzpackage - ✅ Secure download endpoint with license validation
- ✅ Customer portal for license management and downloads
- ✅ Version management and latest release API
3. Customer Experience
- ✅ Email with license key + download link
- ✅ Customer portal login (email + license key)
- ✅ One-click download of Pro package
- ✅ Installation guide links
- ✅ Support contact information
🔧 Setup Instructions
Step 1: Configure Environment Variables
Add these to your production environment (Vercel, Railway, etc.):
# Lemon Squeezy API
LEMON_SQUEEZY_API_KEY=your_ls_api_key_here
LEMON_SQUEEZY_STORE_ID=your_store_id
LEMON_SQUEEZY_PRODUCT_ID=your_product_id
LEMON_SQUEEZY_WEBHOOK_SECRET=your_webhook_secret
# Email Provider (Resend recommended)
EMAIL_PROVIDER=resend
RESEND_API_KEY=re_your_resend_key_here
# Download Security
DOWNLOAD_SECRET=generate_a_random_secret_here
# Site Configuration
SITE_URL=https://photoflowseo.com
ALLOWED_ORIGINS=https://photoflowseo.com,http://localhost:3001
# AI Provider (Optional - for demo/testing)
OPENROUTER_API_KEY=sk-or-v1-...
AI_MODEL=openai/gpt-4o-mini
Step 2: Set Up Lemon Squeezy Product
Create Product in Lemon Squeezy Dashboard:
- Name: "PhotoSwipe Pro - Site License"
- Price: $99/year
- Enable "License Keys" feature
- Set license key format:
pswp_prod_{random}
Configure Webhook:
- Go to Settings → Webhooks
- Add webhook URL:
https://your-domain.com/api/webhooks/lemonsqueezy - Select events:
order_created✅ (required for license delivery)subscription_createdsubscription_updatedsubscription_cancelledlicense_key_created
- Copy webhook secret and add to env as
LEMON_SQUEEZY_WEBHOOK_SECRET
Get API Credentials:
- Go to Settings → API
- Create new API key
- Copy and add to env as
LEMON_SQUEEZY_API_KEY - Note your Store ID and Product ID
Step 3: Set Up Email Provider (Resend)
Why Resend? Simple API, affordable ($20/mo for 100k emails), great deliverability
- Sign up: https://resend.com
- Verify your domain:
- Add DNS records for
photoflowseo.com - Wait for verification (usually instant)
- Add DNS records for
- Create API key:
- Go to API Keys → Create
- Copy key and add to env as
RESEND_API_KEY
- Set FROM address:
- Update webhook handler:
from: 'PhotoSwipe Pro <noreply@photoflowseo.com>'
- Update webhook handler:
Alternative: SendGrid, AWS SES, or any SMTP provider
Step 4: Build and Deploy Pro Package
# Build the Pro package
npm run build-pro
# This creates: /releases/photoswipe-pro-5.4.4.tgz
Deploy releases directory:
- Option A: Commit
releases/*.tgzto Git (simple, version-controlled) - Option B: Upload to S3/CDN (scalable, faster)
- Option C: Serve from Vercel static files
For Vercel, the releases/ directory is automatically served as static files.
Step 5: Test the Full Flow
Test Webhook Locally (Using Webhook.site)
- Go to https://webhook.site
- Copy your unique URL
- Configure Lemon Squeezy webhook to point to that URL temporarily
- Create a test order in Lemon Squeezy
- Verify webhook payload is received
- Update webhook URL to your production API
Test Email Delivery
# Start API server
PORT=4001 npm run api
# Simulate webhook event
curl -X POST http://localhost:4001/api/webhooks/lemonsqueezy \
-H 'Content-Type: application/json' \
-d '{
"meta": { "event_name": "order_created" },
"data": {
"attributes": {
"customer_email": "test@example.com",
"user_name": "Test Customer",
"order_number": "12345",
"first_order_item": {
"license_key": "pswp_prod_test123",
"product_name": "PhotoSwipe Pro - Site License"
},
"urls": { "receipt": "https://example.com/receipt" }
}
}
}'
Expected: Email sent to test@example.com with license key
Step 6: Test Download Flow
# Get latest version info
curl http://localhost:4001/api/download/latest
# Download with license key
curl -o photoswipe-pro.tgz "http://localhost:4001/api/download/download/5.4.4?key=pswp_prod_test123"
# Verify tarball
tar -tzf photoswipe-pro.tgz
Step 7: Test Customer Portal
- Go to http://localhost:3001/customer-portal
- Login with:
- Email: test@example.com
- License Key: pswp_prod_test123
- Verify you can see license info
- Click "Download v5.4.4"
- Verify
.tgzfile downloads successfully
🔄 End-to-End Customer Journey (Production)
1. Customer Purchases
Customer clicks "Buy Now" on /checkout
→ Lemon Squeezy checkout overlay opens
→ Customer enters payment info
→ Order completed
2. License Delivery (Automated)
Lemon Squeezy sends webhook to /api/webhooks/lemonsqueezy
→ Webhook handler verifies signature
→ Extracts license key from order
→ Sends email via Resend to customer
→ Email includes:
- License key: pswp_prod_abc123...
- Download link with secure token
- Installation instructions
- Support contact
3. Customer Receives Email
Subject: Your PhotoSwipe Pro License Key - Order #12345
Hi John Doe,
Thank you for purchasing PhotoSwipe Pro - Site License!
YOUR LICENSE KEY:
pswp_prod_abc123...
[Download PhotoSwipe Pro] [View Receipt]
Quick Start:
1. Download the Pro package
2. Install: npm install ./photoswipe-pro-5.4.4.tgz
3. Initialize with your license key
4. View full guide: https://photoflowseo.com/how-to-use-pro
4. Customer Downloads Package
Option A: From email link (has download token)
Click "Download PhotoSwipe Pro"
→ Redirects to customer portal with ?token=...
→ Auto-authenticated
→ Click "Download v5.4.4"
→ API validates token
→ Streams .tgz file
Option B: Manual portal login
Go to /customer-portal
→ Enter email + license key
→ Click "Access Portal"
→ See license details
→ Click "Download v5.4.4"
→ API validates license key
→ Streams .tgz file
5. Customer Installs
# Customer runs in their project
npm install ./photoswipe-pro-5.4.4.tgz
# Initialize
import { createAiSeoPlugin } from 'photoswipe-pro';
const aiPlugin = createAiSeoPlugin({
licenseKey: 'pswp_prod_abc123...',
baseUrl: '/api/ai'
});
6. License Validation
On first use:
→ Plugin reads license key
→ Validates locally (format, not expired)
→ Shows 14-day grace period
→ Makes remote validation call (optional)
→ Pro features enabled ✅
📧 Email Templates
Purchase Confirmation Email
Location: server/lemonsqueezy/webhook.js
Template includes:
- ✅ License key (formatted, easy to copy)
- ✅ Download button with secure token
- ✅ Receipt link
- ✅ Quick start guide (3-4 steps)
- ✅ What's included list
- ✅ Support links
- ✅ Order number
Customization:
Edit the emailHtml constant in sendLicenseEmail() function.
🔒 Security Features
Webhook Security
- ✅ HMAC signature verification (SHA-256)
- ✅ Timing-safe comparison to prevent timing attacks
- ✅ Environment-based secret configuration
Download Security
- ✅ License key validation before download
- ✅ Time-limited download tokens
- ✅ Rate limiting on API endpoints
- ✅ No direct file access (streamed through API)
Email Security
- ✅ No sensitive data in URLs (except signed tokens)
- ✅ HTTPS-only links in production
- ✅ SPF/DKIM verification via Resend
🚀 Deployment Checklist
Before Going Live:
- Set all environment variables in production
- Configure Lemon Squeezy webhook to production URL
- Verify email domain in Resend
- Test webhook with real Lemon Squeezy test mode purchase
- Verify email is sent and received
- Test download with real license key
- Verify customer portal loads and works
- Check all links in email template point to production URLs
- Set up monitoring/logging (Sentry, Datadog)
- Test with different email providers (Gmail, Outlook, etc.)
Post-Launch Monitoring:
- Monitor webhook endpoint for failures
- Check email deliverability (open rates, bounces)
- Track download metrics
- Monitor license validation API usage
- Set up alerts for errors
🐛 Troubleshooting
Webhook Not Firing
Symptoms: Customer pays but doesn't receive email
Fixes:
- Check Lemon Squeezy webhook logs
- Verify webhook URL is correct (https, no typos)
- Check webhook signature verification
- Look at server logs for errors
- Test with ngrok for local debugging:
ngrok http 4001
# Use ngrok URL in LS webhook temporarily
Email Not Sending
Symptoms: Webhook fires but email doesn't arrive
Fixes:
- Check
EMAIL_PROVIDERenv var is set toresend - Verify
RESEND_API_KEYis correct - Check Resend dashboard for delivery status
- Verify domain is verified in Resend
- Check spam folder
- Look at server logs for email errors
Download Fails
Symptoms: Customer clicks download, gets 404 or 403
Fixes:
- Verify
releases/directory exists with.tgzfile - Check license validation is working
- Verify environment variables are set
- Test download endpoint directly with curl
- Check file permissions on server
License Validation Fails
Symptoms: Customer has valid key but can't use Pro features
Fixes:
- Check
LEMON_SQUEEZY_API_KEYis set correctly - Verify license key format matches (
pswp_prod_*) - Test validation endpoint directly
- Check Lemon Squeezy dashboard for license status
- Verify store ID and product ID match
📊 Metrics to Track
Email Metrics (via Resend)
- Delivery rate
- Open rate
- Click-through rate (download button)
- Bounce rate
Download Metrics
- Total downloads per license
- Version distribution
- Download failures
Support Metrics
- "Can't find license key" tickets
- "Download failed" tickets
- "License invalid" tickets
🔄 Updating the Pro Package
When You Release a New Version:
# 1. Update version in root package.json
npm version 5.5.0
# 2. Build new Pro package
npm run build-pro
# 3. Commit and push
git add releases/photoswipe-pro-5.5.0.tgz
git commit -m "Release PhotoSwipe Pro v5.5.0"
git push
# 4. Deploy to production
vercel --prod
# 5. Email existing customers (optional)
# Use Resend broadcast or Lemon Squeezy customer emails
Existing license keys automatically work with new versions!
💡 Future Enhancements
Short-term:
- Add license usage analytics (how many sites using each key)
- Implement domain-based activation limits
- Add "forgot license key" recovery flow
- Create admin dashboard for license management
Long-term:
- Self-service license transfer between domains
- Upgrade/downgrade flows (Site → Agency)
- License pooling for Agency customers
- Automatic update notifications
✅ Status
License Delivery: ✅ Fully implemented
Pro Package Distribution: ✅ Fully implemented
Customer Portal: ✅ Fully implemented
Email Templates: ✅ Fully implemented
Download Security: ✅ Fully implemented
Ready for production: ⚠️ After Lemon Squeezy + Resend configuration
📞 Need Help?
If you encounter issues during setup:
- Check server logs for errors
- Test each component individually
- Use mock mode for development
- Contact support@photoflowseo.com