Files
briant 2cbacbc4d5 feat(monetization): say what the pricing cap counts, and what spent it
A Silver creator hit "You have monetized 25 of 25 model versions this
month" while publishing in Early Access and asked why it wasn't 25 + 20
= 45. The two limits measure different things -- the 25 counts versions
carrying a licensing fee or a permanent paid gate, while a timed Early
Access window spends nothing and has its own concurrent-window cap --
but the word "monetized" covers both, and the two meters sit side by
side. The product invited the arithmetic, then refused on save with a
number and no explanation.

The counter and the allowance refusal now say "priced", name what is
counted, and rule Early Access out explicitly. PRICING_SLOT_EXPLAINER
and EARLY_ACCESS_NOT_COUNTED live in @civitai/buzz so the main app and
Creator Studio cannot drift, and the refusal names the tier it refuses
on. pricingFloorMessage deliberately keeps "monetize": the floor is
about who may sell at all, not about what the counter counts, and a
test pins that split.

The count was already shown in both editors; the explanation was not.
Both now carry it where the price is set -- an info popover and an
at-limit alert onsite (which says a timed window is still available
because it needs no slot), and labelled meters plus per-mode "uses one
pricing slot" / "uses no pricing slot" text in Studio.

listPricingSlots answers what spent them: the owner's slots newest
first, split on the calendar month the allowance counts, each row the
model version and what it charges. Behind modelVersion.getPricingSlots
onsite, loaded with the models page in Studio.

Amounts are the version's price NOW, not the price at spend time.
PricingSlot is {entityType, entityId, ownerId, createdAt} keyed on the
entity -- current state, not an audit log -- so an accurate fee-at-spend
figure and a real priced/released/re-priced history need an append-only
ledger or amount + releasedAt columns. Not built; the UI says so rather
than implying otherwise.

Prices render through formatFeeRatio, not the raw per-image number: the
default fee is 0.1/image, which every other surface shows as
"1 Buzz / 10 images".

CU: 868m1baec

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 16:23:12 -06:00
..
2026-07-16 16:24:31 -06:00

Creator Studio — feature/page specs

Per-page design docs for creator.civitai.com. These sit under the umbrella docs — read those first:

Implementation tracking — the single source of truth for status:

  • implementation-checklist.md — everything open lives here: per-page build status, open decisions, backend blockers, flagged bugs, deferred work. Start here.

Paid Access (early access + permanent paid access):

  • paid-access-current-state.md — start here to continue paid-access work: what's built (permanent + usage-control pricing), where the code lives across both apps, the verified purchase→access flow, gotchas, and open items (incl. the still-open findings consolidated from the phase-1 reviews).
  • paid-access-followups.md — the actionable checklist from the Justin/Ellie review + notes (button label, buzz-icon prefixes, badge pricing, studio CP-join, nav link, etc.).
  • paid-access-schema.md — the PaidAccess table + terms shapes (data reference).
  • onsite-monetization-parity.md — the design rationale / staging behind the refactor.

The phase-1 plan/review/cutover process docs are done and were removed; the migration record is in prisma/migrations/.

Decisions & Q&A (answered — reference/rationale):

Each page doc follows the same template: Route & purpose → User story → Layout & components → Data (reads) → Actions (writes) → States → Gating → Shared/cross-refs → Open questions.

Pages

Page Doc v1 Notes
Dashboard / overview dashboard.md ✓ at-a-glance earnings + entry points
Model management models.md ⭐ access toggles, per-version licensing fee, sell-indefinitely
Analytics analytics.md ⭐ /analytics — ClickHouse usage/earnings charts (moved from /earnings/analytics)
Earnings earnings.md ✓ /earnings — earnings by source (ClickHouse)
Licensing fees (bulk) licensing.md ~ bulk fee editor; may trail the per-version editor
Settings settings.md ✓ Tipalti/tier status, default fee suggestions
Membership upsell join.md ✓ /join — for non-members

⭐ designer-prioritised · ✓ in v1 · ~ v1 if it lands, else fast-follow

Cross-cutting (not a page — referenced by several)

  • Nav — one app-local nav.ts constant drives the Studio shell's desktop sidebar + mobile header (plan §3). /admin is a separate shell with its own list ($lib/admin-nav.ts); nav.ts's adminOnly item is only the way in.
  • Member gate — most write actions are member-tier gated; the exact bar (tier vs full CP membership) is a pending confirm.
  • Monetization module — setLicensingFee / bulkSetLicensingFee / setUnlimitedAccess (plan §5.3).
  • Analytics reads — ClickHouse via @civitai/clickhouse, daily aggregates (plan §7.6).

Cross-cutting decisions

The recurring cross-page questions that once lived here are now decided and captured in pre-implementation-decisions.md: /licensing = ?mode=bulk on /models (C2), owner-keyed rollup = build it (A1), charting = Chart.js (C1), cash home = /earnings (C6), page boundaries (C5), member gate = full CP membership (B1), access/cosmetic sales in v1 (A5/B3), no per-account default fee (B9).

The few still-open ones (fee-defaults editability #17, early-access reframing #23, publish/schedule B13) are tracked in the implementation checklist → "Open — needs a decision".