Un seul chemin. Chaque étape se vérifie avant de passer à la suivante. Aucune décision d'architecture à prendre ici.
node --version # >= 20
python --version # >= 3.11
docker --version # pour tester l'engine en local (optionnel en mock)Comptes à créer si pas encore fait : Supabase (free), Vercel (free).
# Clone le template dans un nouveau dossier produit
git clone https://github.com/Insular2895/Shell.git
cp -r Shell/micro-saas-template-v2 mon-produit
cd mon-produit
# Installe les dépendances JS
npm install
# Installe les dépendances Python de l'engine
pip install -r engine/requirements.txtVérification :
npm run typecheck # doit terminer sans erreur
npm run test # doit passerCrée un fichier .env.local à la racine du dossier produit :
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=eyJ... # clé Supabase locale ou fake pour mock pur
SUPABASE_SERVICE_ROLE_KEY=eyJ...
NEXT_PUBLIC_APP_URL=http://localhost:3000
ENGINE_MODE=mock
CRON_SECRET=dev-secret-local
WORKER_API_TOKEN=dev-token-localEn mode mock, Supabase n'est pas obligatoire pour voir le rendu UI. Pour un test complet avec auth et jobs, lance Supabase local :
npx supabase startpuis applique les migrationssupabase/migrations/*.sql.
Lance le serveur :
npm run devOuvre http://localhost:3000.
Vérification : La page d'accueil s'affiche. /api/health répond 200.
Édite config/run.schema.json pour définir les champs de ton produit :
{
"title": "Mon outil",
"submitLabel": "Lancer",
"estimatedRuntime": "< 1 minute",
"inputs": [
{
"key": "url",
"type": "url",
"label": "URL à analyser",
"required": true
}
]
}Recharge http://localhost:3000/run — le formulaire se génère automatiquement depuis ce schéma.
Vérification : Le formulaire affiche le bon champ. En mode mock, soumettre affiche output.example.json comme résultat.
Ouvre engine/adapter.py. C'est le seul fichier que tu modifies par produit.
# Exemple : importer ton code Python métier
from mon_core.analyzer import analyze # pip install mon-core
def run(payload: dict) -> dict:
input_data = payload["input"]
result = analyze(input_data["url"]) # ton code métier pur
return {
"status": "success",
"blocks": [
{"type": "text", "content": result["summary"]},
{"type": "score", "title": "Score", "value": result["score"], "label": "Analyse"}
]
}Teste l'adapter en isolation (sans le Shell) :
ENGINE_MODE=local python engine/run_engine.py engine/input.example.jsonVérification : La commande termine avec {"status": "success", "blocks": [...]} dans le terminal.
Assure-toi que Supabase local tourne (npx supabase start) et que les migrations sont appliquées.
Lance npm run dev, crée un compte, soumet un job depuis /run.
L'AutoResultRenderer lit les blocks retournés par l'adapter et les rend automatiquement :
| Type de block | Rendu |
|---|---|
text |
Paragraphe |
score |
Valeur numérique ou % avec label |
table |
Données tabulaires |
list |
Liste à puces |
file |
Lien de téléchargement |
chart |
Graphique |
json |
Données brutes |
warning |
Alerte |
recommendation |
Action recommandée |
Ces types sont les seuls valides — définis dans
RUN_SCHEMA.md. Ne pas inventer de nouveaux types.
Vérification : Le résultat s'affiche dans /results/[jobId] sans aucun code UI à écrire.
Voir DEPLOYMENT.md → section "Niveau 0 — Démo low-cost".
En résumé :
- Crée un projet Supabase (free) → applique les migrations
vercel deploy --prodavec les variables d'env (ENGINE_MODE=mockpour commencer)- Visite
https://ton-app.vercel.app/api/health→ doit répondre 200
Pour passer au moteur réel : Change ENGINE_MODE=docker et déploie le worker sur Fly (DEPLOYMENT.md → Niveau 1).
| Symptôme | Où chercher |
|---|---|
| Formulaire vide ou erreur schema | config/run.schema.json mal formé — valide avec npx ajv validate |
Job reste en pending |
ENGINE_MODE non défini → l'engine ne se lance pas |
| Résultat vide | adapter.py retourne un dict sans blocks |
| Auth cassée | Migrations Supabase non appliquées |
| Build Vercel échoue | Typecheck — lance npm run typecheck en local d'abord |
Voir aussi RUN_FLOW.md pour le pipeline complet paramètre par paramètre.