setup-guides

About That — real-estate paid launch

How to turn on the About That real-estate paywall. Built dark 2026-07-17 (PR pending); mirrors the EMBERKILN_PAID_LAUNCH.md flag-gated pattern.

The model

  • Only the agent/Open-House preset is paid ($79/mo Agent, $399/mo Brokerage). founder and candidate (job-seeker) presets are always free — the funnel. An agent's free bio page just uses a free preset.
  • Dark by default: the whole gate is behind NEXT_PUBLIC_ABOUT_THAT_PAID_MODE. While unset/false, nothing is gated — About That behaves exactly as it does today. Flip to true only after the Stripe prices exist.
  • Gate is at RENDER, not create: owners can build + configure an agent embed, but the spend paths (rendition, FAQ) return 402 and eager render skips silently until the owner subscribes. So flipping the flag never hard-breaks a configured embed — it shows the upgrade CTA.

One-time setup

  1. Create two recurring Stripe prices in your Stripe dashboard:
    • Agent — $79/month
    • Brokerage — $399/month
  2. Set the price env vars (Railway backend + Vercel frontend both read Railway-provided vars):
    STRIPE_PRICE_ABOUT_THAT_AGENT=price_...
    STRIPE_PRICE_ABOUT_THAT_BROKERAGE=price_...
    
    Until these are set, POST /api/payment/about-that/checkout returns 503 (same as Graphene+). The webhook already activates them via priceToPlanKey.
  3. Flip the master switch when ready to charge:
    NEXT_PUBLIC_ABOUT_THAT_PAID_MODE=true
    
    Redeploy. Agent-preset embeds now require an active plan; the dashboard shows the "$79/mo" upgrade CTA on agent embeds; /about-that/for-real-estate shows live pricing.

How activation works (no new code)

Checkout (/api/payment/about-that/checkout {plan:'agent'|'brokerage'}) → Stripe subscription → the existing POST /api/payment/webhook upserts a row into subscriptions with plan_key about_that_agent / about_that_brokerage (mapped by priceToPlanKey). isAboutThatSubscriber(userId) reads that row. Management uses the existing /api/payment/customer-portal.

Comping a user (e.g. Ryan's 90-day design-partner deal)

No Stripe charge needed — insert an active subscription row directly:

insert into subscriptions (user_id, plan_key, status, current_period_end, cancel_at_period_end)
values ('<user-uuid>', 'about_that_agent', 'active', now() + interval '90 days', true);

cancel_at_period_end = true + a future current_period_end = access until it lapses, then it naturally closes (they convert or the gate returns).

Code map

  • Gate + flag + subscriber check: services/about-that-billing.ts (shouldGateRender is the pure, unit-tested decision).
  • Enforcement (402 render/FAQ, eager skip): services/about-that.ts.
  • Checkout + plan-key map: routes/payment.ts.
  • Status endpoint: GET /api/about-that/billing/status.
  • Dashboard CTA: dashboard/about-that/page.tsx; pricing: about-that/for-real-estate/page.tsx.
ABOUT THAT PAID LAUNCH — Docs | HiveJournal