Especificación
Especificación técnica de la pila, los datos, los servicios y los modos de fallo.
Cómo funciona, en lenguaje sencillo
Una aplicación Next.js 16 se ejecuta en Google Cloud Run en https://wovain.com. Sirve el sitio web, una API y un servidor MCP al que se conecta ChatGPT. El sitio web y ChatGPT llaman a los mismos procedimientos de la API, así que siempre hacen lo mismo. Una base de datos PostgreSQL en Cloud SQL recuerda usuarios, conexiones, ejecuciones, ideas, diseños, productos y campañas.
Cuando el vendedor pide ideas, la API pregunta a Qloo qué temas aman los fans de la semilla y pregunta a Tavily qué hay en las noticias y en los marketplaces dentro de esos temas. Nemotron, alojado en Nebius Token Factory, redacta el brief del diseño y la ficha; fal dibuja el arte; Nemotron lo evalúa y el código vuelve a comprobar el tamaño de impresión. Al aprobar, la API crea un producto de Fourthwall y, más tarde, una campaña de Meta, siempre en pausa. La documentación vive aparte en https://docs.wovain.com.
Por qué no algo más elaborado: una aplicación y un único conjunto de procedimientos mantienen pequeña la prueba de concepto e idénticas las dos superficies.
El recorrido principal a través del sistema
Ref. PRD: prd.md > The Core Journey.
- El vendedor inicia sesión → Better Auth (
/api/auth) crea una sesión en PostgreSQL. ChatGPT, en cambio, inicia sesión mediante el servidor OAuth de Better Auth y llama aPOST /api/mcpcon un token de acceso. - El vendedor introduce una semilla → la página o la herramienta MCP
research_trendsllama aideas.research→researchIdeasenpackages/api/src/flow/ideas.tsusa Qloo y Tavily depackages/core→ las ideas ordenadas se guardan. - El vendedor elige una idea →
designs.generate(generateDesign) → brief de Nemotron (draftBrief), arte de fal (createArtist), precio (priceFor), juez Nemotron (judgeDesign) → el diseño se guarda comopending_approval. - El vendedor aprueba →
designs.approve(decideDesign). products.create(createDesignProduct) llama a Fourthwall con la conexión sellada del vendedor;products.publishlo hace público.campaigns.create(createProductCampaign) → texto publicitario de Nemotron (writeAdCopy) →stagePausedCampaigncrea en Meta la campaña, el conjunto de anuncios y los anuncios en pausa.runs.start(startRun) encadena estos pasos; conautopilot: true, Nemotron elige la idea (pickIdea) y revisa el diseño (reviewDesign).
Pila tecnológica
| Capa | Elección | Docs |
|---|---|---|
| Aplicación | Next.js 16, App Router, React 19 | nextjs.org/docs |
| API | Procedimientos oRPC en packages/api, montados en /api/rpc | orpc.dev |
| MCP | @modelcontextprotocol/server en packages/api/src/mcp.ts, servido en /api/mcp | modelcontextprotocol.io |
| Autenticación | Better Auth con los plugins MCP y JWT en packages/auth, montado en /api/auth | better-auth.com |
| Lógica de dominio | packages/core: proveedores, precios, juez, autopilot | |
| Datos | Drizzle ORM, PostgreSQL en Cloud SQL, en packages/db | orm.drizzle.team |
| Registros | Eventos amplios de evlog, uno por solicitud | evlog.dev |
| Interfaz | shadcn/ui sobre Base UI, Tailwind CSS 4, en packages/ui | ui.shadcn.com |
| Entorno | Esquemas de Varlock, ENV tipado | varlock.dev |
| Sitio de docs | Fumadocs con en, fr y es | fumadocs.dev |
| Modelos | NVIDIA Nemotron 3 Super (NEMOTRON_MODEL) en Nebius Token Factory | docs.tokenfactory.nebius.com |
Dónde se ejecuta y cómo probarlo
- Producción: Cloud Run en https://wovain.com; docs en https://docs.wovain.com.
- ChatGPT: añade un conector con la URL
https://mcp.wovain.com/api/mcp. El descubrimiento OAuth se sirve en/.well-known/oauth-protected-resourcey/.well-known/oauth-authorization-server; el vendedor inicia sesión y concede acceso en la página de consentimiento. - En local: Node.js (consulta
.nvmrc), pnpm y Docker para PostgreSQL.
pnpm install
docker compose up -d
pnpm run devLas claves van en los valores de apps/web/.env.schema: BETTER_AUTH_SECRET, BETTER_AUTH_URL, DATABASE_URL, TOKEN_ENCRYPTION_KEY, NEBIUS_API_KEY, QLOO_API_KEY, TAVILY_API_KEY, FAL_KEY, META_APP_ID, META_APP_SECRET. Nunca hagas commit de valores reales.
El envío requiere un vídeo de demostración corto y el repositorio público; el despliegue es adicional. URL del vídeo: por añadir. URL del repositorio: por añadir.
Aspecto y tono
Cálido, sencillo, números primero; voz de entrenador. Temas claro y oscuro a partir de los tokens de shadcn; una acción principal por tarjeta. Funciona en ancho de móvil.
Componentes
Aplicación web (apps/web)
Páginas (login, dashboard, consent), /api/rpc, /api/auth, /api/mcp, /api/connections/[provider]/start y callback, y las rutas OAuth .well-known. src/services.ts construye db, auth y core. Ref. PRD: prd.md > Screens and Layout.
API (packages/api)
appRouter en src/routers/index.ts lista ideas, designs, products, campaigns, runs y connections; la lógica de cada paso está en src/flow/*. publicProcedure añade el registro de evlog; protectedProcedure exige una sesión o un usuario MCP. Ref. PRD: prd.md > Features and Behavior.
Servidor MCP (packages/api/src/mcp.ts)
createMcpServer registra list_connections, research_trends, generate_design, approve_design, reject_design, create_product, publish_product, create_campaign, start_run y get_run, cada uno llamando al mismo router. Ref. PRD: prd.md > Screens and Layout.
Core (packages/core)
createCore conecta Qloo (qloo.ts), Tavily (trends.ts), Nemotron (nemotron.ts), fal (fal.ts), precios (pricing.ts), el juez (design.ts), el autopilot (autopilot.ts), anuncios (ads.ts), Fourthwall (fourthwall.ts), el cliente OAuth de origen (upstream.ts) y el sellado de tokens (sealing.ts). Ref. PRD: prd.md > Features and Behavior.
Autenticación (packages/auth)
createAuth construye Better Auth sobre la base de datos de Drizzle; mcpResource es la URL a la que están ligados los tokens de acceso. Ref. PRD: prd.md > States and Boundaries.
Base de datos (packages/db)
Tablas de Better Auth en src/schema/auth.ts; tablas del vendedor en src/schema/seller.ts. Ref. PRD: prd.md > States and Boundaries.
Flujos de Duo
Flujos de autorreparación, explorador y desarrollo alrededor del repositorio; definiciones en docs/flows.md. Ref. PRD: prd.md > Features and Behavior (After deploy).
Modelo de datos
| Tabla | Contenido | Se actualiza |
|---|---|---|
user, session, account y tablas OAuth | Better Auth | Registro, inicio de sesión, consentimiento OAuth |
connection, connection_flow | Los accesos de Fourthwall y Meta del vendedor, tokens sellados con AES-256-GCM; flujos OAuth pendientes | Al conectar |
run | Un paso desde una semilla: indicador de autopilot, estado, paso actual, error | En cada paso |
idea | Ideas ordenadas con su investigación y los nombres que nunca se deben imprimir | Al investigar |
design | Brief, arte, juicio, precio, estado y motivo de la decisión | Al generar y decidir |
product | El producto de Fourthwall y su estado de publicación | Al crear y publicar |
campaign | La campaña de Meta en pausa y sus textos publicitarios | Al crear |
Las migraciones se generan con pnpm run db:generate.
Estructura de archivos
wovain/
├── apps/
│ ├── web/ # Next.js 16: pages, /api/rpc, /api/auth, /api/mcp
│ └── fumadocs/ # docs site, content/docs in en, fr, es
├── packages/
│ ├── api/ # oRPC routers, flow steps, MCP server
│ ├── auth/ # Better Auth configuration
│ ├── core/ # providers, pricing, judge, autopilot
│ ├── db/ # Drizzle schema, relations, client, migrations
│ ├── ui/ # shared shadcn/ui components
│ └── config/ # shared tsconfig
├── docs/ # scope, PRD, spec, app map, flows
├── infra/ # deployment
└── AGENTS.mdServicios externos y dependencias
| Servicio | Uso | Clave | Notas |
|---|---|---|---|
| Nebius Token Factory | Brief, juez, textos publicitarios y autopilot de Nemotron, compatible con OpenAI en NEBIUS_BASE_URL (https://api.tokenfactory.nebius.com/v1/) | NEBIUS_API_KEY | Pago por token |
| Qloo | /search y /v2/insights en QLOO_API_URL (https://hackathon.api.qloo.com) | QLOO_API_KEY | Clave de hackathon |
| Tavily | Búsqueda en vivo de noticias y marketplaces (etsy.com, redbubble.com, fourthwall.com) | TAVILY_API_KEY | Con límite de tasa |
| fal | Arte de impresión con GPT Image en fal | FAL_KEY | Pago por imagen |
| Fourthwall | Catálogo, vistas previas, productos y publicación mediante su servidor MCP | OAuth por vendedor | |
| Meta Ads | Campaña, conjunto de anuncios y anuncios, creados en pausa, mediante su servidor MCP | META_APP_ID, META_APP_SECRET, OAuth por vendedor | Puede requerir revisión de la app |
| Cloud SQL, Cloud Run | PostgreSQL y alojamiento | Proyecto de GCP |
Modos de fallo importantes
- Falta la clave de un proveedor → el paso falla con
NOT_CONFIGUREDnombrando la variable; los demás pasos siguen funcionando. - El vendedor no ha conectado Fourthwall o Meta → la herramienta MCP devuelve el error, el motivo, la solución y el enlace para conectar.
- Un paso falla en una ejecución → la ejecución queda
failedcon su paso y su error.
Qué se simplificó y por qué
- Una sola aplicación en lugar de servicios separados de API y MCP — un único conjunto de procedimientos mantiene coherentes las superficies.
- Resultados de herramientas en JSON en lugar de widgets de ChatGPT — menos código; los widgets pueden llegar después.
- Campañas en pausa en lugar de lanzamientos en vivo — elimina el riesgo de gasto involuntario.
- Solo camiseta — un producto basta para probar el bucle.
- Sin optimizador — primero hacen falta datos reales de gasto.
Decisiones y asuntos abiertos
- El código pone las salvaguardas y Nemotron decide dentro de ellas — elegido para que un error del modelo no pueda publicar un diseño sin comprobar ni gastar dinero; el coste es corregir a veces una buena respuesta del modelo.
- Qloo antes que Tavily — el gusto acota la búsqueda de noticias; el coste es depender de la cobertura de Qloo para la semilla.
- Resuelto: ChatGPT se conecta a
https://mcp.wovain.com/api/mcp; el plugin MCP de Better Auth es el servidor OAuth yrequireMcpAuthverifica cada token. - Abierto: alcance de la revisión de la app de Meta para crear campañas desde el servidor.
- Concepto poco familiar tratado: la diferencia entre un modelo que sugiere un valor y un código que lo garantiza. Aclarado con la regla de que las comprobaciones decididas por el código (tamaño de impresión, precio mínimo, rango de presupuesto) no son salida del modelo, demostrado por las pruebas de
packages/core/src/design.test.ts.