No sign-in walls. No free trial countdown. No pressure. Just pure value β Natural conversion β Passive revenue.
1. Land on joepro.ai
2. See "Grok Builder" demo
3. Type: "Build me a blog"
4. 10 seconds β Live app appears
5. NO SIGN IN REQUIRED
Small banner (not annoying):
"π³ Enjoying this? Add a card to keep building (pay only for what you use)"
[Add Card] [Remind Me Later]
- Unlimited usage
- Billed monthly for actual usage
- No subscription (pure pay-per-use)
- Dashboard shows current month: $2.47
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next()
// Get or create anonymous session ID
let sessionId = request.cookies.get('anon_session')?.value
if (!sessionId) {
sessionId = `anon_${Date.now()}_${Math.random().toString(36)}`
response.cookies.set('anon_session', sessionId, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 365 // 1 year
})
}
return response
}
export const config = {
matcher: ['/api/:path*', '/apps/:path*']
}// lib/usage-tracker.ts
import Redis from 'ioredis'
const redis = new Redis(process.env.REDIS_URL)
export async function trackUsage(sessionId: string, action: string, cost: number) {
const key = `usage:${sessionId}:${new Date().toISOString().slice(0, 7)}` // YYYY-MM
await redis.hincrby(key, action, 1)
await redis.hincrbyfloat(key, 'total_cost', cost)
// Set expiry to 3 months
await redis.expire(key, 60 * 60 * 24 * 90)
}
export async function getUsage(sessionId: string) {
const key = `usage:${sessionId}:${new Date().toISOString().slice(0, 7)}`
const usage = await redis.hgetall(key)
return {
sandboxes: parseInt(usage.sandbox_create || '0'),
builds: parseInt(usage.grok_build || '0'),
totalCost: parseFloat(usage.total_cost || '0'),
freeUsesLeft: Math.max(0, 3 - parseInt(usage.grok_build || '0'))
}
}// lib/pricing.ts
export const PRICING = {
// Free tier
FREE_BUILDS: 3,
// Pay-per-use (Stripe)
SANDBOX_CREATE: 0.10, // $0.10 per sandbox
SANDBOX_HOUR: 0.02, // $0.02 per hour running
GROK_BUILD: 0.25, // $0.25 per AI-generated app
GROK_API_CALL: 0.01, // $0.01 per API call
STORAGE_GB_MONTH: 0.05, // $0.05 per GB/month
// Volume discounts (automatic)
DISCOUNTS: {
10: 0.10, // 10% off at $10/month
50: 0.20, // 20% off at $50/month
100: 0.30, // 30% off at $100/month
}
}
export function calculateCost(usage: any) {
let cost = 0
cost += usage.sandboxes * PRICING.SANDBOX_CREATE
cost += usage.sandboxHours * PRICING.SANDBOX_HOUR
cost += usage.builds * PRICING.GROK_BUILD
cost += usage.apiCalls * PRICING.GROK_API_CALL
// Apply volume discount
for (const [threshold, discount] of Object.entries(PRICING.DISCOUNTS)) {
if (cost >= parseInt(threshold)) {
cost *= (1 - discount)
}
}
return cost
}// lib/stripe/usage-billing.ts
import Stripe from 'stripe'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
export async function createCustomer(sessionId: string, email?: string) {
const customer = await stripe.customers.create({
metadata: { sessionId },
email,
})
// Create subscription with metered billing
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [
{
price: process.env.STRIPE_USAGE_PRICE_ID!, // Metered price
}
],
payment_behavior: 'default_incomplete',
payment_settings: { save_default_payment_method: 'on_subscription' },
})
return { customer, subscription }
}
export async function reportUsage(customerId: string, quantity: number) {
const subscriptions = await stripe.subscriptions.list({
customer: customerId,
limit: 1,
})
if (subscriptions.data[0]) {
const subscriptionItem = subscriptions.data[0].items.data[0]
await stripe.subscriptionItems.createUsageRecord(subscriptionItem.id, {
quantity: Math.round(quantity * 100), // Convert dollars to cents
timestamp: Math.floor(Date.now() / 1000),
action: 'increment',
})
}
}// components/SoftPaywall.tsx
'use client'
import { useState, useEffect } from 'react'
import { CreditCard, X } from 'lucide-react'
export default function SoftPaywall() {
const [usage, setUsage] = useState<any>(null)
const [show, setShow] = useState(false)
useEffect(() => {
fetch('/api/usage/me')
.then(r => r.json())
.then(data => {
setUsage(data)
// Show after 3 free uses, but not annoying
if (data.builds >= 3 && !data.hasCard) {
setShow(true)
}
})
}, [])
if (!show || !usage) return null
return (
<div className="fixed bottom-4 right-4 max-w-sm bg-[var(--card-bg)] border-2 border-[var(--primary)] rounded-lg p-4 shadow-2xl z-50">
<button
onClick={() => setShow(false)}
className="absolute top-2 right-2 text-[var(--text-muted)] hover:text-[var(--primary)]"
>
<X size={16} />
</button>
<div className="flex items-start gap-3">
<div className="p-2 bg-[var(--primary)]/10 rounded">
<CreditCard className="text-[var(--primary)]" size={20} />
</div>
<div className="flex-1">
<h3 className="font-bold text-foreground mb-1">
Enjoying Grok Builder?
</h3>
<p className="text-sm text-[var(--text-muted)] mb-3">
You've built {usage.builds} apps. Add a card to keep building.
<br />
<span className="text-[var(--primary)] font-medium">
Pay only for what you use.
</span>
</p>
<div className="flex gap-2">
<button
onClick={() => window.location.href = '/add-card'}
className="px-4 py-2 bg-[var(--primary)] hover:bg-[var(--primary-dark)] text-white text-sm font-medium rounded transition-all"
>
Add Card
</button>
<button
onClick={() => setShow(false)}
className="px-4 py-2 text-sm text-[var(--text-muted)] hover:text-foreground transition-colors"
>
Later
</button>
</div>
</div>
</div>
</div>
)
}// app/api/checkout/create-session/route.ts
import { NextRequest, NextResponse } from 'next/server'
import Stripe from 'stripe'
import { cookies } from 'next/headers'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
export async function POST(req: NextRequest) {
const sessionId = cookies().get('anon_session')?.value
if (!sessionId) {
return NextResponse.json({ error: 'No session' }, { status: 400 })
}
const session = await stripe.checkout.sessions.create({
mode: 'setup', // Just collect card, don't charge yet
success_url: `${process.env.NEXT_PUBLIC_URL}/dashboard?setup=success`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/?setup=cancel`,
metadata: { sessionId },
customer_creation: 'always',
payment_method_types: ['card'],
})
return NextResponse.json({ url: session.url })
}// app/dashboard/page.tsx
'use client'
import { useEffect, useState } from 'react'
import { DollarSign, Zap, Database, Clock } from 'lucide-react'
export default function Dashboard() {
const [usage, setUsage] = useState<any>(null)
useEffect(() => {
fetch('/api/usage/me').then(r => r.json()).then(setUsage)
}, [])
if (!usage) return <div>Loading...</div>
return (
<div className="container mx-auto p-8">
<h1 className="text-3xl font-bold mb-8">
<span className="text-white">Usage</span>
<span className="text-[var(--primary)]"> Dashboard</span>
</h1>
{/* Current Month Cost */}
<div className="glass card-border p-6 mb-8">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-[var(--text-muted)] mb-1">Current Month</p>
<p className="text-4xl font-bold text-[var(--primary)]">
${usage.totalCost.toFixed(2)}
</p>
</div>
<DollarSign size={48} className="text-[var(--primary)]/20" />
</div>
</div>
{/* Usage Breakdown */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<UsageCard
icon={<Zap />}
label="AI Builds"
value={usage.builds}
cost={usage.builds * 0.25}
/>
<UsageCard
icon={<Database />}
label="Sandboxes"
value={usage.sandboxes}
cost={usage.sandboxes * 0.10}
/>
<UsageCard
icon={<Clock />}
label="Runtime Hours"
value={usage.sandboxHours}
cost={usage.sandboxHours * 0.02}
/>
</div>
{!usage.hasCard && (
<div className="mt-8 p-6 border-2 border-[var(--primary)] rounded-lg">
<h3 className="font-bold mb-2">Add a card to continue</h3>
<p className="text-sm text-[var(--text-muted)] mb-4">
You'll be billed monthly for your usage. No subscription required.
</p>
<button className="px-6 py-2 bg-[var(--primary)] hover:bg-[var(--primary-dark)] text-white font-medium rounded">
Add Card
</button>
</div>
)}
</div>
)
}
function UsageCard({ icon, label, value, cost }: any) {
return (
<div className="glass card-border p-4">
<div className="flex items-center gap-3 mb-2">
<div className="text-[var(--primary)]">{icon}</div>
<span className="text-sm text-[var(--text-muted)]">{label}</span>
</div>
<p className="text-2xl font-bold text-foreground">{value}</p>
<p className="text-xs text-[var(--text-muted)] mt-1">
${cost.toFixed(2)} this month
</p>
</div>
)
}// components/PricingTooltip.tsx
export function PricingTooltip() {
return (
<div className="text-xs text-[var(--text-muted)]">
Pricing: $0.25/build β’ $0.10/sandbox β’ $0.02/hour
<br />
First 3 builds free
</div>
)
}Scenario 1: 1,000 users/month
- 10% convert (add card) = 100 paying users
- Average usage: $5/user/month
- Monthly Revenue: $500
Scenario 2: 10,000 users/month
- 10% convert = 1,000 paying users
- Average usage: $5/user/month
- Monthly Revenue: $5,000
Scenario 3: 100,000 users/month (viral)
- 10% convert = 10,000 paying users
- Average usage: $5/user/month
- Monthly Revenue: $50,000
Power Users (top 5%):
- Average: $25-50/month
- These are your best customers
- No friction β More users try it
- Free tier β Viral sharing
- Natural conversion β People add card when they LOVE it
- Fair pricing β Pay for value received
- No subscriptions β No cancel anxiety
- β Session cookies
- β Usage tracking (Redis)
- β Free tier (3 builds)
- β Soft paywall component
- β Stripe Checkout (card collection)
- β Usage-based billing setup
- β Monthly invoicing
- β Usage dashboard
- β Usage API endpoints
- β Cost calculator
- β Email notifications
- β Volume discounts
- β Show current usage transparently
- β Highlight value ("You built 5 apps!")
- β Soft reminder after free tier
- β Easy card addition
- β Fair, predictable pricing
- β Countdown timers
- β "Limited time offer!"
- β Fake urgency
- β Hidden fees
- β Aggressive upsells
- β Annoying popups
1. User tries Grok Builder (free)
2. Shares their app on Twitter
3. Friends click β Try it (free)
4. Some convert β Add card
5. Keep using β Monthly revenue
6. Tell more friends
7. REPEAT
The product sells itself. No pressure needed. π―
User Flow:
Visit β Use (free) β Love it β Add card β Keep using β Pay fairly
Revenue:
1% power users = 50% of revenue
9% regular users = 40% of revenue
90% free users = viral growth engine
Result:
- Product that "prints money"
- No annoying paywalls
- Fair, transparent pricing
- Natural viral growth
- Happy customers who WANT to pay
I can implement:
- Anonymous session tracking
- Redis usage database
- Stripe usage-based billing
- Soft paywall component
- Usage dashboard
- API endpoints
Just say the word and I'll start coding. π°
This is how you make money without being annoying about it. π