Skip to main content

fotoswipe-dual-license-e2e

FotoSwipe dual‑license commercialization playbook (end‑to‑end)

Audience: solo founder shipping a commercial widget fast, with clean architecture and low ops.

Principles (from .cursorrules)

  • Brand only in docs/marketing as "FotoSwipe"; keep npm names photoswipe (AGPL) and photoswipe-pro (commercial).
  • Pro features must be tree‑shakeable and license‑gated; local validation with offline grace; no hard phone‑home.
  • Provider‑agnostic, SOLID/DRY; depend on small interfaces; keep secrets server‑side.

TL;DR rollout

  • Day 0–1: Publish docs site Pro page, “Get License Key” CTA, trial flow scaffold. Ship license proxy and gate.
  • Day 2–3: Starter kits + 2 tutorials (AI alt text; ImageObject schema). Add pricing and licensing pages.
  • Day 4–7: Acceptance tests, signed releases, SBOM; pitch (Shopify/Woo/Next.js audiences).

Packaging & licensing

  • Community: photoswipe under AGPL. Commercial boundary enforced by LICENSE-commercial and docs/licensing.md.
  • Pro: photoswipe-pro distributed via private registry or ZIP. All Pro code behind a license gate.
  • Keep public APIs stable; additions are backward compatible; semver both packages.

Key files

  • LICENSE (AGPL), LICENSE-commercial, docs/licensing.md, docs/pricing.md.
  • Pro gate and provider:
    • src/pro/license.js (local gate + offline grace)
    • src/pro/license-remote.js (remote‑aware gate, instance caching)
    • src/pro/licensing/LemonSqueezyProvider.js (talks to your backend)
    • Server proxy: server/lemonsqueezy/router.js
  • Integration details: docs/lemon-squeezy-license-integration.md

Distribution

  • Community: publish to public npm (photoswipe).
  • Pro: ship to private npm (auth via license key) or GitHub Releases as ZIP.
  • Maintain release notes and checksums; optionally sign releases (cosign) and attach SBOM.

Trials & licensing UX

  • Trial: 7‑day key with local validation and offline grace; clear banner with days left.
  • Activation: paste key, optional email check; store instance_id and last_validation_ts.
  • Validation cadence: skip while in grace; after grace, validate via proxy with backoff; fail closed gracefully with clear messaging.

Backend proxy (Lemon Squeezy)

  • Endpoints: /api/license/{activate,validate,deactivate}; see server/lemonsqueezy/router.js.
  • Verify store_id and product/variant IDs; keep LEMON_SQUEEZY_* secrets server‑side only.
  • Docs: docs/lemon-squeezy-license-integration.md.

Docs/marketing

  • Pro landing: demo-docs-website/src/pages/pro.mdx with live demo and license panel (src/components/LicensePanel.js).
  • CTAs: “Get License Key” and “Start 7‑day Trial”.
  • Comparison (Free vs Pro) and quick starts for Shopify/Woo/Next.js.
  • SUPPORT.md for priority email support (Pro).
  • LICENSE-commercial terms (domains, seats, SLA for enterprise); keep copy congruent with docs.

QA & acceptance tests

  • Test licensed/unlicensed states: active/inactive/expired/disabled, offline grace, error paths, deactivation.
  • Mock provider to avoid external dependencies; fixtures for proxy responses.

Security & privacy

  • No secrets in the browser; no unsolicited telemetry. If enabled, anonymized and opt‑in.
  • Respect accessibility and SEO constraints; server‑render schema where applicable.

Release hygiene

  • Semver tags; changelog updates; signed artifacts and SBOM linked in releases.

What’s already in this repo

  • Gate and local validation: src/pro/license.js.
  • Remote‑aware gate and provider scaffold: src/pro/license-remote.js, src/pro/licensing/LemonSqueezyProvider.js.
  • Proxy router example: server/lemonsqueezy/router.js.
  • Docs site Pro page + license panel: demo-docs-website/src/pages/pro.mdx, demo-docs-website/src/components/LicensePanel.js.
  • Command reference: docs/commands.md.

Setup steps (end‑to‑end)

1) Install deps: npm install && cd demo-docs-website && npm install. 2) Configure env (server): LEMON_SQUEEZY_API_KEY, LEMON_SQUEEZY_STORE_ID, and product/variant ID. 3) Mount proxy under /api/license (Express or serverless) using server/lemonsqueezy/router.js. 4) Wrap Pro entry with withRemoteAwareGate and inject new LemonSqueezyProvider({ baseUrl: '/api/license' }). 5) Run everything: npm run watch (or npm run watch-js, npm run watch-css, and docs server on an open port). 6) Validate UX in /pro page: activate, validate, deactivate flows; verify mocked mode when backend is absent. 7) Publish pricing and licensing docs; wire CTAs on the Pro page.

Go‑to‑market checklist

  • Pricing and tiers finalized (docs/pricing.md), with license boundary copy in docs/licensing.md.
  • Landing with demo and CTAs live; announce via tutorials and starter kits.
  • Trial keys working end‑to‑end; email support configured.
  • Acceptance tests and release integrity (signing/SBOM) in place.