payments · tutorial · webhooks
Sell Digital Goods in 60 Seconds Flat
Files, licenses, checkout, delivery: the digital marketplace pattern on one product table plus Dodo. No platform cut. Inside.

Gumroad takes 10% to host a link
The first template sold through a marketplace: 10% plus processing taken, payouts held for weeks, customer relationship owned by the platform (buyers "theirs," rented access to own fans), fee terms changed twice in a year. Their rules, their cut, their customer list — the product merely supplied.
The math at 200 sales × $199: $3,980 to the platform for hosting files and sending emails. A weekend of wiring replaces it permanently — product table, checkout, delivery links, license checks. Same buyer experience, zero rent.
Nextjs marketplace digital products isn't a platform. It's four tables and one checkout — owned outright, paying nobody per sale but the rail's base fee.
Marketplace vs owned storefront
| Sale of $199 template | Marketplace (10%) | Owned (Dodo rail fee) |
|---|---|---|
| Platform cut | ~$19.90 | $0 |
| Payout timing | Weeks held | Scheduled, predictable |
| Customer data | Theirs (rented access) | Yours (rows + emails) |
| Fee changes | Imposed yearly | None (your code) |
| 200 sales total kept | ~$36k | ~$39k+ |
| Branding | Their chrome | Your domain, fully |
Three details make platforms expensive beyond percentages:
- Customer ownership is the real product. Marketplace buyers belong to the marketplace (upsells, emails, relationships flow through them). Owned checkout captures emails into your rows — launch-two sells to launch-one buyers free. Audience compounds for owners, resets for renters.
- Fee terms move one direction. Every marketplace raises takes yearly (reported across all of them, verify current before committing) — locked-in sellers absorb or migrate painfully. Owned rails change fees only when you switch providers (config line, rehearsed). Rent hikes require your signature when you own the store.
- Delivery is the easy 10%. Files plus licenses plus download links — weekend work with presigned URLs (the R2 pattern) and license rows. Platforms charge premium percentages for commodity plumbing. Pay for plumbing once (build it), never per sale.
The lifetime-deal post priced the offer. This one builds the store around it.
Nextjs marketplace digital products pattern
Products table, Dodo checkout, presigned delivery — sixty seconds click-to-download.
Step 1 — Model products, orders, licenses as three rows.
create table if not exists "products" (
"id" text primary key, "name" text, "amountCents" integer,
"fileKey" text, "version" text default '1.0'); -- file lives on R2
create table if not exists "licenses" (
"id" text primary key, "orderId" text, "userId" text,
"productId" text, "downloads" integer default 0); -- per-buyer grantPrice in products (checkout quotes it, webhook charges it, receipt prints it — one truth). Licenses separate from orders (refunds revoke licenses without deleting history; upgrades add licenses without new orders). Files on R2 keyed by product (version bumps swap keys, old buyers keep old keys working). Three tables, total commerce.
Step 2 — Checkout once through Dodo, grant via webhook.
// webhook: dedupe on dodo_payment_id → create order → create license → email receipt
// delivery email carries: download link (presigned, 24h) + license key + version notesHosted checkout (zero card code, global methods), idempotent webhook (exactly-once orders, the billing law), license auto-created (access without manual fulfillment). Sixty seconds click-to-download, fulfilled by code while you sleep. Manual license emails are the prehistory this pattern deletes.
Step 3 — Deliver presigned, version honestly.
# downloads: presigned R2 GETs (24h expiry, per-license checks: downloads < cap?)
# versions: v2 as NEW product row (old buyers keep v1 access; upgrade price optional)
# piracy posture: generous (some sharing inevitable) + per-seat team pricing (convert sharers)Presigned links expire (shared links die in a day — casual piracy taxed without DRM wars). Versions as products (v1 owners buy v2 deliberately — recurring revenue without subscriptions). Team tiers convert sharing into sales (per-seat pricing beats license police). Generosity plus structure beats DRM hostility, in revenue and in sleep.
That's the shape of it — storefronts that sell while you sleep.
Platform vs owned, 200 sales
| $199 template × 200 | Marketplace 10% | Owned Dodo |
|---|---|---|
| Gross | $39,800 | $39,800 |
| Platform cut | ~$3,980 | $0 |
| Payout wait | Weeks held | Scheduled |
| Customer list | Rented | Owned (200 emails) |
| Launch-two marketing | From zero (again) | Free (email list) |
| Build cost | $0 + 10% forever | One weekend, once |
No use pretending otherwise: owned storefronts need the weekend build (checkout, webhooks, delivery, receipts — real work, tested per drill) plus ongoing ownership (refund handling, download support, receipt questions). Priced against $3,980 per 200 sales plus audience rent forever: build once, keep customers, sleep the same. Platforms sell convenience; ownership sells the business itself.
FAQ
Is nextjs marketplace digital products overkill vs LemonSqueezy stores?
LemonSqueezy's hosted stores cover simple cases well (product pages, checkout, delivery basics) — use them when catalog is tiny and customization unneeded. Owned wins at: custom licensing (seats, versions, upgrades), buyer-data depth (joins with app usage), and fee sensitivity (volume justifying the weekend). Hosted for experiments, owned for businesses. Graduate deliberately.
How do refunds work without a marketplace mediating?
Directly and generously: refund webhook revokes license (same transaction), confirmation email apologizes humanly, 30-day window published. Refund rates run lower owned (deliberate purchases, clear scope) than marketplaced (impulse, fuzzy). Generous refunds convert disputes into trust (reviewers mention them); stingy ones convert customers into chargebacks.
What stops buyers sharing download links publicly?
Expiry (24h presigned links die fast), license checks (downloads counted per license, anomalies flagged), team pricing (sharers convert to buyers at per-seat rates). Determined piracy always wins (screenshots exist) — optimize for honest-buyer experience, not pirate-proofing. Friction punishes buyers; pirates bypass everything. Serve the honest generously.
Should marketplace and SaaS share one codebase?
Yes at solo scale (products + subscriptions behind one paywall boolean, shared auth/users, unified admin): one deploy, one database, one ops burden. Split when catalogs diverge operationally (separate teams, distinct compliance, different scale curves). Monolith first (this entire philosophy), services on evidence. One repo until reality objects.
How are versions and updates delivered to buyers?
Version rows (v1, v2 as products), buyer emails on release ( Resend, segmented by owned-version), download center (all owned versions, one login). Update emails are marketing gold (past buyers convert highest on v2). Owned lists make releases launches; marketplace dependence makes them announcements into voids. Launch to owners, not strangers.
When does a marketplace make sense despite the cut?
Discovery-dependent products (unknown creators needing foot traffic), zero-engineering teams (no weekend available, ever), and compliance-heavy categories (marketplace absorbs tax/regulatory surface). Pay the cut while discovery matters, migrate when audience compounds past it. Rent discovery, own retention — sequencing beats ideology.
Keep reading
- Sell Lifetime Deals on Next.js: $199 Beats $15/mo — the pricing this store serves
- Next.js + Dodo $199 Once: Beat $15/mo Forever — the checkout adapter underneath
- 500MB Uploads, 0 Server RAM: R2 Presigned — the delivery pattern files ride
+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)
Command from your phone.
Built so autonomous AI agents build what you want without breaking what's already paying you.
- Built-in analytics — cookie-free mode, $0 forever, no PostHog bill
- SQLite ↔ Supabase: one setting, same field names
- Full digital marketplace & feedback boards included
- 3 payment rails: Stripe, LemonSqueezy & Dodo Payments
- Agent fences: lint gate, read-only data access, auto-rollback
- Ship from your phone via SSH & WireGuard/Tailscale in under a minute
$199
Get BoringPushOne-time payment · Lifetime updates · Unlimited projects.
Keep reading


