MEMORIA FUNCIONAL — HookGenerator
Producto: HookGenerator — Generador de hooks y titulares virales para redes sociales
URL live: https://hookgenerator.theboomer.dev
Stack: React + Vite + React Router (frontend), FastAPI + Motor/MongoDB + OpenAI API (backend), Clerk (auth), Stripe (billing), Ghost CMS (blog), i18next (ES/EN)
Fuente de verdad: code/frontend/src/App.tsx (356 líneas, router + tabs), pages/, context/AuthContext.tsx, services/, i18n/locales/
Fecha de documentación: 2026-08-05
1. Introducción
Propósito
HookGenerator genera hooks y titulares virales para contenido (especialmente videos de YouTube y redes sociales). El usuario introduce un tema, elige proveedor de IA (OpenAI o Gemini), cantidad de hooks (3/5/10) y obtiene una lista de hooks con su estilo identificado (curiosidad, urgencia, storytelling, etc.), cada uno copiable con un clic.
Público objetivo
- Creadores de video (YouTube, TikTok, Shorts/Reels) que necesitan openings irresistibles.
- Marketers de contenido que producen titulares a escala.
- Equipos/agencias (plan Enterprise) con acceso API.
Nota de arquitectura
A diferencia de CaptionAI, esta app usa React Router: rutas públicas (/, /pricing, /blog, /login, /register) y protegidas (/dashboard, /generator, /profile, /usage) dentro de un header global con tabs adicionales (Historial, Facturación, Perfil) gestionados por estado local. La autenticación combina Clerk con un AuthContext propio que provee login/register/logout y un fallback offline cuando falta la publishable key de Clerk. El blog se sirve desde Ghost CMS (services/ghost.service.ts). Nota de CLAUDE.md: este es el frontend "más completo" del grupo, con deployable + Playwright E2E + Stripe + Clerk integrados.
2. Tipos de usuario (roles)
| Rol | Identificación | Capacidades |
|---|---|---|
| Visitante anónimo | Sin sesión Clerk | Ver Landing, Pricing, Blog. Puede usar el Generator (ruta /generator está protegida por ProtectedRoute, pero en la práctica el flujo anónimo de generación existe vía localStorage anon_hooks). Tras su primer hook ve el UpgradeDialog. |
| Usuario registrado (Free) | Sesión Clerk + perfil backend (GET /user/profile) o fallback Clerk |
Dashboard, Generator, Usage, Historial, Perfil, Facturación. Cuota mensual según plan (p. ej. hooks_limit del backend). |
| Pro | Suscripción Stripe (plan pro) |
Más hooks/mes (1.000 según pricing estático), todos los estilos, exportación CSV/JSON, historial completo, soporte prioritario. |
| Enterprise | Suscripción (plan enterprise) |
Hooks ilimitados (hooks_limit === -1), API REST, múltiples usuarios, plantillas personalizadas, gestión de API keys en Perfil. |
3. Funcionalidades
F3.1 Generación de hooks
Descripción: Función principal. POST a /generate (base: VITE_API_URL o http://localhost:8001/api/v1) con {topic, count, provider, model?, api_key?}. Respuesta: HookResponse {success, topic, hooks: string[], count, styles_used: string[]}.
Flujo paso a paso (página /generator):
1. El usuario introduce el tema (input, placeholder "¿De qué quieres generar hooks?").
2. Elige proveedor IA con tabs: OpenAI o Gemini (por defecto openai).
3. Introduce la API key del proveedor en un input tipo password (sk-... para OpenAI, AIza... para Gemini). El backend también acepta OPENAI_API_KEY configurada en servidor; si el usuario deja la key vacía y no hay key en servidor, se muestra el error "API key requerida (o configura OPENAI_API_KEY en el servidor)".
4. Selecciona cantidad de hooks: botones 3 / 5 / 10 (por defecto 5).
5. Pulsa "Generar Hooks" (deshabilitado mientras loading).
6. POST /generate → setHooks(response.hooks) + setStylesUsed(response.styles_used).
7. Si el usuario está logueado, refresca el uso (GET /user/usage).
Validaciones:
- Tema obligatorio: si vacío → error "El tema es obligatorio" (generator.errors.topicRequired).
- API key requerida en cliente (o key de servidor).
- Errores de API: banner rojo con err.message.
- El error y el estado se resetean al iniciar una nueva generación.
F3.2 Copiar hook individual
Flujo: 1. Pulsar botón "Copiar" (ghost) en la card del hook. 2. navigator.clipboard.writeText(hook). 3. El botón cambia a "¡Copiado!" durante 2 segundos (por índice).
F3.3 Indicador de uso (Usage bar)
Descripción: Barra superior del Generator (solo logueados) que muestra consumo mensual.
Flujo: 1. GET /user/usage → UsageStats {month, hooks_used, hooks_limit, remaining, percent_used}. 2. Muestra "X usados / Y restantes" y una barra de progreso (percent_used) si el límite es > 0. 3. Si hooks_limit === -1 muestra "Ilimitado" sin barra.
F3.4 Autenticación (Clerk + AuthContext)
Descripción: Login/registro con Clerk (páginas /login y /register con componentes SignIn/SignUp de Clerk en modo path, con estilos adaptados al tema) y flujo alternativo NoClerkFallback (login/registro contra /auth/login y /auth/register con token en localStorage) cuando falta VITE_CLERK_PUBLISHABLE_KEY.
Flujo:
1. Páginas públicas /login (SignIn) y /register (SignUp), forceRedirectUrl="/dashboard".
2. AuthContext sincroniza: setTokenProvider(() => getToken({template: ''})) para que api.ts inyecte Authorization: Bearer.
3. Tras login, GET /user/profile para obtener el usuario backend; si falla, fallback con datos de Clerk (clerkUserToUser, plan 'free').
4. Google OAuth disponible (signInWithGoogle/signUpWithGoogle → redirect a /dashboard).
5. Logout → signOut() + navegación a /.
F3.5 Rutas protegidas (ProtectedRoute)
Descripción: Wrapper que redirige a /login si no hay usuario.
Flujo: 1. Si auth.loading → spinner full-screen. 2. Si auth.user → renderiza children. 3. Si no → <Navigate to="/login" />. Aplica a /dashboard, /generator, /profile, /usage.
F3.6 Dashboard (Panel)
Descripción: Resumen para usuarios logueados.
Flujo:
1. GET /user/usage al montar; spinner mientras carga.
2. Uso mensual: hooks_used / hooks_limit (o ∞), "X remaining", barra de progreso, o "Unlimited plan" en verde.
3. Plan actual: nombre del plan (user.subscription.display_name o plan o 'Free'); si es free → botón "Upgrade" que enlaza a /billing.
4. Quick Generate: input de tema + botón "Generate" (deshabilitado si vacío); Enter o clic navega a /generator?topic=<tema> (el tema viaja por query string).
5. Recent Activity: si no hay hooks → "No hooks generated yet" + botón "Generate your first hook"; si hay → "X hooks generated this month (YYYY-MM)" + enlace "Generate more →".
F3.7 Página Usage (Uso)
Descripción: Vista detallada de consumo mensual.
Flujo: 1. Carga GET /user/usage. 2. Card "Monthly Usage (YYYY-MM)": hooks usados vs límite, barra de progreso con % usado y restantes. 3. Tres stat cards: This Month (hooks generados), Plan Limit (∞ o límite), Remaining (∞ o restantes).
F3.8 Historial de contenido (vista interna "Historial")
Descripción: Vista por tabs del header (no es una ruta). Lista de contenido generado con búsqueda por tema.
Flujo: 1. Tab "Historial" del header. 2. Input de búsqueda (filtra por tema, case-insensitive). 3. Lista de items {topic, platform, date} con botón "Descargar". 4. Estado actual: la lista se inicializa vacía (useState([])) → siempre muestra "Aún no has generado contenido" (estado placeholder, sin integración backend todavía).
F3.9 Facturación — suscripción Stripe (vista interna "Facturación")
Descripción: Idéntica estructura a CaptionAI: plan actual, PlanCards, paquetes de créditos, historial de facturas.
Flujo:
1. Tab "Facturación" del header → useBilling() carga loadAll() (pricing-plans, summary, invoices).
2. Sin clerk_token en localStorage: solo planes (botones "Inicia sesión"), créditos y prompt de login.
3. Con sesión: tarjeta "Tu Plan" (plan, estado, renovación, cancelación a fin de período, importe/intervalo), grid de planes, créditos ("Comprar"), tabla de facturas (nº, fecha, importe, estado coloreado, "Ver" → hostedUrl).
4. "Suscribirse" → create-checkout-session (successUrl /billing?success=true); "Gestionar facturación" → Customer Portal; "Comprar" créditos → buy-credits.
5. Back button: "Volver a HookGenerator".
F3.10 Perfil (vista interna "Perfil" + ruta /profile)
Descripción: Info de usuario Clerk, plan y uso, y gestión de API keys (Enterprise). Mismo componente que en CaptionAI (bilingüe).
Flujo: 1. Tab "Perfil" del header o ruta /profile. 2. Sin sesión → "Inicia sesión para acceder al perfil". 3. Con sesión: Información del Usuario (avatar, nombre, email, miembro desde), Plan y Uso (plan, límite diario, usados, restantes, créditos extra, acceso API). 4. Claves API: solo Enterprise (bloqueo "Actualiza a Enterprise" + botón "Ver Planes" → /billing si no lo es; generar con nombre, ver mascarada, copiar, revocar con confirmación, IP whitelist).
F3.11 Blog (Ghost CMS)
Descripción: Página /blog alimentada por Ghost (Content API) vía services/ghost.service.ts. Muestra artículos del blog de HookGenerator.
F3.12 Landing page
Descripción: Página pública / con hero, bento de características, sección de precios estáticos y CTA.
Flujo: 1. Hero: título "Crea hooks virales para tu próximo video", subtítulo, CTA "Empezar gratis" (→ /register) y "Ver precios" (→ /#pricing). 2. Features bento (4 cards: 🤖 IA avanzada, 🎨 Múltiples estilos, ⚡ Resultados rápidos, 📊 Analíticas). 3. Precios estáticos hardcodeados: Free $0 ("10 hooks/day", estilos básicos, soporte comunitario), Pro $9.99 ("100 hooks/day", todos los estilos, soporte prioritario, analíticas — marcado "popular"), Enterprise $29.99 (hooks ilimitados, acceso API, soporte dedicado, plantillas personalizadas). CTAs → /register. 4. CTA final ("Listo para destacar" → "Crear cuenta gratis").
F3.13 Página Pricing
Descripción: Página /pricing standalone con 3 planes hardcodeados (Free $0 / Pro $9 / Enterprise $49), toggle Mensual/Anual (visual, -20%), FAQ (4 preguntas) y CTA final.
Flujo: 1. Header propio (logo + "Iniciar sesión" + "Registrarse gratis"). 2. Hero con badge "Planes y Precios". 3. Toggle Mensual/Anual (interruptor visual; los precios no cambian — estático). 4. Cards: Free ("Perfecto para probar", 50 hooks/mes, estilos básicos, exportar a texto, soporte comunitario), Pro ("Para creadores de contenido", 1.000 hooks/mes, todos los estilos, exportar CSV/JSON, historial completo, prioridad en soporte — badge "Más popular"), Enterprise ("Para equipos y agencias", hooks ilimitados, API REST, múltiples usuarios, plantillas personalizadas, soporte dedicado). CTAs → /register. 5. FAQ: cambio de plan, exceso de límite (pausa hasta el siguiente ciclo), período de prueba, facturación mensual. 6. Footer con enlaces Blog/Privacidad/Términos.
F3.14 Selectores de tema e idioma (Navbar)
Descripción: ThemeSelector (claro/oscuro/sistema) y LanguageSelector (ES/EN) en el Navbar sticky. El idioma de i18next se persiste en localStorage.language (default en en i18n/index.ts; el App.tsx usa lang propio con default es para header/badges — doble sistema de i18n coexistente).
F3.15 QuotaBadge y UpgradeDialog
Descripción: Mismos patrones que CaptionAI: badge de cuota (usados/límite) para logueados; UpgradeDialog para anónimos tras el primer hook del día (contador anon_hooks en localStorage) con texto "Crea una cuenta gratis y obten 3 hooks al día!" y botón "Iniciar sesión con Google".
F3.16 Footer
Descripción: Footer global con texto "HookGenerator" (copyright).
4. Pantallas (wireframes textuales)
P4.1 Layout global (header sticky + nav móvil + footer)
┌────────────────────────────────────────────────────────────────────┐
│ HEADER (sticky, backdrop-blur) │
│ ┌──────────┬─────────────────────────────┬───────────────────────┐ │
│ │ [✨] │ Generator│Historial│ │ [QuotaBadge] [Gratis] │ │
│ │ HookGener.│ Facturación│Perfil│Docs │ [avatar] [tema][lang] │ │
│ │ subtitle │ (tabs desktop) │ o [Iniciar sesión] │ │
│ └──────────┴─────────────────────────────┴───────────────────────┘ │
│ MOBILE: tabs Generator|Historial|Facturación|Perfil|Docs │
├────────────────────────────────────────────────────────────────────┤
│ MAIN: view interno (billing/profile/history) o <Routes> público │
│ / /pricing /blog /login /register │
│ /dashboard /generator /profile /usage (protegidas) │
├────────────────────────────────────────────────────────────────────┤
│ FOOTER: "HookGenerator" │
│ [UpgradeDialog] [VersionBadge] │
└────────────────────────────────────────────────────────────────────┘
P4.2 Landing /
┌─ HERO (py-20/32, centrado) ──────────────────────────┐
│ H1: Crea hooks virales para tu próximo video │
│ P: Genera automáticamente openings irresistibles… │
│ [Empezar gratis] [Ver precios] │
├─ FEATURES (bg-muted/30, bento 4 col) ────────────────┤
│ 🤖 IA avanzada 🎨 Múltiples estilos │
│ ⚡ Resultados rápidos 📊 Analíticas │
├─ PRICING (id=pricing, 3 cards) ──────────────────────┤
│ [Free $0] [Pro $9.99 ★popular] [Enterprise $29.99] │
│ cada una: features con ✓ y botón → /register │
├─ CTA (bg-primary) ───────────────────────────────────┤
│ "Listo para destacar" → [Crear cuenta gratis] │
└──────────────────────────────────────────────────────┘
P4.3 Pricing /pricing
┌─ HEADER propio: HookGenerator | Iniciar sesión | Registrarse gratis ┐
│ [Planes y Precios] Elige el plan perfecto para ti │
│ Mensual [toggle] Anual -20% │
│ [Free $0] [Pro $9 ★Más popular] [Enterprise $49] │
│ FAQ (2x2): ¿Puedo cambiar de plan? ¿Qué pasa si excedo mi límite? │
│ ¿Hay período de prueba? ¿Cómo funciona la facturación? │
│ CTA final: ¿Listo para crear contenido viral? → Empezar gratis │
│ Footer: © 2026 | Blog Privacidad Términos │
└─────────────────────────────────────────────────────────────────────┘
P4.4 Login /login y Register /register
┌───────────────────────────────┐
│ HookGenerator │
│ ┌─────────────────────────┐ │
│ │ Clerk <SignIn/SignUp> │ │ (card-stripe, estilos adaptados)
│ │ email + password │ │ → forceRedirect /dashboard
│ │ o botones sociales │ │
│ └─────────────────────────┘ │
│ "¿No tienes cuenta? Regístrate" / "¿Ya tienes cuenta? Inicia sesión" │
└───────────────────────────────┘
P4.5 Dashboard /dashboard (protegido)
Bienvenido, {nombre}!
USO (2 cards)
┌─ Monthly Usage ────────┐ ┌─ Current Plan ────────┐
│ 12 / 50 │ │ FREE (capitalize) │
│ 38 restantes │ │ [Upgrade → /billing] │
│ [████████░░] progreso │ │ (si plan free) │
└────────────────────────┘ └────────────────────────┘
QUICK GENERATE
[input tema............] [Generate] → /generator?topic=
RECENT ACTIVITY
"No hooks generated yet. Start creating!" [Generate your first hook]
— o — "12 hooks generated this month (2026-08)" Generate more →
P4.6 Generator /generator (protegido, grid 5 cols: form 2 / resultados 3)
┌──────────────┬────────────────────────────────────────────┐
│ FORM (col-2) │ RESULTADOS (col-3) │
│ ┌──────────┐ │ [banner error rojo si error] │
│ │ Tema │ │ ┌─ Resultados ───────────────────────────┐ │
│ │ [input…] │ │ │ Estado vacío: │ │
│ │ │ │ │ ✨ Ingresa un tema y haz clic en │ │
│ │ Proveedor│ │ │ "Generar Hooks" │ │
│ │ IA │ │ │ Estado carga: spinner + "Generando…" │ │
│ │ [OpenAI| │ │ │ Estado con resultados: │ │
│ │ Gemini] │ │ │ ┌─ hook card ───────────────────────┐ │ │
│ │ [API key │ │ │ │ hook texto (multi-línea) │ │ │
│ │ sk-… │ │ │ │ [PREGUNTA badge] [Copiar] │ │ │
│ │ (pass)] │ │ │ └──────────────────────────────────┘ │ │
│ │ │ │ │ (…una card por hook, badge con estilo│ │
│ │ Cantidad │ │ │ del array styles_used) │ │
│ │ [3][5][10]│ │ └──────────────────────────────────────┘ │
│ │ │ │ │
│ │ [Generar │ │ │
│ │ Hooks] │ │ │
│ └──────────┘ │ │
│ (arriba: barra uso "X usados / Y restantes" + progreso │
│ si logueado) │
└──────────────┴────────────────────────────────────────────┘
P4.7 Usage /usage (protegido)
Usage
┌─ Monthly Usage (2026-08) ──────────────────────┐
│ 12 hooks used 50 limit │
│ [████████████░░░░] progreso h-3 │
│ 24% used 38 remaining │
└────────────────────────────────────────────────┘
┌─ This Month ──┐ ┌─ Plan Limit ──┐ ┌─ Remaining ──┐
│ 12 │ │ 50 │ │ 38 │
└───────────────┘ └───────────────┘ └──────────────┘
P4.8 Vista Historial (tab header)
[← Volver]
Historial de Contenido — Tu contenido generado anteriormente
[🔍 Buscar por tema.....................]
┌────────────────────────────────────────────┐
│ (estado actual: lista vacía) │
│ [📄] Aún no has generado contenido │
└────────────────────────────────────────────┘
— o — [item: tema | plataforma · fecha | Descargar]
P4.9 Vista Facturación (tab header)
[← Volver a HookGenerator]
Facturación — Gestiona tu suscripción y facturación [Gestionar facturación ↗]
┌─ TU PLAN ───────────────────────────┐
│ Suscrito a: Pro [Activo🟢] │
│ Fecha de renovación: … │
│ 9.00 EUR/month │
└─────────────────────────────────────┘
┌─ PLANES DE PRECIOS ────────────────┐
│ [PlanCard Free] [Pro] [Enterprise] │
└────────────────────────────────────┘
┌─ PAQUETES DE CRÉDITOS ─────────────┐
│ [1000 créditos €X Comprar] … │
└────────────────────────────────────┘
┌─ HISTORIAL DE FACTURAS ────────────┐
│ Nº | Fecha | Importe | Estado | Ver │
└────────────────────────────────────┘
P4.10 Vista Perfil (tab header) y ruta /profile
[← Volver]
Perfil — Gestiona la configuración de tu cuenta
┌─ INFORMACIÓN DEL USUARIO ──┐ ┌─ PLAN Y USO ────────────┐
│ [avatar] Nombre │ │ Plan: PRO │
│ email │ │ Límite diario: 100 │
│ Miembro desde: … │ │ Usados/Restantes │
│ │ │ Créditos Extra: 0 │
└────────────────────────────┘ │ Acceso API: Activado │
└─────────────────────────┘
┌─ CLAVES API (Enterprise only) ──────────────────────┐
│ no-Enterprise: [🛡] Actualiza a Enterprise [Ver Planes]│
│ Enterprise: [+ Generar Clave API] · lista · whitelist│
└──────────────────────────────────────────────────────┘
P4.11 Blog /blog
Header del sitio | Lista de artículos de Ghost CMS (cards) | Footer
P4.12 Modal UpgradeDialog
┌─ overlay ──────────────────────────┐
│ ┌───────────────────────────────┐ │
│ │ [✨] [X] │ │
│ │ Desbloquea más hooks │ │
│ │ Crea una cuenta gratis y │ │
│ │ obten 3 hooks al día! │ │
│ │ [G Iniciar sesión con Google] │ │
│ └───────────────────────────────┘ │
└────────────────────────────────────┘
5. Flujos de trabajo
Flujo A: Alta
- Visitante llega a
/(Landing) o/pricing. - Pulsa "Empezar gratis" / "Crear cuenta gratis" →
/register(Clerk SignUp). - Tras registrarse,
forceRedirectUrl="/dashboard". - AuthContext obtiene perfil backend (
GET /user/profile); si el backend no responde, usa datos de Clerk con plan 'free'. - Alternativa: Google OAuth (login o registro) →
/dashboard. - Fallback sin Clerk key: login/registro contra
/auth/loginy/auth/register(token + user en localStorage).
Flujo B: Configuración y generación
- Desde Dashboard (Quick Generate) o
/generator(el tema puede llegar pre-relleno vía?topic=). - En
/generator: tema → proveedor (OpenAI/Gemini) → API key → cantidad (3/5/10). - Pulsar "Generar Hooks" → validación (tema + API key) → POST
/generate. - Ver spinner "Generando hooks..." y luego la lista de hooks con badges de estilo.
- Copiar hooks individuales (feedback "¡Copiado!" por 2s).
Flujo C: Consumo y límites
- El usuario logueado ve su uso en el Generator (barra), Dashboard y Usage.
- Si el plan es limitado y se acerca al límite, la barra de progreso crece; al llegar al 100% (o superar
hooks_limit) el backend bloquea nuevas generaciones ("No te quedan regeneraciones disponibles"). - Con plan ilimitado (
hooks_limit === -1) no hay restricciones.
Flujo D: Billing
- Tab "Facturación" o botón "Upgrade" del Dashboard.
- Ver planes; "Suscribirse" → Stripe Checkout → retorno a
/billing?success=true. - "Gestionar facturación" → Customer Portal (cambiar/cancelar suscripción).
- Créditos extra opcionales ("Comprar").
Flujo E: Perfil y API keys (Enterprise)
- Tab "Perfil" → datos de usuario, plan y consumo.
- Enterprise: generar API key con nombre (visible una sola vez), copiar, revocar con confirmación, IP whitelist.
- No-Enterprise: CTA "Ver Planes" →
/billing.
Flujo F: Historial
- Tab "Historial" → búsqueda por tema + lista con descarga.
- Estado actual: placeholder vacío (sin persistencia backend aún).
6. Reglas de negocio
| Regla | Detalle |
|---|---|
| Cuota mensual por plan | UsageStats.hooks_limit define el límite mensual (Free: 50/mes según Pricing estático; Pro: 1.000; Enterprise: -1 = ilimitado). hooks_used, remaining, percent_used vienen del backend (GET /user/usage). |
| Generación requiere API key | El frontend exige API key del proveedor (OpenAI/Gemini) o la key del servidor (OPENAI_API_KEY). Sin ninguna → error visible. |
| Proveedores soportados | openai y gemini (tabs). El campo model se envía como undefined si está vacío (backend decide el modelo). |
| Cantidad de hooks | Solo 3, 5 o 10 (botones). |
| Estilos de hooks | El backend devuelve styles_used[] alineado con hooks[]; la UI los muestra como badges (fallback "PREGUNTA" si falta). |
| Quota anónima | Contador diario anon_hooks en localStorage; tras el primer hook del día se muestra el UpgradeDialog ("3 hooks al día!"). |
| Quota logueados | usage_log en localStorage alimenta el QuotaBadge (límite del plan vía stripe.getPricingPlans()/getSummary(); default free 3). |
| Rutas protegidas | /dashboard, /generator, /profile, /usage redirigen a /login si no hay sesión; spinner mientras AuthContext carga. |
| Planes estáticos (Landing/Pricing) | Precios hardcodeados que no están conectados a Stripe en esas páginas (Free $0, Pro $9.99/$9, Enterprise $29.99/$49, toggle anual -20% solo visual). El billing real (con Stripe) vive en la vista Facturación con planes desde /api/v1/billing/pricing-plans. |
| Suscripción Stripe | Detectada por GET /api/v1/billing/summary; estados: active=verde, resto=ámbar; cancelAtPeriodEnd → aviso "Se cancelará al final del período". |
| Facturas | Estados: paid (verde), open (ámbar), uncollectible (rojo), void (gris). |
| API keys | Solo plan Enterprise; gestión en Perfil (/api/v1/api-keys*). El bloqueo muestra "Actualiza a Enterprise" con CTA a /billing. |
| Auth | Clerk es el proveedor principal; AuthContext añade capa propia con fallback localStorage; token vía setTokenProvider → header Authorization: Bearer en todas las llamadas api.*. |
| i18n | Doble sistema: react-i18next (localStorage.language, default en) para páginas de router, y objeto i18n inline del App.tsx (localStorage.lang, default es) para header/badges/vistas internas. |
| Tema | ThemeContext/selector: dark (default), light, system; clase dark en <html>. |
Endpoints consumidos por el frontend
POST /generate(baseVITE_API_URL/localhost:8001/api/v1) — generación de hooks{topic, count, provider, model?, api_key?}.GET /user/profile,PUT /user/profile— perfil de usuario.GET /user/usage— estadísticas de uso mensual.GET /user/plans— planes disponibles.POST /auth/login,POST /auth/register— auth fallback (sin Clerk key).GET /api/v1/billing/pricing-plans·create-checkout-session·create-portal-session·summary·invoices·credit-packs·buy-credits— billing Stripe./api/v1/api-keys*— gestión de API keys (Enterprise).- Ghost Content API — blog (
services/ghost.service.ts).