Created comprehensive launch materials and monetization foundation. Marketing Materials Created: 1. DEMO_VIDEO_SCRIPT.md (90-second demo script) - Complete shot-by-shot breakdown - Voiceover script with timing - B-roll suggestions - Social media cut variations (30s, 60s) - Publishing checklist - Music recommendations - Target: 10K+ views in first week 2. PRODUCT_HUNT_LAUNCH.md (Complete PH strategy) - Optimized product listing copy - Founder's first comment (1000+ words) - 6-8 gallery images specifications - Hour-by-hour launch day plan - Comment response templates - Success metrics and goals - Community outreach strategy - Email campaign templates - Target: Top 5 product of the day 3. AUTHENTICATION_SETUP.md (Clerk + Stripe guide) - Step-by-step Clerk integration - Subscription tier definitions (Free/Studio/Pro/Enterprise) - Feature gating implementation - Stripe payment integration - Webhook handling - Usage tracking system - Implementation checklist - Target: Monetization-ready in 4 weeks Strategic Impact: Launch Readiness: ✅ Demo video script ready to record ✅ Product Hunt listing optimized ✅ Social media strategy planned ✅ Authentication roadmap defined ✅ Monetization path clear Revenue Model: - Free: 5 templates, no translation - Studio ($15/mo): All templates, desktop app - Pro ($45/mo): AI translation + collaboration - Enterprise: Custom pricing Time to Launch: - Record demo: 2-3 hours - Product Hunt submission: 30 minutes - Clerk auth implementation: 1 week - Stripe integration: 1 week - Total: 2-3 weeks to full monetization Next Actions: 1. Record demo video using provided script 2. Schedule Product Hunt launch (Tuesday-Thursday) 3. Implement Clerk authentication 4. Add Stripe payments 5. Deploy to production 6. Launch and scale!
15 KiB
🔐 Authentication Setup Guide (Clerk Integration)
Complete guide to adding authentication to AeThex Studio for monetization and user management.
🎯 Why Authentication?
Required for:
- User accounts and profiles
- Feature gating by tier (Free/Studio/Pro)
- Billing and subscriptions
- Team collaboration
- Usage tracking and analytics
- API key management
🚀 Quick Start (30 minutes)
Step 1: Create Clerk Account
- Visit: https://clerk.com
- Sign up (free tier: 10,000 MAU)
- Create new application: "AeThex Studio"
- Select authentication methods:
- ✅ Email + Password
- ✅ Google OAuth
- ✅ GitHub OAuth
- ⚠️ Magic Links (optional)
Step 2: Install Dependencies
npm install @clerk/nextjs
Step 3: Add Environment Variables
# .env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
# Optional: Customize URLs
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
Get keys from: https://dashboard.clerk.com/apps → API Keys
📁 File Structure
src/
├── app/
│ ├── sign-in/
│ │ └── [[...sign-in]]/
│ │ └── page.tsx
│ ├── sign-up/
│ │ └── [[...sign-up]]/
│ │ └── page.tsx
│ └── layout.tsx (wrap with ClerkProvider)
├── middleware.ts (protect routes)
└── components/
└── UserButton.tsx (user menu)
🛠️ Implementation
1. Update Next.js Layout
File: src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ClerkProvider>
<html lang="en">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
2. Create Sign-In Page
File: src/app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs';
export default function Page() {
return (
<div className="flex items-center justify-center min-h-screen">
<SignIn />
</div>
);
}
3. Create Sign-Up Page
File: src/app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs';
export default function Page() {
return (
<div className="flex items-center justify-center min-h-screen">
<SignUp />
</div>
);
}
4. Add Middleware (Route Protection)
File: src/middleware.ts
import { authMiddleware } from '@clerk/nextjs';
// Protect all routes except public ones
export default authMiddleware({
publicRoutes: [
'/',
'/sign-in(.*)',
'/sign-up(.*)',
'/api/public(.*)',
],
});
export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};
5. Add User Button to Toolbar
File: src/components/Toolbar.tsx
import { UserButton, SignInButton, useUser } from '@clerk/nextjs';
export function Toolbar({ ... }: ToolbarProps) {
const { isSignedIn, user } = useUser();
return (
<div className="flex items-center gap-2">
{/* Existing toolbar items */}
{/* Add authentication */}
{isSignedIn ? (
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground">
{user.fullName || user.emailAddress}
</span>
<UserButton afterSignOutUrl="/" />
</div>
) : (
<SignInButton mode="modal">
<button className="px-4 py-2 bg-accent text-white rounded">
Sign In
</button>
</SignInButton>
)}
</div>
);
}
🎫 Feature Gating (Subscription Tiers)
1. Define User Tiers
File: src/lib/subscription-tiers.ts
export type SubscriptionTier = 'free' | 'studio' | 'pro' | 'enterprise';
export interface TierFeatures {
name: string;
price: number;
features: {
translation: boolean;
desktopApp: boolean;
maxTemplates: number;
teamCollaboration: boolean;
prioritySupport: boolean;
};
}
export const tiers: Record<SubscriptionTier, TierFeatures> = {
free: {
name: 'Foundation',
price: 0,
features: {
translation: false,
desktopApp: false,
maxTemplates: 5,
teamCollaboration: false,
prioritySupport: false,
},
},
studio: {
name: 'Studio',
price: 15,
features: {
translation: false,
desktopApp: true,
maxTemplates: -1, // unlimited
teamCollaboration: false,
prioritySupport: true,
},
},
pro: {
name: 'Pro',
price: 45,
features: {
translation: true, // 🔥 KILLER FEATURE
desktopApp: true,
maxTemplates: -1,
teamCollaboration: true,
prioritySupport: true,
},
},
enterprise: {
name: 'Enterprise',
price: 0, // Custom pricing
features: {
translation: true,
desktopApp: true,
maxTemplates: -1,
teamCollaboration: true,
prioritySupport: true,
},
},
};
2. Add Tier to User Metadata
In Clerk Dashboard:
- Go to "Users" → "Metadata"
- Add public metadata field:
subscriptionTier - Default value:
"free"
3. Check User Tier
File: src/lib/use-subscription.ts
import { useUser } from '@clerk/nextjs';
import { tiers, SubscriptionTier } from './subscription-tiers';
export function useSubscription() {
const { user } = useUser();
const tier: SubscriptionTier =
(user?.publicMetadata?.subscriptionTier as SubscriptionTier) || 'free';
const features = tiers[tier].features;
const hasFeature = (feature: keyof typeof features): boolean => {
return features[feature] as boolean;
};
const canUseTemplates = (count: number): boolean => {
if (features.maxTemplates === -1) return true;
return count <= features.maxTemplates;
};
return {
tier,
features,
hasFeature,
canUseTemplates,
isProOrHigher: tier === 'pro' || tier === 'enterprise',
};
}
4. Gate Translation Feature
File: src/components/Toolbar.tsx
import { useSubscription } from '@/lib/use-subscription';
export function Toolbar({ ... }: ToolbarProps) {
const { hasFeature, tier } = useSubscription();
const handleTranslateClick = () => {
if (!hasFeature('translation')) {
toast.error('Translation requires Pro plan. Upgrade to unlock!');
// Redirect to pricing page
window.location.href = '/pricing';
return;
}
setShowTranslation(true);
};
return (
<Button onClick={handleTranslateClick}>
Translate
{!hasFeature('translation') && (
<Badge className="ml-2">PRO</Badge>
)}
</Button>
);
}
5. Gate Templates
File: src/components/TemplatesDrawer.tsx
import { useSubscription } from '@/lib/use-subscription';
export function TemplatesDrawer({ ... }: TemplatesDrawerProps) {
const { canUseTemplates, features, tier } = useSubscription();
const handleTemplateClick = (template: ScriptTemplate, index: number) => {
// Check if user can access this template
if (!canUseTemplates(index + 1)) {
toast.error(
`Template ${index + 1} requires ${features.maxTemplates < index + 1 ? 'Studio' : 'Free'} plan or higher`
);
return;
}
onSelectTemplate(template.code);
onClose();
};
return (
{/* ... */}
{platformTemplates.map((template, index) => (
<Card
key={template.id}
className={`
p-4 cursor-pointer
${!canUseTemplates(index + 1) && 'opacity-50 cursor-not-allowed'}
`}
onClick={() => handleTemplateClick(template, index)}
>
<div className="flex items-start justify-between">
<h3>{template.name}</h3>
{!canUseTemplates(index + 1) && (
<Badge>
{tier === 'free' ? 'STUDIO' : 'PRO'}
</Badge>
)}
</div>
{/* ... */}
</Card>
))}
);
}
💳 Stripe Integration (Payments)
1. Install Stripe
npm install @stripe/stripe-js stripe
2. Add Environment Variables
# .env.local
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
3. Create Pricing Page
File: src/app/pricing/page.tsx
import { tiers } from '@/lib/subscription-tiers';
export default function PricingPage() {
return (
<div className="container mx-auto py-12">
<h1 className="text-4xl font-bold text-center mb-12">
Choose Your Plan
</h1>
<div className="grid md:grid-cols-4 gap-6">
{Object.entries(tiers).map(([key, tier]) => (
<div key={key} className="border rounded-lg p-6">
<h2 className="text-2xl font-bold">{tier.name}</h2>
<p className="text-4xl font-bold my-4">
${tier.price}
{tier.price > 0 && <span className="text-lg">/mo</span>}
</p>
<ul className="space-y-2 mb-6">
<li>✓ {tier.features.maxTemplates === -1 ? 'Unlimited' : tier.features.maxTemplates} Templates</li>
<li>{tier.features.translation ? '✓' : '✗'} AI Translation</li>
<li>{tier.features.desktopApp ? '✓' : '✗'} Desktop App</li>
<li>{tier.features.teamCollaboration ? '✓' : '✗'} Team Collaboration</li>
<li>{tier.features.prioritySupport ? '✓' : '✗'} Priority Support</li>
</ul>
<button className="w-full bg-accent text-white py-2 rounded">
{tier.price === 0 ? 'Current Plan' : 'Upgrade'}
</button>
</div>
))}
</div>
</div>
);
}
4. Create Checkout API Route
File: src/app/api/create-checkout-session/route.ts
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
import { auth } from '@clerk/nextjs';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16',
});
export async function POST(req: Request) {
const { userId } = auth();
if (!userId) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { tier } = await req.json();
// Price IDs from Stripe Dashboard
const priceIds = {
studio: 'price_studio_monthly',
pro: 'price_pro_monthly',
};
const session = await stripe.checkout.sessions.create({
customer_email: userId, // Or get from Clerk
line_items: [
{
price: priceIds[tier as keyof typeof priceIds],
quantity: 1,
},
],
mode: 'subscription',
success_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard?success=true`,
cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/pricing?canceled=true`,
metadata: {
userId,
tier,
},
});
return NextResponse.json({ url: session.url });
}
5. Handle Webhooks
File: src/app/api/webhooks/stripe/route.ts
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
import { clerkClient } from '@clerk/nextjs';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16',
});
export async function POST(req: Request) {
const body = await req.text();
const sig = req.headers.get('stripe-signature')!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
sig,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err) {
return NextResponse.json({ error: 'Webhook error' }, { status: 400 });
}
// Handle successful payment
if (event.type === 'checkout.session.completed') {
const session = event.data.object as Stripe.Checkout.Session;
const userId = session.metadata?.userId;
const tier = session.metadata?.tier;
if (userId && tier) {
// Update user's tier in Clerk
await clerkClient.users.updateUserMetadata(userId, {
publicMetadata: {
subscriptionTier: tier,
stripeCustomerId: session.customer,
},
});
}
}
// Handle subscription cancellation
if (event.type === 'customer.subscription.deleted') {
const subscription = event.data.object as Stripe.Subscription;
// Downgrade user to free tier
}
return NextResponse.json({ received: true });
}
📊 Usage Tracking (Optional)
Track API Usage Per User
File: src/lib/usage-tracking.ts
import { auth } from '@clerk/nextjs';
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!
);
export async function trackTranslation(
sourcePlatform: string,
targetPlatform: string
) {
const { userId } = auth();
if (!userId) return;
await supabase.from('usage').insert({
user_id: userId,
action: 'translation',
source_platform: sourcePlatform,
target_platform: targetPlatform,
timestamp: new Date().toISOString(),
});
}
export async function getUserUsage(userId: string, month: string) {
const { data } = await supabase
.from('usage')
.select('*')
.eq('user_id', userId)
.gte('timestamp', `${month}-01`)
.lte('timestamp', `${month}-31`);
return {
translationCount: data?.filter(u => u.action === 'translation').length || 0,
};
}
✅ Implementation Checklist
Phase 1: Basic Auth (Week 1)
- Install Clerk
- Add environment variables
- Create sign-in/sign-up pages
- Add middleware
- Add UserButton to Toolbar
- Test authentication flow
Phase 2: Feature Gating (Week 2)
- Define subscription tiers
- Create
use-subscriptionhook - Gate translation feature
- Gate templates (5 free, rest require Studio+)
- Add upgrade prompts
- Create pricing page
Phase 3: Payments (Week 3)
- Install Stripe
- Create products in Stripe Dashboard
- Implement checkout API
- Add webhook handler
- Test payment flow
- Handle subscription management
Phase 4: Polish (Week 4)
- Add usage tracking
- Create user dashboard
- Implement billing portal
- Add team features (Pro tier)
- Test edge cases
- Deploy to production
🎯 Quick Win: Free vs Pro
Easiest monetization path:
-
Free Tier:
- 5 templates (1 per category)
- No translation (show "Upgrade to Pro" message)
- Web IDE only
-
Pro Tier ($45/mo):
- ✅ AI Translation (killer feature)
- ✅ All 43 templates
- ✅ Desktop app access
- ✅ Priority support
Implementation: Just gate translation feature. That alone justifies $45/mo for studios.
📚 Resources
- Clerk Docs: https://clerk.com/docs
- Stripe Docs: https://stripe.com/docs
- Next.js Auth: https://clerk.com/docs/quickstarts/nextjs
- Webhooks: https://stripe.com/docs/webhooks
Ready to monetize? Start with Clerk auth, then add Stripe payments! 💰