Marketing Site + Trial Update Design

Challenge: docs/projects/eko-v2-rollout/05-marketing-site.md

1. Trial Migration & Stripe Checkout (5.1 + 5.2)

Migration 0114

Single statement: UPDATE plan_definitions SET trial_days = 14 WHERE plan_key = 'plus'

Subscribe Flow Change

Current:  Subscribe Page → startFreeTrial() → local DB insert → /subscribe/success
New:      Subscribe Page → POST /api/stripe/checkout → Stripe Checkout (CC + 14-day trial) → webhook → DB upsert

Code Changes

  • apps/web/app/api/stripe/checkout/route.ts — Add 'plus' to Zod enum, accept billingPeriod param, pass trialDays: 14
  • packages/stripe/src/checkout.ts — Add payment_method_collection: 'always' to Stripe session
  • apps/web/app/subscribe/_components/subscribe-page.tsx — Replace startFreeTrial() with fetch to /api/stripe/checkout, redirect to Stripe URL
  • apps/web/app/actions/subscription.ts — Update hardcoded 30 to read from plan_definitions.trial_days
  • Copy updates — "30-day" → "14-day", footer → "No charge for 14 days. Cancel anytime."

2. Public Site Architecture (5.3 + 5.8)

Feed Proxy

Next.js rewrite in apps/public/next.config.ts:

rewrites: [{ source: '/api/feed', destination: process.env.FEED_API_URL || 'https://app.eko.day/api/feed' }]

Local dev points to http://localhost:3000/api/feed.

Home Page

  • Server component fetches /api/feed through rewrite proxy
  • Lightweight PublicFactCard components in apps/public/app/_components/
  • Card click opens a modal dialog with fact teaser + "Sign up to unlock" CTA → app.eko.day/subscribe
  • Responsive grid: 1 col mobile, 2 col tablet, 3 col desktop

Layout

  • Updated metadata from v1 copy to v2 fact-engine positioning
  • Shared nav: Home, Features, Pricing, About + "Sign in" / "Start trial" CTAs
  • Footer with site links

Component Placement

  • apps/public/app/_components/ — nav, footer, public-fact-card, card-modal
  • packages/ui-public/ — stays empty (no cross-app reuse needed yet)

3. Content Pages (5.4 + 5.5 + 5.6)

All server components, no data fetching, pure Tailwind. Voice follows docs/marketing/CHALLENGE_TONE.md.

Pricing

  • Two-tier comparison: Free ($0) vs Eko+ ($3.99/mo or $34.99/yr)
  • Monthly/annual toggle (client component island)
  • Feature comparison table
  • "Start 14-day free trial" CTA → app.eko.day/subscribe
  • "36+ topic categories" badge

Features

  • Hero with v2 tagline
  • Feature sections: Challenge system, Spaced repetition, Score disputes & rewards, 36+ categories
  • Icon + heading + description per section
  • Bottom CTA → subscribe

About

  • Mission statement for knowledge platform
  • High-level "How it works": News ingestion → AI extraction → Verification → Challenge cards
  • 3-4 concise sections

4. Subscription Card Injection (5.7)

Location

apps/web/app/feed/_components/card-feed.tsx (authenticated app feed)

Logic

  • If user is not authenticated, inject SubscriptionCard at position 4
  • Repeat every 24 cards
  • Client-side injection (no API change)

Component

New file: apps/web/app/feed/_components/subscription-card.tsx

  • Visually distinct: gradient border or accent background
  • Headline + 2-3 benefit bullets + CTA → /subscribe
  • Same dimensions as FactCard for grid fit

Implementation Order

  1. 5.1 — Migration 0114 (trial_days 30→14) + fix hardcoded action
  2. 5.2 — Checkout route + subscribe page Stripe redirect + copy
  3. 5.8 — Rewrite proxy in public app config
  4. 5.3 — Public home page with feed + card modal
  5. 5.4, 5.5, 5.6 — Pricing, Features, About (parallelizable)
  6. 5.7 — Subscription card injection in app feed
  7. 5.Q — Quality verification (responsive, links, build)