Deployment Guide — PhotoSwipe Pro with AI SEO
This guide explains how to deploy the complete revenue-generating system: payment checkout, license validation, and documentation site.
Architecture Overview
┌─────────────────────────────────────────────────┐
│ Frontend (Docusaurus) │
│ - Marketing pages (/pro, /checkout) │
│ - Documentation │
│ - Customer portal │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Backend API (Express) │
│ - /api/payment/* (checkout, products) │
│ - /api/license/* (activate, validate) │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ LemonSqueezy │
│ - Payment processing │
│ - License key generation │
│ - Customer management │
└─────────────────────────────────────────────────┘
Prerequisites
- LemonSqueezy Account — Sign up at https://lemonsqueezy.com
- Products Created — Site and Agency licenses configured with license keys
- Environment Variables — See Environment Configuration
Option 1: Deploy to Vercel (Recommended)
Vercel provides seamless deployment for both frontend and backend.
Step 1: Install Vercel CLI
npm i -g vercel
Step 2: Link Project
vercel link
Step 3: Set Environment Variables
vercel env add LEMON_SQUEEZY_API_KEY production
vercel env add LEMON_SQUEEZY_STORE_ID production
vercel env add LEMON_SQUEEZY_VARIANT_ID_SITE production
vercel env add LEMON_SQUEEZY_VARIANT_ID_AGENCY production
vercel env add LEMON_SQUEEZY_PRODUCT_ID production
Or via Vercel dashboard:
- Go to Project → Settings → Environment Variables
- Add all required variables for Production
- Redeploy
Step 4: Deploy
vercel --prod
Your site will be live at https://your-project.vercel.app
Step 5: Test
# Health checks
curl https://your-project.vercel.app/health
curl https://your-project.vercel.app/api/payment/health
curl https://your-project.vercel.app/api/license/health
Option 2: Deploy to Railway
Railway is great for full-stack apps with persistent backends.
Step 1: Install Railway CLI
npm i -g @railway/cli
railway login
Step 2: Initialize Project
railway init
Step 3: Set Environment Variables
railway variables set LEMON_SQUEEZY_API_KEY=your_key
railway variables set LEMON_SQUEEZY_STORE_ID=12345
railway variables set LEMON_SQUEEZY_VARIANT_ID_SITE=67890
railway variables set LEMON_SQUEEZY_VARIANT_ID_AGENCY=67891
railway variables set LEMON_SQUEEZY_PRODUCT_ID=your_product_id
Step 4: Deploy
railway up
Step 5: Get URL
railway domain
Option 3: Deploy to Fly.io
Fly.io offers global edge deployment with low latency.
Step 1: Install Fly CLI
curl -L https://fly.io/install.sh | sh
fly auth login
Step 2: Create App
fly launch
Step 3: Set Secrets
fly secrets set LEMON_SQUEEZY_API_KEY=your_key
fly secrets set LEMON_SQUEEZY_STORE_ID=12345
fly secrets set LEMON_SQUEEZY_VARIANT_ID_SITE=67890
fly secrets set LEMON_SQUEEZY_VARIANT_ID_AGENCY=67891
fly secrets set LEMON_SQUEEZY_PRODUCT_ID=your_product_id
Step 4: Deploy
fly deploy
Option 4: Self-Hosted (VPS/Cloud)
For full control, deploy to your own server.
Step 1: Install Dependencies
# On your server
git clone https://github.com/your-org/photoswipe-pro.git
cd photoswipe-pro
# Install backend deps
cd server
npm install
# Install frontend deps
cd ../demo-docs-website
npm install
npm run build
Step 2: Configure Environment
# Create .env in server/
cp .env.example .env
nano .env
# Add all required variables
Step 3: Set Up Process Manager
# Install PM2
npm i -g pm2
# Start backend
cd server
pm2 start index.js --name photoswipe-pro-api
# Serve frontend (use Nginx/Caddy)
Step 4: Configure Web Server
Nginx example:
server {
listen 80;
server_name photoflowseo.com;
# Frontend (static files)
root /var/www/photoswipe-pro/demo-docs-website/build;
index index.html;
# API proxy
location /api/ {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
}
Step 5: Set Up SSL
# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Get certificate
sudo certbot --nginx -d photoflowseo.com
Post-Deployment Checklist
1. Test Payment Flow
- Visit
/checkout - Click "Buy Now" on Site tier
- Complete test purchase (use LemonSqueezy test mode)
- Verify redirect to success page
- Check license key in email
2. Test License Validation
- Go to
/customer-portal - Enter test order ID
- Verify license key appears
- Copy key and test in demo
/propage - Verify AI SEO features unlock
3. Test API Endpoints
# Health checks
curl https://your-domain.com/health
curl https://your-domain.com/api/payment/health
curl https://your-domain.com/api/license/health
# Get products
curl https://your-domain.com/api/payment/products
# Create checkout (should return checkoutUrl)
curl -X POST https://your-domain.com/api/payment/checkout \
-H "Content-Type: application/json" \
-d '{"productId":"site"}'
4. Configure Monitoring
Set up error tracking and monitoring:
Sentry (recommended):
npm install @sentry/node
Add to server/index.js:
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
});
app.use(Sentry.Handlers.errorHandler());
Uptime monitoring:
- Use UptimeRobot, Pingdom, or Better Uptime
- Monitor
/healthendpoint every 5 minutes
5. Configure Analytics
Track conversions:
Google Analytics:
- Add GA4 to Docusaurus config
- Track
/checkoutpage views - Set up purchase event tracking
Plausible (privacy-friendly):
// In docusaurus.config.js
scripts: [
{
src: 'https://plausible.io/js/script.js',
'data-domain': 'photoflowseo.com',
defer: true,
},
],
6. Set Up Backups
Database backups (if using):
- Automated daily backups
- Store in S3/R2
Code backups:
- Git repository (already backed up)
- Tag releases:
git tag v1.0.0 && git push --tags
Troubleshooting
"Payment system not configured"
Problem: Backend can't connect to LemonSqueezy
Solution:
- Check environment variables are set
- Verify API key has correct permissions
- Test API key manually:
curl https://api.lemonsqueezy.com/v1/stores \
-H "Authorization: Bearer YOUR_API_KEY"
Checkout button does nothing
Problem: Frontend can't reach backend
Solution:
- Check browser console for errors
- Verify CORS is configured correctly
- Test backend endpoint directly:
curl -X POST https://your-domain.com/api/payment/checkout \
-H "Content-Type: application/json" \
-d '{"productId":"site"}'
License validation fails
Problem: License key format or validation logic issue
Solution:
- Verify license key format matches:
pswp_paid_XXXX - Check
/api/license/validateendpoint works - Test with a real key from LemonSqueezy
500 errors in production
Problem: Server error not caught properly
Solution:
- Check server logs:
pm2 logsorvercel logs - Enable debug mode temporarily:
DEBUG=* node server/index.js - Check all environment variables are set in production
Security Best Practices
- Never commit secrets — Use environment variables only
- Rotate API keys — Quarterly or if compromised
- Rate limit APIs — Prevent abuse (use express-rate-limit)
- Validate inputs — Never trust client data
- Use HTTPS — Always (free with Vercel/Certbot)
- Monitor logs — Set up alerts for unusual activity
Scaling Considerations
Current Setup (up to 1,000 customers)
- ✅ Serverless functions (Vercel/Railway)
- ✅ No database needed (LemonSqueezy stores everything)
- ✅ Simple deployment
Medium Scale (1,000–10,000 customers)
- Add Redis for caching product data
- Implement rate limiting
- Use CDN for static assets (Cloudflare)
Large Scale (10,000+ customers)
- Dedicated backend server (not serverless)
- Database for analytics
- Load balancer
- Separate license validation service
Next Steps
- ✅ Deploy to your chosen platform
- ✅ Test complete purchase flow
- ✅ Configure monitoring and analytics
- ✅ Set up custom domain
- ✅ Launch! 🚀
See also: