docs: purge the dead $29/$49 + Polar model from every tracked file, add the Y1 forecast
The pricing ruling landed twice (2026-09-21 one-time, then 2026-09-27 Store IAP $10/mo + $400 lifetime) and the map never caught up. Six tracked files still told a future session that billing was Polar and the price was $29/$49. A stale memory map is worse than a stale comment: it is the file every session trusts, and this one was actively steering work toward a deleted provider. MONETIZATION.md (gitignored, so not in this commit) was rebuilt first: - "Revenue projections" now carries a modelled Year 1 forecast — pessimistic $4.0K / base $15.4K / optimistic $53.3K net, ~$22K weighted. Funnel is installs -> 35-45% activate -> 1.5-3% of active users pay. - Three findings recorded: Year 1 is ~97% lifetime transactions (subs net $392 of $15.4K, so MRR is not a Year-1 planning input); conversion dominates price (~1pp of conversion = ~$7K net, and ADA 6(h) locks $10 anyway); subscriber churn moves Year 1 by under $200 and is a Year-2 problem. - Break-even restated for $400: $25K net = 74 lifetime buyers, not 862. The price cut the volume requirement ~10x and raised the skill requirement to match. - Market sizing willingness-to-pay row rewritten. The 100K-400K TAM was price-bound to $29-49 and is wrong at $400; revised ~20K-60K, flagged as an estimate rather than a sourced number. - Flagged a real contradiction: $500K ARR needs ~4,900 concurrent subscribers, so the Exit section's ARR multiples do not describe what Years 1-3 produce. The defensible asset there is lifetime cash flow, not ARR. Tracked files corrected to match: - ai.md: paid-delta, pricing and billing bullets rewritten; Polar product id, org id, LCYT- key prefix and LLAMAFOUNDER/LLAMA50 marked as deleted; 15% share + net-after-tax recorded with the ADA 6(b)(i) citation. - TASKS.md: catalog row retitled as a teardown; the "still to verify — the price is not decided" note closed (it contradicted the ruling 20 lines below it); the OverlayHost "Polar unlocks alerts" open question marked resolved; Polar file-hosting deliverable removed from the release build. - task-10: reframed as a teardown. Steps 4-5 marked as surviving, 1-2-3-6-7 as deleting, 8 as a compliance action (Velopack downloads AND executes, which Store policy 10.2.2 does not permit). - task-36 item 5 (license-expiry reminders) struck — no key, no expiry, no lapse under Store IAP, so there is nothing to remind anyone about. - Distribution.md 4.2 / 4.4 / 4.5 marked obsolete; 4.5's "already implemented" corrected, since PolarLicenseService is being deleted rather than shipped. - README: "one-time license" -> "paid tier". Historical Polar sections are retained deliberately — the reasoning is reusable (merchant-of-record, fee comparison), only the conclusions are dead. Each is now labelled so it cannot be mistaken for the plan. No code touched.
This commit is contained in:
@@ -1,12 +1,36 @@
|
||||
# TASK 10 — Monetization: watermark-only one-time license + Polar billing
|
||||
# TASK 10 — Monetization: watermark-only paid delta (branding flash)
|
||||
|
||||
> Catalog: [`TASKS.md`](../TASKS.md) — status and requirements live here.
|
||||
|
||||
**Goal:** a **paid tier that removes the branding flash and nothing else.** Every feature is free
|
||||
— Alerts, social bar slots, voice filters, TRAX, recording, analytics. The free tier is the *full*
|
||||
app. ⛔ **There is no feature gating, ever** — revenue argument, not taste: the free tier's reach
|
||||
is the funnel, and the flash is an ad running inside other people's content, so a free user with a
|
||||
flash every 30–60s is already paying in exposure.
|
||||
|
||||
**Goal:** a **one-time perpetual license** via Polar.sh that removes the branding watermark. All features
|
||||
are free — the only difference between free and paid is the watermark. (Model changed 2026-09-21 from
|
||||
annual subscription to one-time "own it": $29 founder / $49 list lifetime. See `MONETIZATION.md` →
|
||||
Pricing for the reasoning.)
|
||||
**⚠️ STATUS: THIS IS A TEARDOWN, NOT A BUILD (2026-09-27).** The billing provider is
|
||||
**Microsoft Store IAP**, not Polar. Everything below describing Polar is **dead** and is retained
|
||||
only as history. **Do not resurrect any of it.** The teardown's file-by-file list lives in
|
||||
[`TASKS/task-48-distribution-msix.md`](task-48-distribution-msix.md) item 0 — **work from there,
|
||||
not from this file.**
|
||||
|
||||
**Pricing — ✅ DECIDED 2026-09-27: `$10/mo` subscription, or `$400` lifetime. No annual.**
|
||||
|
||||
| Tier | Price | Net after 15% | Role |
|
||||
|---|---|---|---|
|
||||
| Free | $0 | — | Everything, plus the branding flash. The funnel. |
|
||||
| **Pro monthly** | **$10/mo** | ~$8.50/mo | The default. Low-risk entry. |
|
||||
| **Pro lifetime** | **$400** | ~$340 | The hedge. Committed / subscription-hostile buyers. |
|
||||
|
||||
- **15% Store revenue share, subscriptions included** — verified from the ADA v8.10 PDF, §6(b)(i).
|
||||
Net receipts are after VAT/GST, so commission is not paid on pass-through tax.
|
||||
- **Break-even is month 40**, so the two tiers barely compete — which is why lifetime is safe to
|
||||
offer at launch rather than saving it for later.
|
||||
- ⛔ **No annual tier** — Microsoft does not pro-rate and the developer cannot refund the
|
||||
forfeited remainder. ⛔ **No `.99` prices.** ⛔ **No discounted upgrade SKU.**
|
||||
- **ADA §6(h): raising the price disables auto-renew ⇒ `$10` is effectively locked for life.**
|
||||
- ⛔ **Superseded pricing, do not cite:** the 2026-09-21 one-time model (`$29` founder → `$49`
|
||||
list lifetime) and the earlier `$49.99/yr → $99/yr` subscription.
|
||||
|
||||
**Related work — monetization awareness (2026-09-01, ungated, free):** this task's billing is the
|
||||
*payer* side; the *product* also carries built-in, ungated monetization awareness for every creator —
|
||||
@@ -19,26 +43,32 @@ narrative, not a separate task number — it ships in its own code slices with o
|
||||
**Scope: v1** (2026-09-01 complete-v1 ruling — there is no v1.x): slice order = reward-event capture →
|
||||
session report → journey tracker → Alerts (TASK 3 item 20).
|
||||
|
||||
**Business details (pricing, Polar product/checkout/discounts) in `MONETIZATION.md` (gitignored).**
|
||||
**Business details (pricing, Partner Center product declaration) in `MONETIZATION.md` (gitignored).**
|
||||
|
||||
**Polar product:** `d105dfa1-497e-423b-8cd4-e0ee2e3abbc0` (LlamaCasty, ⚠️ currently configured as
|
||||
$99/yr **subscription** — must be re-created as a **one-time** product: $29 founder / $49 list lifetime)
|
||||
**Checkout:** `llamacasty.com` → Polar hosted page (~80% configured)
|
||||
**Discounts:** `LLAMAFOUNDER` (100% off, 50 uses, `once`), `LLAMA50` (50% off, `once`)
|
||||
**Org ID:** `c05fb364-b967-4f6c-adf2-8a144e46d085` (org-scoped OAT — `organization_id` can be omitted from API calls)
|
||||
**Key prefix:** `LCYT-`
|
||||
**Validate endpoint:** `POST https://api.polar.sh/v1/customer-portal/license-keys/validate` (no auth required for client-side validation)
|
||||
### Status: 🔶 TEARDOWN — steps 1–7 shipped under Polar, all now to be removed
|
||||
|
||||
### Status: 🔶 In progress — steps 1–7 shipped, Velopack update URL pending
|
||||
|
||||
1. ✅ **Billing provider** — Polar (polar.sh) chosen and configured. Product, price, license key benefit, discounts, checkout link all created.
|
||||
2. ✅ **License key entry + verification UI** — About overlay swap panel (same pattern as Licenses panel). Text input + "Activate" button + status message. "Enter License Key" button in the hub.
|
||||
3. ✅ **Offline entitlement** — `LayoutStore` Settings table: `LicenseKey`, `LicenseValidatedAt`, `IsPremium`. 14-day offline grace period. Startup re-validates online, falls back to cache.
|
||||
4. ✅ **BrandFlash → watermark toggle** — `IsPremium` property setter flips `BrandFlashEnabled = !value`. Flash stops immediately on premium activation. Flash asset VideoFrame rendering deferred to TASK 4 compositor.
|
||||
5. ✅ **Remove social slot locks** — all 6 social bar slots open to everyone (no `IsPremium` gating on slots 3-6) — shipped as TASK 10c
|
||||
6. ✅ **"Unlock Premium" button** — `PremiumUrl` set to Polar checkout; `IsPremiumAvailable` is true; button lights up in the About hub.
|
||||
7. ✅ **Licensing model** — startup re-validates against Polar API. **Perpetual key (2026-09-21): the
|
||||
license never expires, `IsPremium` never lapses, and the flash does not return.** The former
|
||||
renewal/lapse path is dead. Offline grace period (14 days) still applies to the validation call only.
|
||||
8. 🔶 **Velopack auto-updates** — NuGet packages + bootstrap in `App.xaml.cs`. Update URL self-hosted on DO droplet (pending configuration).
|
||||
Steps 1–7 below are a **record of what was built**, not a description of what ships. The Polar
|
||||
licensing path is being deleted because Store IAP supplies the same bit from the OS entitlement.
|
||||
|
||||
1. ⛔ **Billing provider** — was Polar (polar.sh). **DELETED.** The product, checkout link, and the
|
||||
discount codes `LLAMAFOUNDER` / `LLAMA50` no longer exist. Store IAP products are declared in
|
||||
**Partner Center**, not Polar.
|
||||
2. ⛔ **License key entry + verification UI** — was the About-overlay swap panel
|
||||
("Enter License Key"). **DELETING.**
|
||||
3. ⛔ **Offline entitlement** — was `LayoutStore` Settings (`LicenseKey`, `LicenseValidatedAt`,
|
||||
`IsPremium`) + a 14-day offline grace period + startup re-validation. **DELETING.** The OS
|
||||
supplies license state, so the entire offline-grace machine goes with it — along with the whole
|
||||
"network flaky → app thinks I'm expired" bug class.
|
||||
4. ✅ **BrandFlash → watermark toggle** — `IsPremium` setter flips `BrandFlashEnabled = !value`, so
|
||||
the flash stops the moment the entitlement flips. **This survives the teardown.** Under Store IAP
|
||||
`IsPremium` is derived from the Store entitlement rather than a remote HTTP call. One bit,
|
||||
locally cached, refreshed by the OS. ⚠️ **This is the whole product surface of the paid tier.**
|
||||
5. ✅ **Remove social slot locks** — all 6 social bar slots open to everyone. **Survives.**
|
||||
6. ⛔ **"Unlock Premium" button** — `PremiumUrl` pointed at Polar checkout. **DELETING**; the Store
|
||||
handles purchase. Paid users see zero license UI.
|
||||
7. ⛔ **Licensing model / renewal-lapse path** — already dead before the Store ruling (a perpetual
|
||||
key never expires). Now superseded again: **Store IAP has no keys at all.**
|
||||
8. 🔶 **Velopack auto-updates** — NuGet packages + bootstrap in `App.xaml.cs`. **TEARDOWN is a
|
||||
compliance action, not cleanup:** the updater downloads *and executes*, and Store policy 10.2.2
|
||||
does not permit it. Tracked as [`TASKS/task-48-distribution-msix.md`](task-48-distribution-msix.md)
|
||||
item 3; the Store updates the app instead.
|
||||
@@ -39,7 +39,7 @@ The tasks below are ordered by dependency and risk. Each task builds on the prev
|
||||
|
||||
1. ✅ **TASK 9.4** — Live chat (right panel) — wire `YouTubeChatService.Start()`, parse messages, render in panel. Foundation for chat box source.
|
||||
2. ✅ **TASK 3.18** — Chat box source — renders chat ON the stream. Depends on TASK 9.4 (same message parsing).
|
||||
3. ✅ **TASK 10** — Polar billing — license key entry + watermark toggle + Velopack auto-updates (steps 1-7 shipped; Velopack update URL pending).
|
||||
3. ✅ **TASK 10** — watermark-only paid delta (brand flash). Steps 1–7 shipped under **Polar**, which is **now deleted in favour of Microsoft Store IAP** (2026-09-27) — TASK 10 is a **teardown**, and the Velopack updater goes with it (Store policy 10.2.2).
|
||||
4. ✅ **TASK 19/23** — Control Surface UX — director's control room: thumbnails above central monitor, transitions (Cut/Fade/Move), edit mode offline only, left panel two-state (layers/props ↔ chat), right panel eliminated. Verified shipped 2026-08-24.
|
||||
5. ✅ **TASK 20** — Hotkeys — global keyboard shortcuts. Shipped 2026-08-26: F1-F9 defaults + config UI with modifier chords, persistence, conflict detection, unbinding.
|
||||
5b. ✅ **Broadcast metadata pull-out + launch geometry** — shipped 2026-08-24 (row 29 above). Live-screen "Text" tab → broadcast form, persistence + remote update; window default/minimums bumped (1920×1040 / 1366×768) with size+position restore.
|
||||
|
||||
@@ -17,10 +17,11 @@ may be done opportunistically mid-development — each item has a lock/comment p
|
||||
real mp4 decode/loop/pacing (TASK 21 picker must have landed), real recording file opens +
|
||||
plays (fragmented MP4), a real private go-live end-to-end, GUI/RealApp test classes green on
|
||||
the desktop (they've only ever run against fakes).
|
||||
5. ☐ **License-expiry reminders** — T-14 / T-7 / T-1 toasts via the existing notification stack
|
||||
("renews <date> — manage here" → `PremiumUrl`); lapsed: flash returns (the product itself is the
|
||||
notice) + one Info toast; active paid users see ZERO license UI. Research: does Polar's
|
||||
validate response carry `expires_at` reliably — cite before building.
|
||||
5. ⛔ **STRUCK — License-expiry reminders are dead.** This item assumed a Polar license with an
|
||||
`expires_at` we could warn about. Under **Store IAP** there is no key, no expiry, and no lapse:
|
||||
the lifetime entitlement never ends and the subscription is renewed by Microsoft. **Nothing to
|
||||
remind anyone about — do not build.** (The `expires_at` question is moot for the same reason:
|
||||
`PolarLicenseService` is being deleted.)
|
||||
6. ☐ **Release engineering** (the `Distribution.md` plan, 644 lines, finally tasked): code signing
|
||||
(HARD blocker — an unsigned installer is a SmartScreen scarewall), installer + Velopack update URL
|
||||
(TASK 10 item 8), EULA draft/review, THIRD-PARTY-NOTICES license-texts gate (TASK 4 req 9).
|
||||
|
||||
Reference in New Issue
Block a user