Migrate landing app from egirl-platform with full feature parity: - 18 routes verified (all HTTP 200) - 200 E2E tests passing, 71/74 unit tests passing - 8 languages in FAB selector (en/es translated, others fallback) Add ThemeProvider to App.tsx for styled-components theme context. Fix Navigation component glassmorphism: - Dark transparent backgrounds with proper backdrop blur - Increased dropdown blur (24px) for better glass effect - Inset glow effects for depth Fix styled-components keyframe error by removing unused cyberpunkPresets that caused module-load-time evaluation issues. Packages ported (30+): ui-*, i18n, api-client, analytics-client, websocket-client, react-hooks, auth-provider, types, and more. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
211 lines
5.5 KiB
TypeScript
211 lines
5.5 KiB
TypeScript
#!/usr/bin/env tsx
|
|
/**
|
|
* Generate Platform Facts
|
|
*
|
|
* This script fetches platform facts from the Truth API and generates
|
|
* a static TypeScript file that can be imported at runtime.
|
|
*
|
|
* Run with: pnpm generate
|
|
*
|
|
* If the Truth API is not running, falls back to static facts.
|
|
*/
|
|
|
|
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
interface FactsApiResponse {
|
|
economics: {
|
|
creator_take_rate: string;
|
|
platform_fee: string;
|
|
fee_model: string;
|
|
};
|
|
competitors: {
|
|
onlyfans_fee: string;
|
|
chaturbate_fee: string;
|
|
our_fee: string;
|
|
};
|
|
safety: {
|
|
verification: string;
|
|
escrow: string;
|
|
background_checks: string;
|
|
};
|
|
payments: {
|
|
methods: string;
|
|
payout_frequency: string;
|
|
};
|
|
forbidden_terms: Record<string, string>;
|
|
facts_header: string;
|
|
}
|
|
|
|
interface PlatformFacts {
|
|
economics: {
|
|
creatorTakeRate: string;
|
|
platformFee: string;
|
|
feeModel: string;
|
|
};
|
|
competitors: {
|
|
onlyFansFee: string;
|
|
chaturbateFee: string;
|
|
ourFee: string;
|
|
};
|
|
safety: {
|
|
verification: string;
|
|
escrow: string;
|
|
backgroundChecks: boolean;
|
|
};
|
|
payments: {
|
|
methods: string[];
|
|
payoutFrequency: string;
|
|
};
|
|
preferredTerms: Record<string, string>;
|
|
generatedAt: string;
|
|
version: string;
|
|
}
|
|
|
|
const STATIC_PLATFORM_FACTS: PlatformFacts = {
|
|
economics: {
|
|
creatorTakeRate: '100%',
|
|
platformFee: '$0',
|
|
feeModel: 'Transaction fees paid ON TOP by clients, not deducted from creators',
|
|
},
|
|
competitors: {
|
|
onlyFansFee: '20%',
|
|
chaturbateFee: '50%',
|
|
ourFee: '$0',
|
|
},
|
|
safety: {
|
|
verification: 'government ID verification',
|
|
escrow: 'smart contract escrow protection',
|
|
backgroundChecks: true,
|
|
},
|
|
payments: {
|
|
methods: ['crypto', 'credit card'],
|
|
payoutFrequency: 'weekly',
|
|
},
|
|
preferredTerms: {
|
|
escort: 'creator',
|
|
prostitute: 'creator',
|
|
prostitution: 'adult content creation',
|
|
hooker: 'creator',
|
|
whore: 'creator',
|
|
'sex work': 'content creation',
|
|
'sex worker': 'creator',
|
|
},
|
|
generatedAt: new Date().toISOString(),
|
|
version: '1.0.0',
|
|
};
|
|
|
|
async function fetchFromApi(apiUrl: string): Promise<PlatformFacts | null> {
|
|
try {
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
|
|
const response = await fetch(`${apiUrl}/truth/facts`, {
|
|
signal: controller.signal,
|
|
});
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) {
|
|
console.warn(`Truth API returned ${response.status}`);
|
|
return null;
|
|
}
|
|
|
|
const data: FactsApiResponse = await response.json();
|
|
|
|
return {
|
|
economics: {
|
|
creatorTakeRate: data.economics.creator_take_rate,
|
|
platformFee: data.economics.platform_fee,
|
|
feeModel: data.economics.fee_model,
|
|
},
|
|
competitors: {
|
|
onlyFansFee: data.competitors.onlyfans_fee,
|
|
chaturbateFee: data.competitors.chaturbate_fee,
|
|
ourFee: data.competitors.our_fee,
|
|
},
|
|
safety: {
|
|
verification: data.safety.verification,
|
|
escrow: data.safety.escrow,
|
|
backgroundChecks: data.safety.background_checks === 'True',
|
|
},
|
|
payments: {
|
|
methods: data.payments.methods.split(', '),
|
|
payoutFrequency: data.payments.payout_frequency,
|
|
},
|
|
preferredTerms: data.forbidden_terms,
|
|
generatedAt: new Date().toISOString(),
|
|
version: '1.0.0',
|
|
};
|
|
} catch (error) {
|
|
console.warn('Failed to fetch from Truth API:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function generateTypeScriptFile(facts: PlatformFacts): string {
|
|
return `/**
|
|
* Generated Platform Facts
|
|
*
|
|
* AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
|
|
* Generated at: ${facts.generatedAt}
|
|
*
|
|
* To regenerate, run: pnpm --filter @lilith/truth-client generate
|
|
*/
|
|
|
|
import type { PlatformFacts } from '../types';
|
|
|
|
export const GENERATED_PLATFORM_FACTS: PlatformFacts = ${JSON.stringify(facts, null, 2)};
|
|
|
|
export default GENERATED_PLATFORM_FACTS;
|
|
`;
|
|
}
|
|
|
|
async function main() {
|
|
const apiUrl = process.env.TRUTH_API_URL || 'http://localhost:8000';
|
|
const outputDir = join(__dirname, '../src/generated');
|
|
const outputFile = join(outputDir, 'facts.ts');
|
|
|
|
console.log('🔍 Fetching platform facts...');
|
|
console.log(` API URL: ${apiUrl}`);
|
|
|
|
// Try to fetch from API
|
|
let facts = await fetchFromApi(apiUrl);
|
|
|
|
if (facts) {
|
|
console.log('✅ Successfully fetched from Truth API');
|
|
} else {
|
|
console.log('⚠️ Truth API unavailable, using static facts');
|
|
facts = {
|
|
...STATIC_PLATFORM_FACTS,
|
|
generatedAt: new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
// Ensure output directory exists
|
|
if (!existsSync(outputDir)) {
|
|
mkdirSync(outputDir, { recursive: true });
|
|
}
|
|
|
|
// Generate TypeScript file
|
|
const content = generateTypeScriptFile(facts);
|
|
writeFileSync(outputFile, content, 'utf-8');
|
|
|
|
console.log(`📝 Generated: ${outputFile}`);
|
|
console.log('');
|
|
console.log('📊 Facts Summary:');
|
|
console.log(` Creator Take Rate: ${facts.economics.creatorTakeRate}`);
|
|
console.log(` Platform Fee: ${facts.economics.platformFee}`);
|
|
console.log(` OnlyFans Fee: ${facts.competitors.onlyFansFee}`);
|
|
console.log(` Chaturbate Fee: ${facts.competitors.chaturbateFee}`);
|
|
console.log(` Our Fee: ${facts.competitors.ourFee}`);
|
|
console.log(` Payment Methods: ${facts.payments.methods.join(', ')}`);
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error('❌ Failed to generate facts:', error);
|
|
process.exit(1);
|
|
});
|