745 lines
24 KiB
Markdown
745 lines
24 KiB
Markdown
# Free Account Options - Architecture Analysis
|
|
|
|
**Date:** January 14, 2026
|
|
**Status:** Planning Phase
|
|
**Purpose:** Compare two approaches for free user onboarding with limited AI operations
|
|
|
|
---
|
|
|
|
## Current System Architecture
|
|
|
|
### 1. **Account & Plan System**
|
|
```python
|
|
Account Model:
|
|
- plan (FK to Plan)
|
|
- credits (Integer, current balance)
|
|
- status (trial, active, suspended, pending_payment, cancelled)
|
|
- payment_method
|
|
- usage_ahrefs_queries (monthly counter)
|
|
- usage_period_start/end
|
|
|
|
Plan Model:
|
|
- name, slug, price, billing_cycle
|
|
- is_internal (hide from public listings)
|
|
- max_sites, max_keywords, max_users, max_author_profiles
|
|
- included_credits (monthly allocation)
|
|
- extra_credit_price
|
|
- allow_credit_topup
|
|
- max_ahrefs_queries (monthly limit)
|
|
```
|
|
|
|
### 2. **AI Configuration System**
|
|
```python
|
|
AIModelConfig (Global - Single Source of Truth):
|
|
- model_name (e.g., 'gpt-4o-mini', 'hidream-full')
|
|
- model_type (text/image)
|
|
- provider (openai, runware, etc.)
|
|
- is_default (one default per type)
|
|
- is_active
|
|
- cost_per_1k_input/output (text models)
|
|
- credits_per_image (image models)
|
|
- tokens_per_credit (text models)
|
|
|
|
AISettings (Per-Account Overrides):
|
|
- account (FK)
|
|
- integration_type (openai, runware)
|
|
- config (API keys, settings)
|
|
- model_preferences (per operation type)
|
|
- cost_limits (budgets)
|
|
```
|
|
|
|
### 3. **Credit Tracking System**
|
|
```python
|
|
CreditTransaction:
|
|
- transaction_type (purchase, subscription, deduction, adjustment)
|
|
- amount (positive/negative)
|
|
- balance_after
|
|
- description, metadata
|
|
|
|
CreditUsageLog (Per AI Operation):
|
|
- operation_type (clustering, idea_generation, content_generation, image_generation)
|
|
- credits_used
|
|
- cost_usd
|
|
- model_used
|
|
- tokens_input/output
|
|
- site (FK for filtering)
|
|
- related_object_type/id
|
|
```
|
|
|
|
### 4. **Current Registration Flow**
|
|
1. User registers → `RegisterSerializer.create()`
|
|
2. If `plan_slug` not provided or = 'free':
|
|
- Assigns Plan.slug='free' (must exist)
|
|
- Account.status = 'trial'
|
|
- Account.credits = plan.included_credits
|
|
- Creates CreditTransaction (initial allocation)
|
|
3. User can perform AI operations until credits exhausted
|
|
|
|
---
|
|
|
|
## 📊 Option 1: Individual Free Accounts (Isolated)
|
|
|
|
### **Concept**
|
|
Each user gets their own free account with:
|
|
- Fixed cheaper AI models (GPT-4o mini, Hidream-full)
|
|
- Low credit allocation (50-100 operations)
|
|
- Own isolated data/workspace
|
|
- Ability to upgrade to paid plan
|
|
|
|
### **Implementation Plan**
|
|
|
|
#### **Step 1: Create Free Plan**
|
|
```sql
|
|
-- Admin action via Django Admin
|
|
INSERT INTO igny8_plans (
|
|
name, slug, price, billing_cycle,
|
|
is_featured, is_internal, is_active,
|
|
max_sites, max_users, max_keywords,
|
|
included_credits, allow_credit_topup,
|
|
max_ahrefs_queries
|
|
) VALUES (
|
|
'Free Starter', 'free', 0.00, 'monthly',
|
|
false, true, true,
|
|
1, -- max_sites: 1 site only
|
|
1, -- max_users: owner only
|
|
100, -- max_keywords: 100
|
|
100, -- included_credits: 100 credits (~50 operations)
|
|
false, -- No credit topup for free
|
|
0 -- No Ahrefs access
|
|
);
|
|
```
|
|
|
|
#### **Step 2: Create AI Model Configs (If Not Exist)**
|
|
```sql
|
|
-- GPT-4o Mini (cheaper text model)
|
|
INSERT INTO igny8_ai_model_config (
|
|
model_name, model_type, provider, display_name,
|
|
is_default, is_active,
|
|
cost_per_1k_input, cost_per_1k_output,
|
|
tokens_per_credit, max_tokens, context_window
|
|
) VALUES (
|
|
'gpt-4o-mini', 'text', 'openai', 'GPT-4o Mini (Fast & Efficient)',
|
|
false, true,
|
|
0.00015, 0.0006, -- Cheaper than GPT-4
|
|
1000, 16384, 128000
|
|
);
|
|
|
|
-- Hidream Full (cheaper image model)
|
|
INSERT INTO igny8_ai_model_config (
|
|
model_name, model_type, provider, display_name,
|
|
is_default, is_active,
|
|
credits_per_image, quality_tier,
|
|
square_size, landscape_size
|
|
) VALUES (
|
|
'hidream-full', 'image', 'runware', 'Hidream Full (Standard Quality)',
|
|
false, true,
|
|
1, -- 1 credit per image (cheapest)
|
|
'basic',
|
|
'1024x1024', '1280x768'
|
|
);
|
|
```
|
|
|
|
#### **Step 3: Update Registration Logic**
|
|
```python
|
|
# In auth/serializers.py RegisterSerializer.create()
|
|
|
|
# No changes needed! Current logic already handles this:
|
|
if not plan_slug or plan_slug == 'free':
|
|
plan = Plan.objects.get(slug='free', is_active=True)
|
|
account_status = 'trial'
|
|
initial_credits = plan.included_credits # 100 credits
|
|
```
|
|
|
|
#### **Step 4: Force Free Plan AI Models**
|
|
**Option A: Global Default (Simplest)**
|
|
```sql
|
|
-- Set GPT-4o Mini and Hidream as defaults
|
|
UPDATE igny8_ai_model_config
|
|
SET is_default = false
|
|
WHERE model_type = 'text';
|
|
|
|
UPDATE igny8_ai_model_config
|
|
SET is_default = true
|
|
WHERE model_name = 'gpt-4o-mini';
|
|
|
|
UPDATE igny8_ai_model_config
|
|
SET is_default = false
|
|
WHERE model_type = 'image';
|
|
|
|
UPDATE igny8_ai_model_config
|
|
SET is_default = true
|
|
WHERE model_name = 'hidream-full';
|
|
```
|
|
**Pros:** Zero code changes, all free accounts inherit defaults
|
|
**Cons:** Affects ALL accounts (paid users too)
|
|
|
|
**Option B: Per-Account AI Settings (Recommended)**
|
|
```python
|
|
# In auth/serializers.py RegisterSerializer.create()
|
|
# After account creation:
|
|
|
|
if account_status == 'trial': # Free accounts only
|
|
from igny8_core.modules.system.settings_models import AISettings
|
|
|
|
# Create AI settings for OpenAI (text)
|
|
AISettings.objects.create(
|
|
account=account,
|
|
integration_type='openai',
|
|
model_preferences={
|
|
'clustering': 'gpt-4o-mini',
|
|
'idea_generation': 'gpt-4o-mini',
|
|
'content_generation': 'gpt-4o-mini',
|
|
'optimization': 'gpt-4o-mini',
|
|
},
|
|
is_active=True
|
|
)
|
|
|
|
# Create AI settings for Runware (images)
|
|
AISettings.objects.create(
|
|
account=account,
|
|
integration_type='runware',
|
|
model_preferences={
|
|
'image_generation': 'hidream-full',
|
|
},
|
|
is_active=True
|
|
)
|
|
```
|
|
**Pros:** Free accounts locked to cheap models, paid accounts unaffected
|
|
**Cons:** Requires code change in registration flow
|
|
|
|
**Option C: Plan-Level AI Model Configuration**
|
|
```python
|
|
# Add new field to Plan model (migration required)
|
|
class Plan(models.Model):
|
|
# ... existing fields ...
|
|
allowed_text_models = models.JSONField(
|
|
default=list,
|
|
help_text="Allowed text AI models (empty = all)"
|
|
)
|
|
allowed_image_models = models.JSONField(
|
|
default=list,
|
|
help_text="Allowed image AI models (empty = all)"
|
|
)
|
|
force_default_models = models.BooleanField(
|
|
default=False,
|
|
help_text="Force plan defaults, ignore user overrides"
|
|
)
|
|
|
|
# Update Free plan:
|
|
plan = Plan.objects.get(slug='free')
|
|
plan.allowed_text_models = ['gpt-4o-mini']
|
|
plan.allowed_image_models = ['hidream-full']
|
|
plan.force_default_models = True
|
|
plan.save()
|
|
|
|
# In AI operation logic (ai/services.py or similar):
|
|
def get_ai_model_for_account(account, operation_type):
|
|
plan = account.plan
|
|
if plan.force_default_models:
|
|
if operation_type in ['clustering', 'idea_generation', 'content_generation']:
|
|
return 'gpt-4o-mini'
|
|
elif operation_type == 'image_generation':
|
|
return 'hidream-full'
|
|
# ... existing logic for paid accounts
|
|
```
|
|
**Pros:** Centralized plan-based control, scalable
|
|
**Cons:** Requires migration + AI operation logic changes
|
|
|
|
#### **Step 5: Frontend Restrictions**
|
|
```typescript
|
|
// In frontend, check plan limits
|
|
if (user.account.plan.slug === 'free') {
|
|
// Hide model selector (force defaults)
|
|
// Show "Upgrade for more models" message
|
|
// Disable credit topup
|
|
// Disable Ahrefs research
|
|
}
|
|
```
|
|
|
|
### **✅ Pros: Individual Free Accounts**
|
|
1. **Full User Experience** - Users get their own workspace, test all features
|
|
2. **Data Isolation** - Private data, no cross-contamination
|
|
3. **Smooth Upgrade Path** - Existing account → upgrade plan → keep data
|
|
4. **Proper Multi-Tenancy** - Each account is isolated, secure
|
|
5. **Credit Tracking** - Accurate per-user usage analytics
|
|
6. **Marketing Value** - "100 Free Credits" sounds generous
|
|
|
|
### **❌ Cons: Individual Free Accounts**
|
|
1. **Database Growth** - Each user = new Account + User + potential Sites/Keywords
|
|
2. **Abuse Potential** - Users can create multiple emails for free credits
|
|
3. **Complex Enforcement** - Need to enforce model restrictions per account
|
|
4. **Storage Costs** - Each account stores independent data
|
|
5. **Migration Complexity** - If user upgrades, need to handle plan transition
|
|
|
|
### **Effort Estimate: Individual Free Accounts**
|
|
- **Minimal Approach** (Option A): **1 hour**
|
|
- Create free plan via admin
|
|
- Set default models globally
|
|
- Update frontend to hide topup for free users
|
|
|
|
- **Recommended Approach** (Option B): **4-6 hours**
|
|
- Create free plan via admin
|
|
- Update registration to create AISettings per free account
|
|
- Update AI operation logic to read account-specific models
|
|
- Frontend: Hide model selector for free users
|
|
- Testing across all AI operations
|
|
|
|
- **Enterprise Approach** (Option C): **1-2 days**
|
|
- Migration: Add allowed_models fields to Plan
|
|
- Update registration flow
|
|
- Refactor AI operation logic (all modules)
|
|
- Admin UI for plan model management
|
|
- Comprehensive testing
|
|
|
|
---
|
|
|
|
## 🎭 Option 2: Shared Demo Account (Multi-User)
|
|
|
|
### **Concept**
|
|
One demo account shared by multiple users:
|
|
- Users provide email → get "demo access" token
|
|
- Limited operations pool (50-100 per user, tracked separately)
|
|
- Shared data (users see what others created)
|
|
- Pre-configured cheaper AI models
|
|
- No upgrade path (must create new account)
|
|
|
|
### **Implementation Plan**
|
|
|
|
#### **Step 1: Create Demo Account**
|
|
```sql
|
|
-- Create demo plan (internal)
|
|
INSERT INTO igny8_plans (
|
|
name, slug, price, billing_cycle,
|
|
is_internal, is_active,
|
|
max_sites, max_users, max_keywords,
|
|
included_credits, allow_credit_topup
|
|
) VALUES (
|
|
'Demo Access', 'demo', 0.00, 'monthly',
|
|
true, true,
|
|
1, -- 1 demo site
|
|
999, -- Unlimited demo users
|
|
50, -- Limited keywords
|
|
10000, -- Large shared pool
|
|
false
|
|
);
|
|
|
|
-- Create demo account
|
|
INSERT INTO igny8_tenants (
|
|
name, slug, owner_id, plan_id,
|
|
credits, status
|
|
) VALUES (
|
|
'IGNY8 Demo Workspace', 'igny8-demo', 1, -- owner = admin
|
|
(SELECT id FROM igny8_plans WHERE slug='demo'),
|
|
10000, 'active'
|
|
);
|
|
|
|
-- Create demo site
|
|
INSERT INTO igny8_sites (
|
|
name, url, account_id, is_active
|
|
) VALUES (
|
|
'Demo Content Site', 'https://demo.example.com',
|
|
(SELECT id FROM igny8_tenants WHERE slug='igny8-demo'),
|
|
true
|
|
);
|
|
```
|
|
|
|
#### **Step 2: Create DemoUserAccess Model**
|
|
```python
|
|
# In auth/models.py
|
|
class DemoUserAccess(models.Model):
|
|
"""Track individual demo user access and limits"""
|
|
email = models.EmailField(unique=True, db_index=True)
|
|
demo_account = models.ForeignKey(
|
|
'Account',
|
|
on_delete=models.CASCADE,
|
|
related_name='demo_users'
|
|
)
|
|
access_token = models.CharField(max_length=255, unique=True)
|
|
operations_used = models.IntegerField(default=0)
|
|
operations_limit = models.IntegerField(default=50)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
last_accessed = models.DateTimeField(auto_now=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
class Meta:
|
|
db_table = 'igny8_demo_user_access'
|
|
indexes = [
|
|
models.Index(fields=['email', 'is_active']),
|
|
models.Index(fields=['access_token']),
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"Demo: {self.email} ({self.operations_used}/{self.operations_limit})"
|
|
|
|
def has_operations_remaining(self):
|
|
return self.operations_used < self.operations_limit
|
|
```
|
|
|
|
#### **Step 3: Migration**
|
|
```python
|
|
# migrations/0014_demo_user_access.py
|
|
from django.db import migrations, models
|
|
|
|
class Migration(migrations.Migration):
|
|
dependencies = [
|
|
('igny8_core_auth', '0013_add_plan_is_internal'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name='DemoUserAccess',
|
|
fields=[
|
|
('id', models.AutoField(primary_key=True)),
|
|
('email', models.EmailField(unique=True, db_index=True)),
|
|
('demo_account', models.ForeignKey(
|
|
on_delete=models.CASCADE,
|
|
to='igny8_core_auth.Account',
|
|
related_name='demo_users'
|
|
)),
|
|
('access_token', models.CharField(max_length=255, unique=True)),
|
|
('operations_used', models.IntegerField(default=0)),
|
|
('operations_limit', models.IntegerField(default=50)),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('last_accessed', models.DateTimeField(auto_now=True)),
|
|
('is_active', models.BooleanField(default=True)),
|
|
],
|
|
options={'db_table': 'igny8_demo_user_access'},
|
|
),
|
|
]
|
|
```
|
|
|
|
#### **Step 4: Demo Access Endpoint**
|
|
```python
|
|
# In auth/views.py AuthViewSet
|
|
|
|
@action(detail=False, methods=['post'], permission_classes=[])
|
|
def request_demo_access(self, request):
|
|
"""Request demo account access with email only"""
|
|
email = request.data.get('email')
|
|
if not email:
|
|
return error_response(
|
|
error='Email is required',
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
request=request
|
|
)
|
|
|
|
# Validate email format
|
|
from django.core.validators import validate_email
|
|
from django.core.exceptions import ValidationError
|
|
try:
|
|
validate_email(email)
|
|
except ValidationError:
|
|
return error_response(
|
|
error='Invalid email format',
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
request=request
|
|
)
|
|
|
|
# Get demo account
|
|
try:
|
|
demo_account = Account.objects.get(slug='igny8-demo', status='active')
|
|
except Account.DoesNotExist:
|
|
return error_response(
|
|
error='Demo account not configured',
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
request=request
|
|
)
|
|
|
|
# Get or create demo user access
|
|
from .models import DemoUserAccess
|
|
import secrets
|
|
|
|
demo_user, created = DemoUserAccess.objects.get_or_create(
|
|
email=email,
|
|
demo_account=demo_account,
|
|
defaults={
|
|
'access_token': secrets.token_urlsafe(32),
|
|
'operations_limit': 50,
|
|
}
|
|
)
|
|
|
|
if not demo_user.is_active:
|
|
return error_response(
|
|
error='Demo access suspended. Please contact support.',
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
request=request
|
|
)
|
|
|
|
if not demo_user.has_operations_remaining():
|
|
return error_response(
|
|
error='Demo operation limit reached. Please sign up for a full account.',
|
|
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
|
request=request
|
|
)
|
|
|
|
# Generate temporary JWT for demo account
|
|
# (Custom token that includes demo_user_id)
|
|
access_token = generate_demo_access_token(demo_account, demo_user)
|
|
|
|
return success_response(
|
|
data={
|
|
'access_token': access_token,
|
|
'demo_user': {
|
|
'email': demo_user.email,
|
|
'operations_remaining': demo_user.operations_limit - demo_user.operations_used,
|
|
'operations_limit': demo_user.operations_limit,
|
|
},
|
|
'account': {
|
|
'id': demo_account.id,
|
|
'name': demo_account.name,
|
|
'is_demo': True,
|
|
}
|
|
},
|
|
message='Demo access granted' if created else 'Welcome back to demo',
|
|
request=request
|
|
)
|
|
```
|
|
|
|
#### **Step 5: Custom JWT with Demo Context**
|
|
```python
|
|
# In auth/utils.py
|
|
|
|
def generate_demo_access_token(account, demo_user):
|
|
"""Generate JWT for demo access with demo_user context"""
|
|
import jwt
|
|
from datetime import datetime, timedelta
|
|
from django.conf import settings
|
|
|
|
expiry = datetime.utcnow() + timedelta(hours=24) # 24-hour demo session
|
|
|
|
payload = {
|
|
'account_id': account.id,
|
|
'account_slug': account.slug,
|
|
'demo_user_id': demo_user.id,
|
|
'demo_user_email': demo_user.email,
|
|
'is_demo': True,
|
|
'exp': expiry,
|
|
'iat': datetime.utcnow(),
|
|
}
|
|
|
|
return jwt.encode(payload, settings.SECRET_KEY, algorithm='HS256')
|
|
```
|
|
|
|
#### **Step 6: Demo Operation Tracking Middleware**
|
|
```python
|
|
# In middleware/demo_tracking.py
|
|
|
|
class DemoOperationTrackingMiddleware:
|
|
"""Track demo user operations and enforce limits"""
|
|
|
|
def __init__(self, get_response):
|
|
self.get_response = get_response
|
|
|
|
def __call__(self, request):
|
|
# Check if demo user
|
|
if hasattr(request, 'demo_user_id'):
|
|
from igny8_core.auth.models import DemoUserAccess
|
|
|
|
demo_user = DemoUserAccess.objects.select_for_update().get(
|
|
id=request.demo_user_id
|
|
)
|
|
|
|
# Check limit before processing
|
|
if not demo_user.has_operations_remaining():
|
|
return JsonResponse({
|
|
'success': False,
|
|
'error': 'Demo operation limit reached. Please sign up for a full account.',
|
|
'upgrade_url': '/pricing'
|
|
}, status=429)
|
|
|
|
# Store demo_user in request for operation tracking
|
|
request.demo_user = demo_user
|
|
|
|
response = self.get_response(request)
|
|
return response
|
|
|
|
# Add to settings.py MIDDLEWARE
|
|
```
|
|
|
|
#### **Step 7: Update AI Operation Logic**
|
|
```python
|
|
# In ai/services.py or wherever AI operations are tracked
|
|
|
|
def log_ai_operation(account, operation_type, credits_used, **kwargs):
|
|
"""Log AI operation and increment demo counter if demo user"""
|
|
from igny8_core.business.billing.models import CreditUsageLog
|
|
from django.db import transaction
|
|
|
|
with transaction.atomic():
|
|
# Create credit usage log
|
|
CreditUsageLog.objects.create(
|
|
account=account,
|
|
operation_type=operation_type,
|
|
credits_used=credits_used,
|
|
**kwargs
|
|
)
|
|
|
|
# Deduct credits from account
|
|
account.credits -= credits_used
|
|
account.save()
|
|
|
|
# If demo user, increment their personal counter
|
|
from threading import local
|
|
_request = getattr(local(), 'request', None)
|
|
if _request and hasattr(_request, 'demo_user'):
|
|
demo_user = _request.demo_user
|
|
demo_user.operations_used += 1
|
|
demo_user.save()
|
|
```
|
|
|
|
#### **Step 8: Frontend Demo Flow**
|
|
```typescript
|
|
// New demo signup flow
|
|
async function requestDemoAccess(email: string) {
|
|
const response = await api.post('/v1/auth/request-demo-access/', { email });
|
|
|
|
if (response.success) {
|
|
// Store demo token
|
|
localStorage.setItem('demo_token', response.data.access_token);
|
|
localStorage.setItem('is_demo', 'true');
|
|
|
|
// Show demo banner
|
|
showDemoBanner({
|
|
operationsRemaining: response.data.demo_user.operations_remaining,
|
|
operationsLimit: response.data.demo_user.operations_limit,
|
|
});
|
|
|
|
// Redirect to demo workspace
|
|
router.push('/dashboard');
|
|
}
|
|
}
|
|
|
|
// Demo banner component
|
|
<DemoBanner>
|
|
<p>🎭 You're in Demo Mode - {operationsRemaining} operations remaining</p>
|
|
<Button onClick={() => router.push('/pricing')}>
|
|
Upgrade for Full Access
|
|
</Button>
|
|
</DemoBanner>
|
|
|
|
// Disable certain features in demo mode
|
|
if (isDemo) {
|
|
disableFeatures(['integrations', 'automation', 'wordpress_sync']);
|
|
showSharedDataWarning();
|
|
}
|
|
```
|
|
|
|
### **✅ Pros: Shared Demo Account**
|
|
1. **Zero Database Growth** - One account, minimal new records
|
|
2. **Instant Access** - No account creation, just email → token
|
|
3. **Showcase Content** - Users see real AI-generated examples from others
|
|
4. **Anti-Abuse** - Email-based tracking, hard limits per email
|
|
5. **Conversion Pressure** - "See others creating, sign up for your own workspace"
|
|
6. **Cost Efficient** - Shared credit pool, bulk tracking
|
|
|
|
### **❌ Cons: Shared Demo Account**
|
|
1. **No Data Privacy** - All users see shared workspace (could be feature or bug)
|
|
2. **Complex Access Control** - Need custom JWT + middleware + tracking
|
|
3. **No Upgrade Path** - Demo token ≠ real account, must register separately
|
|
4. **Shared Credit Pool** - If pool exhausted, demo is down for everyone
|
|
5. **Feature Limitations** - Can't show integrations, automation, publishing
|
|
6. **User Confusion** - "Why do I see others' content?" + "Lost my demo data!"
|
|
7. **Backend Complexity** - New model, middleware, JWT type, operation tracking
|
|
|
|
### **Effort Estimate: Shared Demo Account**
|
|
**Full Implementation**: **2-3 days**
|
|
- Create demo plan + account + site (1 hour)
|
|
- Create DemoUserAccess model + migration (2 hours)
|
|
- Build request_demo_access endpoint (2 hours)
|
|
- Custom JWT generation with demo context (2 hours)
|
|
- Middleware for demo tracking + limits (3 hours)
|
|
- Update AI operation logging (2 hours)
|
|
- Frontend: Demo flow + banner + restrictions (4 hours)
|
|
- Admin: Dashboard to manage demo users (2 hours)
|
|
- Testing: Edge cases, limits, shared data (4 hours)
|
|
|
|
---
|
|
|
|
## 🎯 Recommendation
|
|
|
|
### **🏆 Winner: Option 1 - Individual Free Accounts (Option B)**
|
|
|
|
**Rationale:**
|
|
1. **Simpler Architecture** - Leverages existing multi-tenancy, no custom JWT/middleware
|
|
2. **Better UX** - Private workspace, smooth upgrade path, feels like real product
|
|
3. **Faster Implementation** - 4-6 hours vs 2-3 days
|
|
4. **Lower Risk** - No shared data confusion, no new access control layer
|
|
5. **Marketing Win** - "100 Free Credits" > "Demo Access with Shared Data"
|
|
6. **Scalable** - If abuse becomes issue, add email verification or captcha
|
|
|
|
**Implementation Checklist:**
|
|
```markdown
|
|
- [ ] Create 'free' plan via Django Admin
|
|
- [ ] Set: included_credits=100, max_sites=1, max_keywords=100
|
|
- [ ] Set: is_internal=true, allow_credit_topup=false
|
|
|
|
- [ ] Verify AI Model Configs exist
|
|
- [ ] GPT-4o Mini (text, cheap)
|
|
- [ ] Hidream Full (image, cheap)
|
|
|
|
- [ ] Update RegisterSerializer (auth/serializers.py)
|
|
- [ ] After account creation for trial status:
|
|
- [ ] Create AISettings for openai (text) → gpt-4o-mini
|
|
- [ ] Create AISettings for runware (images) → hidream-full
|
|
|
|
- [ ] Update Frontend
|
|
- [ ] Hide model selector for free plan
|
|
- [ ] Disable credit topup for free plan
|
|
- [ ] Show "Upgrade for more models" CTA
|
|
|
|
- [ ] Testing
|
|
- [ ] Register new free account
|
|
- [ ] Run text AI operation → verify gpt-4o-mini used
|
|
- [ ] Run image AI operation → verify hidream-full used
|
|
- [ ] Verify 100 credits allocated
|
|
- [ ] Verify upgrade flow works
|
|
```
|
|
|
|
---
|
|
|
|
## 🔮 Future Enhancements (Optional)
|
|
|
|
### For Option 1 (Individual Free Accounts):
|
|
1. **Email Verification** - Require verified email to prevent abuse
|
|
2. **Captcha** - Add reCAPTCHA on free signups
|
|
3. **Usage Analytics** - Track free-to-paid conversion rates
|
|
4. **Referral Credits** - Give 50 bonus credits for referrals
|
|
5. **Time-Limited Trial** - 30-day access instead of credit-limited
|
|
|
|
### For Option 2 (Shared Demo - If Pursued):
|
|
1. **Demo Content Curation** - Pre-seed with high-quality examples
|
|
2. **Demo Reset** - Daily reset to clean state
|
|
3. **Anonymous Mode** - Show "User A, User B" instead of emails
|
|
4. **Live Activity Feed** - "User just generated an article about X"
|
|
5. **Demo Leaderboard** - Gamify the experience
|
|
|
|
---
|
|
|
|
## 📚 Reference Files
|
|
|
|
**Models:**
|
|
- `/backend/igny8_core/auth/models.py` - Account, Plan, User
|
|
- `/backend/igny8_core/business/billing/models.py` - AIModelConfig, CreditTransaction, CreditUsageLog
|
|
- `/backend/igny8_core/modules/system/settings_models.py` - AISettings
|
|
|
|
**Registration:**
|
|
- `/backend/igny8_core/auth/serializers.py` - RegisterSerializer
|
|
- `/backend/igny8_core/auth/views.py` - AuthViewSet.register()
|
|
|
|
**AI Operations:**
|
|
- Check modules: clustering, ideas, content, images for credit deduction logic
|
|
|
|
---
|
|
|
|
## ✅ Decision
|
|
|
|
**Recommended:** Proceed with **Option 1 - Individual Free Accounts (Option B)**
|
|
**Estimated Time:** 4-6 hours
|
|
**Risk Level:** Low
|
|
**User Experience:** Excellent
|
|
|
|
Consider **Option 2** only if:
|
|
- Need to showcase "collaborative" aspect
|
|
- Want zero database growth (high traffic expected)
|
|
- Marketing wants "see what others create" feature
|