Spécification
Spécification technique de la pile, des données, des services et des modes de défaillance.
Comment ça marche, en langage simple
Une application Next.js 16 s'exécute sur Google Cloud Run à https://wovain.com. Elle sert le site web, une API et un serveur MCP auquel ChatGPT se connecte. Le site web et ChatGPT appellent les mêmes procédures d'API : ils font donc toujours la même chose. Une base PostgreSQL sur Cloud SQL mémorise les utilisateurs, connexions, exécutions, idées, designs, produits et campagnes.
Quand le vendeur demande des idées, l'API demande à Qloo quels thèmes aiment les fans de la graine et demande à Tavily ce qui est dans l'actualité et sur les places de marché dans ces thèmes. Nemotron, hébergé sur Nebius Token Factory, rédige le brief de design et la fiche produit ; fal dessine l'illustration ; Nemotron l'évalue et le code revérifie la taille d'impression. À l'approbation, l'API crée un produit Fourthwall puis, plus tard, une campagne Meta, toujours en pause. La documentation vit séparément sur https://docs.wovain.com.
Pourquoi pas quelque chose de plus élaboré : une application et un seul jeu de procédures gardent la preuve de concept petite et les deux surfaces identiques.
Le parcours principal à travers le système
Réf. PRD : prd.md > The Core Journey.
- Le vendeur se connecte → Better Auth (
/api/auth) crée une session dans PostgreSQL. ChatGPT se connecte plutôt via le serveur OAuth de Better Auth et appellePOST /api/mcpavec un jeton d'accès. - Le vendeur saisit une graine → la page ou l'outil MCP
research_trendsappelleideas.research→researchIdeasdanspackages/api/src/flow/ideas.tsutilise Qloo et Tavily depuispackages/core→ les idées classées sont enregistrées. - Le vendeur choisit une idée →
designs.generate(generateDesign) → brief Nemotron (draftBrief), illustration fal (createArtist), prix (priceFor), juge Nemotron (judgeDesign) → le design est enregistré enpending_approval. - Le vendeur approuve →
designs.approve(decideDesign). products.create(createDesignProduct) appelle Fourthwall via la connexion scellée du vendeur ;products.publishle rend public.campaigns.create(createProductCampaign) → texte publicitaire Nemotron (writeAdCopy) →stagePausedCampaigncrée la campagne, l'ensemble de publicités et les publicités en pause sur Meta.runs.start(startRun) enchaîne ces étapes ; avecautopilot: true, Nemotron choisit l'idée (pickIdea) et relit le design (reviewDesign).
Pile technique
| Couche | Choix | Docs |
|---|---|---|
| Application | Next.js 16, App Router, React 19 | nextjs.org/docs |
| API | Procédures oRPC dans packages/api, montées sur /api/rpc | orpc.dev |
| MCP | @modelcontextprotocol/server dans packages/api/src/mcp.ts, servi sur /api/mcp | modelcontextprotocol.io |
| Authentification | Better Auth avec les plugins MCP et JWT dans packages/auth, monté sur /api/auth | better-auth.com |
| Logique métier | packages/core : fournisseurs, prix, juge, autopilot | |
| Données | Drizzle ORM, PostgreSQL sur Cloud SQL, dans packages/db | orm.drizzle.team |
| Journaux | Événements larges evlog, un par requête | evlog.dev |
| Interface | shadcn/ui sur Base UI, Tailwind CSS 4, dans packages/ui | ui.shadcn.com |
| Environnement | Schémas Varlock, ENV typé | varlock.dev |
| Site de docs | Fumadocs en en, fr et es | fumadocs.dev |
| Modèles | NVIDIA Nemotron 3 Super (NEMOTRON_MODEL) sur Nebius Token Factory | docs.tokenfactory.nebius.com |
Où cela s'exécute et comment l'essayer
- Production : Cloud Run sur https://wovain.com ; docs sur https://docs.wovain.com.
- ChatGPT : ajoutez un connecteur avec l'URL
https://mcp.wovain.com/api/mcp. La découverte OAuth est servie sur/.well-known/oauth-protected-resourceet/.well-known/oauth-authorization-server; le vendeur se connecte et accorde l'accès sur la page de consentement. - En local : Node.js (voir
.nvmrc), pnpm et Docker pour PostgreSQL.
pnpm install
docker compose up -d
pnpm run devLes clés vont dans les valeurs 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. Ne commitez jamais de vraies valeurs.
La soumission exige une courte vidéo de démo et le dépôt public ; le déploiement s'y ajoute. URL de la vidéo : à ajouter. URL du dépôt : à ajouter.
Style et ambiance
Chaleureux, simple, chiffres d'abord ; voix de coach. Thèmes clair et sombre issus des tokens shadcn ; une action principale par carte. Fonctionne en largeur de téléphone.
Composants
Application web (apps/web)
Pages (login, dashboard, consent), /api/rpc, /api/auth, /api/mcp, /api/connections/[provider]/start et callback, et les routes OAuth .well-known. src/services.ts construit db, auth et core. Réf. PRD : prd.md > Screens and Layout.
API (packages/api)
appRouter dans src/routers/index.ts liste ideas, designs, products, campaigns, runs et connections ; la logique de chaque étape est dans src/flow/*. publicProcedure ajoute la journalisation evlog ; protectedProcedure exige une session ou un utilisateur MCP. Réf. PRD : prd.md > Features and Behavior.
Serveur MCP (packages/api/src/mcp.ts)
createMcpServer enregistre list_connections, research_trends, generate_design, approve_design, reject_design, create_product, publish_product, create_campaign, start_run et get_run, chacun appelant le même routeur. Réf. PRD : prd.md > Screens and Layout.
Core (packages/core)
createCore assemble Qloo (qloo.ts), Tavily (trends.ts), Nemotron (nemotron.ts), fal (fal.ts), le prix (pricing.ts), le juge (design.ts), l'autopilot (autopilot.ts), les publicités (ads.ts), Fourthwall (fourthwall.ts), le client OAuth amont (upstream.ts) et le scellement des jetons (sealing.ts). Réf. PRD : prd.md > Features and Behavior.
Authentification (packages/auth)
createAuth construit Better Auth sur la base Drizzle ; mcpResource est l'URL à laquelle les jetons d'accès sont liés. Réf. PRD : prd.md > States and Boundaries.
Base de données (packages/db)
Tables Better Auth dans src/schema/auth.ts ; tables du vendeur dans src/schema/seller.ts. Réf. PRD : prd.md > States and Boundaries.
Flows Duo
Flows d'auto-réparation, d'éclaireur et de développeur autour du dépôt ; définitions dans docs/flows.md. Réf. PRD : prd.md > Features and Behavior (After deploy).
Modèle de données
| Table | Contenu | Mise à jour |
|---|---|---|
user, session, account et tables OAuth | Better Auth | Inscription, connexion, consentement OAuth |
connection, connection_flow | Les accès Fourthwall et Meta du vendeur, jetons scellés en AES-256-GCM ; flux OAuth en attente | À la connexion |
run | Un passage depuis une graine : drapeau autopilot, état, étape courante, erreur | À chaque étape |
idea | Idées classées avec leur recherche et les noms à ne jamais imprimer | À la recherche |
design | Brief, illustration, jugement, prix, état et raison de la décision | À la génération et à la décision |
product | Le produit Fourthwall et son état de publication | À la création et à la publication |
campaign | La campagne Meta en pause et ses textes publicitaires | À la création |
Les migrations sont générées avec pnpm run db:generate.
Structure des fichiers
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.mdServices externes et dépendances
| Service | Usage | Clé | Notes |
|---|---|---|---|
| Nebius Token Factory | Brief, juge, textes publicitaires et autopilot Nemotron, compatible OpenAI sur NEBIUS_BASE_URL (https://api.tokenfactory.nebius.com/v1/) | NEBIUS_API_KEY | Paiement au jeton |
| Qloo | /search et /v2/insights sur QLOO_API_URL (https://hackathon.api.qloo.com) | QLOO_API_KEY | Clé de hackathon |
| Tavily | Recherche en direct de l'actualité et des places de marché (etsy.com, redbubble.com, fourthwall.com) | TAVILY_API_KEY | Débit limité |
| fal | Illustrations d'impression avec GPT Image sur fal | FAL_KEY | Paiement à l'image |
| Fourthwall | Catalogue, aperçus, produits et publication via son serveur MCP | OAuth par vendeur | |
| Meta Ads | Campagne, ensemble de publicités et publicités, créés en pause, via son serveur MCP | META_APP_ID, META_APP_SECRET, OAuth par vendeur | Une revue d'application peut être nécessaire |
| Cloud SQL, Cloud Run | PostgreSQL et hébergement | Projet GCP |
Modes de défaillance importants
- Une clé de fournisseur manque → l'étape échoue avec
NOT_CONFIGUREDnommant la variable ; les autres étapes fonctionnent toujours. - Le vendeur n'a pas connecté Fourthwall ou Meta → l'outil MCP renvoie l'erreur, la raison, la solution et le lien de connexion.
- Une étape échoue dans une exécution → l'exécution est
failedavec son étape et son erreur.
Ce qui a été simplifié et pourquoi
- Une seule application plutôt que des services API et MCP séparés — un seul jeu de procédures garde les surfaces cohérentes.
- Des résultats d'outils en JSON plutôt que des widgets ChatGPT — moins de code ; les widgets pourront venir plus tard.
- Des campagnes en pause plutôt que des lancements en direct — supprime le risque de dépense involontaire.
- T-shirt uniquement — un seul produit suffit à prouver la boucle.
- Pas d'optimiseur — il faut d'abord de vraies données de dépenses.
Décisions et points ouverts
- Le code garde-fou et Nemotron décide à l'intérieur — choisi pour qu'une erreur du modèle ne puisse pas publier un design non vérifié ni dépenser de l'argent ; le compromis est de corriger parfois une bonne réponse du modèle.
- Qloo avant Tavily — le goût restreint la recherche d'actualité ; le compromis est la dépendance à la couverture de Qloo pour la graine.
- Résolu : ChatGPT se connecte à
https://mcp.wovain.com/api/mcp; le plugin MCP de Better Auth est le serveur OAuth etrequireMcpAuthvérifie chaque jeton. - Ouvert : périmètre de la revue d'application Meta pour la création de campagnes côté serveur.
- Concept peu familier abordé : la différence entre un modèle qui suggère une valeur et un code qui la garantit. Clarifié par la règle selon laquelle les contrôles tranchés par le code (taille d'impression, prix plancher, fourchette de budget) ne sont pas une sortie du modèle, démontrée par les tests de
packages/core/src/design.test.ts.