B2C Landing Page & Freemium Monetization¶
Status: shipped (home redesign 2026-07-10) Owner: Bhanu Related: site-ia-and-organizations-landing.md, b2c-two-tier-pricing.md, b2c-signup-attribution.md
Kwilo's public B2C surface: the marketing site home plus a freemium chat experience for individual users (learners prepping for exams, freelance trainers) who arrive without an institution. They try the core product for free, then convert to paid when they want downloads or exceed usage limits. The free tier is the product demo: generate the artifact, show the preview, paywall the download.
Pricing is two-tier (Free + Pro ₹399/mo). The canonical source is b2c-two-tier-pricing.md. Free-tier mechanics (pooled monthly cap, watermarked downloads, locked Study/Lesson Plan) are owned there.
Why this exists (Product Mindset Gate)¶
- Who asked for it? Owner-driven redesign, executed from a design handoff. Nobody outside the team requested it; that is flagged, not hidden.
- What user pain? Three concrete problems on the old page. The hero was generic: a persona toggle plus a trial input that asked visitors to classify themselves before showing any value. The social proof was fabricated: press mentions, ratings, and trial or money-back claims we could not stand behind. And the brand font never actually loaded: Manrope was declared but never shipped, so every visitor saw a system-font fallback instead of the brand.
- Cost of not doing it? Every paid and organic visitor landed on a page that undersold the product and overstated the proof. Fabricated claims are also a trust liability the moment anyone checks them.
- Validated or guess? Weak validation: owner dogfooding of the old page, no user interviews or A/B data. Flagged explicitly.
- How we know it worked? Hero-CTA signups attributed via the
individualsinternal UTM source, plus bounce rate on/. Sean Ellis counterfactual: reverting would bring back the persona-toggle page, and the difference is visible on the first screen.
The home page (promoted from /individuals)¶
The B2C landing was redesigned and promoted to the site home. kwilo.ai/ now serves a single-track learner and exam-prep landing; /individuals 301-redirects to /. The IA contract (who owns which route, canonicals, sitemap) is owned by site-ia-and-organizations-landing.md.
Section order on /:
- CTA-only hero. Library photo background, one headline, one primary CTA. No persona toggle, no trial input. Visitors are not asked to classify themselves or type a topic before seeing value.
- Exam-coverage pills. JEE Main, JEE Advanced, NEET UG, CBSE, State Boards, CUET.
- Feature showcases with product mocks. Study Plan, Practice, AI guidance, Analytics.
- Truthful results band. Only claims we can back: +42 average mock-score gain in 8 weeks, 94% weekly goal completion, 6,000+ topic-tagged past-paper questions, JEE + NEET coverage.
- Testimonials and mentors strips. Placeholder social proof, clearly pending real assets.
- Interactive exam-readiness journey. A baseline slider plus an exam date produce a computed plan preview.
- Free/Pro pricing teaser. Trial and money-back claims removed.
- Truthful FAQ.
- Final CTA on a premium
SmartSurface.
Every CTA on the page carries internal UTM attribution with source=individuals (see b2c-signup-attribution.md).
Honesty policy¶
The page carries no fabricated press mentions, no invented ratings, no trial claims, and no money-back claims. The results band states only numbers we can defend. Testimonials and mentors are visibly placeholder until real assets exist. If a claim cannot survive a skeptical visitor checking it, it does not ship.
What was retired¶
- Persona toggle. The hero no longer tailors copy per persona; the page is single-track for learners. Organizations get their own page at
/organizations. - Trial input. The type-a-topic PLG loop in the hero is gone. The CTA sends visitors straight to signup.
- Fabricated social proof. Press logos, ratings, trial and money-back badges.
Freemium model¶
The two apps split by subdomain, sharing @kwilo/ui:
apps/site→kwilo.ai: public marketing, prerendered static HTML for SEO (scripts/prerender.mjs), dep-lean, no TanStack Query or Zustand.apps/web→app.kwilo.ai: authenticated product SPA.apps/backend→api.kwilo.ai.
The same FastAPI backend serves B2B and B2C. B2C users are not a separate backend: they live in one shared "Individual Kwilo" org (individual institution type) with the b2c_user role. Quota and ownership are per-user, so row-level permission checks still work. Subscription tier (free / pro) is a separate field on User, not a role: roles define permissions, tier defines limits.
User journey:
Search / word-of-mouth / social
→ Home page (kwilo.ai/)
→ Signup (Phone | Google | Email)
→ Free tier: unlimited chat + metered artifact generation (preview only)
→ Hits cap or wants a download → PaywallModal
→ Pro ₹399/mo: unlimited generation, PPTX/DOCX/PDF downloads, priority, Study/Lesson Plan unlocked
Generation works on free; the download is gated. The user sees value (the preview) before being asked to pay for the file.
Auth handoff¶
Signup or login on kwilo.ai (email, Google, or phone) sets kwilo_access and kwilo_refresh as HttpOnly; Secure; SameSite=Lax; Domain=.kwilo.ai cookies, then redirects to app.kwilo.ai/<intent-path>. The browser sends the cookies on the next load, so apps/web sees an authenticated user without the frontend ever touching a token. SameSite=Lax is sufficient because both hosts are same-site at the parent-domain boundary, so no separate CSRF token is needed. Dev uses COOKIE_DOMAIN=.kwilo.local.
Signup methods¶
Tabs on /signup: Phone | Google | Email. Phone is the default because most visitors are in India.
| Method | Verification | Backend endpoints |
|---|---|---|
| Phone | MSG91 SMS OTP (6-digit) | /auth/phone-otp/send + /auth/phone-otp/verify |
trust the email_verified claim |
/auth/google/authorize + /auth/google/callback |
|
| register, then email-OTP verify before tokens are valid | /auth/register-individual + /auth/email-otp/send + /auth/email-otp/verify |
Email uses OTP (not a verification link) to keep all three paths consistent at a 6-digit code.
Fraud detection (soft-flag only)¶
At signup, apps/web computes a device fingerprint hash client-side (@fingerprintjs/fingerprintjs visitor ID, SHA-256) and posts device_fingerprint_hash; the backend stores it on the User record. If the same hash appears on 3 or more accounts, it logs auth.duplicate_fingerprint. GET /api/v1/admin/fraud/duplicate-fingerprints?hash= lists accounts sharing a fingerprint. There is no hard block: false positives (shared machines, college networks, cybercafes) outnumber real fraud, so admins review flagged clusters manually. IP-based clustering is avoided because Indian users sit heavily behind shared NAT.
Non-goals¶
- Standalone B2C solution pages. Study Plan, Practice Hub, and exam readiness are footer anchors on
/(/#study-plan,/#practice-hub,/#exam-readiness) for now, not dedicated pages. - Mastery-backed analytics on the landing. The analytics showcase is a mock; wiring it to real mastery data comes later.
Rejected alternatives¶
- Keeping the trial-input hero. The type-a-topic PLG loop asked for effort before showing value and produced weak-intent signups. Rejected for a single CTA into signup.
- Audience switcher on the B2B page. Considered letting
/organizationstoggle back to learner content. Rejected: one audience per page,/owns learners (see the IA doc). - Yellow marker highlight. A hand-drawn marker effect on hero keywords was tried in the handoff and dropped; it fought the premium look.
Where it lives¶
- Marketing:
apps/site/src/pages/Individuals/(now served at/; hero, exam pills, showcases, results band, readiness journey, pricing teaser, FAQ, final CTA),apps/site/src/lib/attribution.ts(dual-touch UTM capture),apps/site/scripts/prerender.mjs. - Product:
apps/web/src/pages/Signup.tsx(Phone/Google/Email tabs),apps/web/src/features/signup/intent.ts. - Backend:
apps/backend/src/api/v1/auth.py,apps/backend/src/services/quota.py,apps/backend/src/services/paywall.py,apps/backend/src/models/user.py. - Design primitives:
@kwilo/uiSmartSurface,SmartBadge,Heading(display-2xl,extrabold),Text(lead). Manrope is self-hosted via@fontsourcein bothapps/siteandapps/web; it was previously declared but never loaded, so pages fell back to system fonts.
Changelog¶
- 2026-07-10: B2C landing redesigned and promoted to site home. Single-track learner page, CTA-only hero, persona toggle and trial input retired, fabricated social proof removed, truthful results band,
/individuals301 to/, internal UTMsource=individualson every CTA. Gate answers added.