Document external DashCaddy billing architecture
This commit is contained in:
21
.env.example
21
.env.example
@@ -1,16 +1,7 @@
|
|||||||
# Stripe Configuration
|
# DashCaddy website configuration
|
||||||
# Get your keys from https://dashboard.stripe.com/apikeys
|
|
||||||
STRIPE_SECRET_KEY=sk_test_your_secret_key_here
|
|
||||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here
|
|
||||||
|
|
||||||
# Stripe Webhook Secret
|
|
||||||
# Get this from https://dashboard.stripe.com/webhooks after creating an endpoint
|
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
|
|
||||||
|
|
||||||
# Stripe Price IDs
|
|
||||||
# Create these in your Stripe Dashboard under Products > Pricing
|
|
||||||
STRIPE_PRICE_MONTHLY=price_your_monthly_price_id
|
|
||||||
STRIPE_PRICE_YEARLY=price_your_yearly_price_id
|
|
||||||
|
|
||||||
# App URL
|
|
||||||
NEXT_PUBLIC_APP_URL=https://dashcaddy.net
|
NEXT_PUBLIC_APP_URL=https://dashcaddy.net
|
||||||
|
NEXT_PUBLIC_LICENSE_SERVER_URL=https://licenses.dashcaddy.net
|
||||||
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_your_publishable_key_here
|
||||||
|
|
||||||
|
# The website no longer owns Stripe secret or webhook handling.
|
||||||
|
# Stripe Checkout sessions and webhook processing live in dashcaddy-license-server.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
| `CLAUDE.md` | Project instructions for Claude |
|
| `CLAUDE.md` | Project instructions for Claude |
|
||||||
| `FILELIST.md` | This file |
|
| `FILELIST.md` | This file |
|
||||||
| `README.md` | Project overview and setup guide |
|
| `README.md` | Project overview and setup guide |
|
||||||
| `STRIPE_SETUP.md` | Step-by-step Stripe configuration guide |
|
| `STRIPE_SETUP.md` | Billing architecture and license-server setup guide |
|
||||||
| `eslint.config.mjs` | ESLint configuration |
|
| `eslint.config.mjs` | ESLint configuration |
|
||||||
| `next-env.d.ts` | Next.js TypeScript declarations |
|
| `next-env.d.ts` | Next.js TypeScript declarations |
|
||||||
| `next.config.ts` | Next.js configuration |
|
| `next.config.ts` | Next.js configuration |
|
||||||
@@ -53,8 +53,8 @@
|
|||||||
|
|
||||||
| File | Endpoint | Purpose |
|
| File | Endpoint | Purpose |
|
||||||
|------|----------|---------|
|
|------|----------|---------|
|
||||||
| `src/app/api/checkout/route.ts` | `POST /api/checkout` | Creates Stripe Checkout session with 14-day trial |
|
| `src/app/api/checkout/route.ts` | `POST /api/checkout` | Disabled compatibility stub; production checkout lives in dashcaddy-license-server |
|
||||||
| `src/app/api/webhooks/stripe/route.ts` | `POST /api/webhooks/stripe` | Handles Stripe subscription lifecycle events |
|
| `src/app/api/webhooks/stripe/route.ts` | `POST /api/webhooks/stripe` | Disabled compatibility stub; production webhook lives in dashcaddy-license-server |
|
||||||
|
|
||||||
## Components (`src/components/`)
|
## Components (`src/components/`)
|
||||||
|
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ Open [http://localhost:3000](http://localhost:3000) to see the site.
|
|||||||
|
|
||||||
## Stripe Integration
|
## Stripe Integration
|
||||||
|
|
||||||
See [STRIPE_SETUP.md](./STRIPE_SETUP.md) for detailed setup instructions.
|
See [STRIPE_SETUP.md](./STRIPE_SETUP.md) for the current billing and license-server setup.
|
||||||
|
|
||||||
**API Routes:**
|
**API Routes:**
|
||||||
- `POST /api/checkout` - Creates Stripe Checkout session
|
- Website pricing uses the external DashCaddy license server for checkout initiation.
|
||||||
- `POST /api/webhooks/stripe` - Handles Stripe webhook events
|
- Website-local Stripe routes are disabled compatibility stubs and are not the production billing path.
|
||||||
|
|
||||||
## Logo Setup
|
## Logo Setup
|
||||||
|
|
||||||
|
|||||||
116
STRIPE_SETUP.md
116
STRIPE_SETUP.md
@@ -1,83 +1,65 @@
|
|||||||
# Stripe Setup Guide for DashCaddy.net
|
# DashCaddy Billing Setup
|
||||||
|
|
||||||
## 1. Create a Stripe Account
|
DashCaddy website no longer processes Stripe webhooks locally.
|
||||||
|
|
||||||
Go to [stripe.com](https://stripe.com) and create an account (or log in).
|
Current architecture:
|
||||||
|
- `dashcaddy.net` handles pricing UI and starts checkout by calling the external license server
|
||||||
|
- `dashcaddy-license-server` owns Stripe secret usage, webhook handling, subscription state, and license generation
|
||||||
|
- DashCaddy app instances validate/deactivate against the external license server
|
||||||
|
|
||||||
## 2. Create Your Product and Prices
|
## Required website environment
|
||||||
|
|
||||||
In the Stripe Dashboard:
|
```env
|
||||||
|
NEXT_PUBLIC_APP_URL=https://dashcaddy.net
|
||||||
|
NEXT_PUBLIC_LICENSE_SERVER_URL=https://licenses.dashcaddy.net
|
||||||
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_your_publishable_key_here
|
||||||
|
```
|
||||||
|
|
||||||
1. Go to **Products** > **Add Product**
|
## Required license server environment
|
||||||
2. Name: `DashCaddy Premium`
|
|
||||||
3. Description: `Premium license for DashCaddy - Self-hosting dashboard`
|
|
||||||
4. Create two prices:
|
|
||||||
- **Monthly**: $20.00 USD / month (recurring)
|
|
||||||
- **Yearly**: $99.00 USD / year (recurring)
|
|
||||||
5. Note down both **Price IDs** (they look like `price_1234...`)
|
|
||||||
|
|
||||||
## 3. Get Your API Keys
|
```env
|
||||||
|
PORT=3010
|
||||||
|
APP_BASE_URL=https://licenses.dashcaddy.net
|
||||||
|
DASHCADDY_WEBSITE_URL=https://dashcaddy.net
|
||||||
|
STRIPE_SECRET_KEY=sk_live_...
|
||||||
|
STRIPE_PUBLISHABLE_KEY=pk_live_...
|
||||||
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||||
|
```
|
||||||
|
|
||||||
1. Go to **Developers** > **API Keys**
|
## Stripe product model
|
||||||
2. Copy your **Publishable key** (`pk_test_...` or `pk_live_...`)
|
|
||||||
3. Copy your **Secret key** (`sk_test_...` or `sk_live_...`)
|
|
||||||
|
|
||||||
## 4. Set Up Webhooks
|
One Premium tier, four subscription cadences:
|
||||||
|
- 1 month — $25
|
||||||
|
- 3 months — $50
|
||||||
|
- 6 months — $65
|
||||||
|
- 12 months — $99
|
||||||
|
|
||||||
1. Go to **Developers** > **Webhooks**
|
No free trial.
|
||||||
2. Click **Add endpoint**
|
7-day grace period.
|
||||||
3. URL: `https://dashcaddy.net/api/webhooks/stripe`
|
Cancel at period end.
|
||||||
4. Select these events:
|
One active machine at a time.
|
||||||
|
Premium features only: `sso`, `recipes`, `swarm`.
|
||||||
|
|
||||||
|
## Stripe webhook target
|
||||||
|
|
||||||
|
Configure Stripe to send events to the license server, not the website.
|
||||||
|
|
||||||
|
Recommended webhook endpoint:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://licenses.dashcaddy.net/api/stripe/webhook
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended events:
|
||||||
- `checkout.session.completed`
|
- `checkout.session.completed`
|
||||||
|
- `customer.subscription.created`
|
||||||
- `customer.subscription.updated`
|
- `customer.subscription.updated`
|
||||||
- `customer.subscription.deleted`
|
- `customer.subscription.deleted`
|
||||||
- `invoice.payment_failed`
|
- `invoice.payment_failed`
|
||||||
5. Copy the **Webhook signing secret** (`whsec_...`)
|
|
||||||
|
|
||||||
## 5. Configure Environment Variables
|
## Website behavior
|
||||||
|
|
||||||
Copy `.env.example` to `.env.local` and fill in your values:
|
The website pricing page should start checkout via:
|
||||||
|
- `POST /api/checkout/session` on the external license server
|
||||||
|
|
||||||
```bash
|
The website-local routes under `src/app/api/checkout` and `src/app/api/webhooks/stripe` are intentionally disabled compatibility stubs and should not be used for production billing.
|
||||||
cp .env.example .env.local
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit `.env.local`:
|
|
||||||
|
|
||||||
```env
|
|
||||||
STRIPE_SECRET_KEY=sk_live_your_actual_secret_key
|
|
||||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_your_actual_publishable_key
|
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_actual_webhook_secret
|
|
||||||
STRIPE_PRICE_MONTHLY=price_your_monthly_price_id
|
|
||||||
STRIPE_PRICE_YEARLY=price_your_yearly_price_id
|
|
||||||
NEXT_PUBLIC_APP_URL=https://dashcaddy.net
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. Test with Stripe CLI (Optional)
|
|
||||||
|
|
||||||
For local development, use Stripe CLI to forward webhooks:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
stripe listen --forward-to localhost:3000/api/webhooks/stripe
|
|
||||||
```
|
|
||||||
|
|
||||||
Use test card `4242 4242 4242 4242` with any future date and any CVC.
|
|
||||||
|
|
||||||
## 7. License Key Delivery
|
|
||||||
|
|
||||||
The webhook handler at `src/app/api/webhooks/stripe/route.ts` has TODO comments
|
|
||||||
where you need to implement:
|
|
||||||
|
|
||||||
1. **Generate license key** using the same format as DashCaddy's license-keygen
|
|
||||||
(DC-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX)
|
|
||||||
2. **Store it** in a database (Stripe metadata can also hold it)
|
|
||||||
3. **Email it** to the customer (use Stripe's receipt email or a service like
|
|
||||||
SendGrid/Resend)
|
|
||||||
4. **Link it** to the Stripe subscription ID so you can manage renewals/cancellations
|
|
||||||
|
|
||||||
## Pricing Strategy Notes
|
|
||||||
|
|
||||||
- **Monthly ($20/mo)**: Positioned as the flexibility option
|
|
||||||
- **Yearly ($99/yr)**: ~$8.25/mo — 58% savings, this will be the primary seller
|
|
||||||
- **14-day free trial**: Enabled on both plans via `trial_period_days: 14`
|
|
||||||
- **Promotion codes**: Enabled via `allow_promotion_codes: true`
|
|
||||||
|
|||||||
Reference in New Issue
Block a user