Skip to content

B2C freemium: unified preview-and-paywall lock model

One rule for every B2C free surface: every free user can open every chat mode (no hard locks), every mode is rate-limited by a monthly quota, every generated artifact is previewable, and every download (and every copy of an artifact preview) is locked behind the paywall. Pro ₹399 unlocks downloads, uncaps generation, and adds priority. B2B users are unaffected.

Pricing is two-tier (Free + Pro ₹399). See b2c-two-tier-pricing.md. This doc supersedes the lock-model section of chat-mode-surface.md; the mode chip row design there stays valid.

How it works

The model removes feature-level hard locks (the old question_bank / lesson_plan padlock chips) so a free user always reaches generate → preview → want-to-download → paywall. The paywall fires on the download or copy attempt, not on opening the mode.

Action Free tier Pro Enforced in
Open any chat mode Allowed Allowed n/a
Generate artifact (under cap) Allowed Allowed backend quota remaining > 0
Generate artifact (after cap) Chip soft-locks → paywall Allowed ChatPage.deriveLockedModes
View any artifact preview Allowed Allowed n/a
Copy/select/right-click artifact preview body Blocked → paywall Allowed <CopyBlockWrapper> in preview components
Download artifact (PPTX/PDF/DOCX/MD) Blocked → paywall Allowed renderDownload (chat) + handleExport (viewer)
Copy conversational chat text Allowed Allowed n/a

Mode locks are derived from quota only (PRO_TIER_MODE_IDS is deleted). Every mode is soft-locked when its cap is reached.

The copy-block scope is artifact previews only, never plain chat answers. A learner asking "what's the derivative of sin(x)" can copy the answer into their notes; that's fair use and doesn't reduce upgrade pressure. Three preview components carry the block:

  • ResearchMessageContent.tsx (research report body): wrapped in <CopyBlockWrapper canCopy={canCopy} featureName="research">.
  • MockTestCard (unit test + exam prep question sheets): same wrapper, featureName="unit test" / "exam prep".
  • PresentationViewerPage.tsx (slide viewer iframe): injects a copy-block CSS rule + oncontextmenu handler on iframe onLoad when isDownloadLocked.

Each path triggers PaywallModal on attempt with featureName set to the artifact type. Watermarking, print-blocking, and screenshot-blocking are out of scope; the block targets the casual majority, not DRM.

The sidebar's Research and Slides tabs show the free user's own artifacts, the same lists as B2B (ResearchSessionList, PresentationSessionList). Download buttons inside each session stay gated; opening a session shows the preview, which inherits the copy-block. A persistent single-line footer for free users only reads "Unlock all downloads, ₹399/mo →" linking to kwilo.ai/pricing. The sidebar quota block uses useB2CQuota() for B2C (B2B keeps the legacy AIQuotaDisplay).

Tier pitch

  • Free: chat unlimited; all modes usable under a single pooled monthly generation cap; Study/Lesson Plan locked; preview-only, no copy or download of artifacts.
  • Pro ₹399: uncaps generation, unlocks all downloads and copy on previews, unlocks the Study/Lesson Plan, adds priority generation. One-line pitch: "Pro unlocks the Study/Lesson Plan and removes limits."

Where it lives

  • apps/web/src/pages/b2c/ChatPage/index.tsx: quota-only lock derivation, threads canCopy.
  • apps/web/src/pages/b2c/components/: CopyBlockWrapper.tsx, SidebarUpgradeFooter.tsx, B2CSidebarQuota.tsx (new).
  • apps/web/src/pages/shared/AITutorPage/: ChatEngine.tsx, ChatView.tsx, MessageBubble.tsx, ResearchMessageContent.tsx, ChatSidebar.tsx (slot props).
  • apps/web/src/components/ai-tutor/mock-test/MockTestCard.tsx, apps/web/src/pages/shared/PresentationViewerPage.tsx.

Backend dependency: add question_bank and lesson_plan quotas to QuotaStatusResponse (apps/backend/src/schemas/b2c_auth.py), suggested free cap 2/month each. The frontend assumes the keys exist and falls back to unlimited via detail?.unlimited ?? true.