33800 Docs

← Retour

Proposition: QIG v2 - Universal Interface Generator

Date: 24-01-2026 18:22 Status: ✅ VALIDÉ

Vision

Fin des frontends. Juste des APIs.

Un utilisateur dit ce qu'il veut en langage naturel, Ollama comprend, trouve l'API, génère un formulaire beau et user-friendly, l'utilisateur remplit, l'API est appelée. Terminé.

"Je veux créer un projet GitLab"
              ↓
    Interface générée en live
              ↓
      Formulaire rempli
              ↓
        API appelée
              ↓
         Résultat

Pourquoi Qwik (non négociable)

Concept Application QIG
Resumability Serveur génère le form dynamique, client reprend sans re-exécuter JS
Micro-bundles Form de 50 champs = charge JS uniquement du champ cliqué
Lazy loading Composants chargés à la demande, parfait pour UI inconnue à l'avance
0kb JS initial Page interactive immédiatement, JS streamé au besoin

Cas d'usage : Ollama génère un form avec 20 champs complexes. Avec React = 500kb JS chargé. Avec Qwik = 0kb initial, ~2kb par interaction.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                           USER INPUT                             │
│  - Langage naturel : "créer un projet GitLab"                   │
│  - URL Swagger : https://api.example.com/swagger.json           │
│  - Schema JSON brut                                              │
│  - Description textuelle d'entités                               │
│  - Anything                                                      │
└─────────────────────────────────────────────────────────────────┘
                                 ↓
┌─────────────────────────────────────────────────────────────────┐
│                    OLLAMA (cerveau central)                      │
│                    via ai-orchestrator queue                     │
│                    priority: high pour tests                     │
├─────────────────────────────────────────────────────────────────┤
│  1. INTENTION : comprendre ce que veut l'utilisateur            │
│  2. DISCOVERY : identifier l'API/connector nécessaire           │
│  3. SCHEMA : analyser le schéma de l'endpoint                   │
│  4. RELATIONS : détecter entités liées, workflows               │
│  5. UI SPEC : générer la spec du formulaire                     │
│     - champs, types, validations                                │
│     - ordre logique, groupes                                    │
│     - labels user-friendly, hints                               │
│     - valeurs par défaut intelligentes                          │
└─────────────────────────────────────────────────────────────────┘
                                 ↓
┌─────────────────────────────────────────────────────────────────┐
│                 CONNECTORS-HUB /api/fetch                        │
│                 (pierre angulaire)                               │
├─────────────────────────────────────────────────────────────────┤
│  - Proxy universel vers N'IMPORTE QUELLE API                    │
│  - Auth centralisée (bearer, oauth2, basic, custom)             │
│  - Découverte schémas (swagger, openapi, graphql)               │
│  - Exécution des appels                                          │
│                                                                  │
│  Connecteurs existants : github, gitlab, mailjet, o2switch...   │
│  Extensible : ajouter n'importe quelle API                      │
└─────────────────────────────────────────────────────────────────┘
                                 ↓
┌─────────────────────────────────────────────────────────────────┐
│                     QIG QWIK RENDERER                            │
├─────────────────────────────────────────────────────────────────┤
│  SSR (Server Side Render)                                        │
│  ├── Reçoit UI Spec de Ollama                                   │
│  ├── Génère HTML avec Qwik components                           │
│  ├── Envoie au client (0kb JS)                                  │
│  └── Client "resume" au lieu de "hydrate"                       │
│                                                                  │
│  Composants Qwik (lazy loaded)                                   │
│  ├── FormField (text, number, email, url...)                    │
│  ├── SelectField (dropdown, multi-select)                       │
│  ├── CheckboxField, RadioField                                  │
│  ├── TextArea, RichText                                         │
│  ├── FileUpload                                                  │
│  ├── DatePicker, ColorPicker                                    │
│  ├── Autocomplete (avec appels API)                             │
│  ├── ArrayField (items dynamiques)                              │
│  ├── ObjectField (nested forms)                                 │
│  └── RelationField (référence autre entité)                     │
│                                                                  │
│  DaisyUI + Tailwind pour le style                                │
└─────────────────────────────────────────────────────────────────┘
                                 ↓
┌─────────────────────────────────────────────────────────────────┐
│                        EXECUTION                                 │
├─────────────────────────────────────────────────────────────────┤
│  1. User remplit le formulaire                                   │
│  2. Validation côté client (lazy loaded)                        │
│  3. Submit → QIG server                                          │
│  4. QIG → connectors-hub /api/fetch                             │
│  5. Résultat affiché proprement                                  │
│  6. Ollama peut enrichir l'affichage du résultat                │
└─────────────────────────────────────────────────────────────────┘

Flow détaillé

Exemple : "Je veux créer un projet GitLab"

1. USER INPUT
   └── "Je veux créer un projet GitLab"

2. OLLAMA (job priority:high)
   ├── Prompt: "L'utilisateur veut: créer un projet GitLab.
   │           Connecteurs disponibles: github, gitlab, mailjet, o2switch.
   │           Identifie le connector et l'action."
   ├── Response: { connector: "gitlab", action: "create_project",
   │               endpoint: "POST /projects" }
   │
   ├── Fetch schema via connectors-hub:
   │   POST /api/fetch { connector: "gitlab", path: "/projects", method: "OPTIONS" }
   │   ou fetch swagger: /api/v4/swagger.json
   │
   └── Prompt: "Génère un formulaire user-friendly pour créer un projet GitLab.
               Schema: { name: string (required), description: string,
                         visibility: enum[private,internal,public], ... }
               Retourne une UI Spec JSON."

3. UI SPEC générée par Ollama
   {
     "title": "Créer un projet GitLab",
     "description": "Nouveau repository sur GitLab",
     "groups": [
       {
         "name": "Informations principales",
         "fields": [
           {
             "id": "name",
             "type": "text",
             "label": "Nom du projet",
             "placeholder": "mon-super-projet",
             "required": true,
             "hint": "Lettres, chiffres et tirets uniquement"
           },
           {
             "id": "description",
             "type": "textarea",
             "label": "Description",
             "placeholder": "Décrivez votre projet...",
             "required": false
           }
         ]
       },
       {
         "name": "Paramètres",
         "fields": [
           {
             "id": "visibility",
             "type": "select",
             "label": "Visibilité",
             "options": [
               { "value": "private", "label": "Privé", "icon": "lock" },
               { "value": "internal", "label": "Interne", "icon": "building" },
               { "value": "public", "label": "Public", "icon": "globe" }
             ],
             "default": "private",
             "hint": "Qui peut voir ce projet ?"
           }
         ]
       }
     ],
     "submit": {
       "connector": "gitlab",
       "method": "POST",
       "path": "/projects",
       "label": "Créer le projet"
     }
   }

4. QIG RENDER (Qwik SSR)
   └── Génère HTML avec composants Qwik
       └── Envoie au client (0kb JS initial)

5. USER INTERACTION
   ├── Clique sur champ "name" → charge micro-bundle validation (~1kb)
   ├── Clique sur select "visibility" → charge micro-bundle dropdown (~2kb)
   └── Clique "Créer" → charge micro-bundle submit (~3kb)

6. SUBMIT
   ├── QIG POST /api/execute
   │   { spec: {...}, values: { name: "test", visibility: "private" } }
   ├── QIG → connectors-hub POST /api/fetch
   │   { connector: "gitlab", method: "POST", path: "/projects",
   │     body: { name: "test", visibility: "private" } }
   └── Résultat affiché

7. RESULT DISPLAY
   └── Ollama enrichit: "Projet 'test' créé avec succès!
                         URL: https://gitlab.../test
                         Prochaine étape: ajouter des collaborateurs?"

Structure projet

qwik-interface-generator/
├── src/
│   ├── routes/
│   │   ├── index.tsx                 # Page principale (input)
│   │   ├── generate/
│   │   │   └── index.tsx             # Affiche le form généré
│   │   └── api/
│   │       ├── intent/index.ts       # POST: analyse intention (→ Ollama)
│   │       ├── schema/index.ts       # POST: fetch schema API
│   │       ├── ui-spec/index.ts      # POST: génère UI spec (→ Ollama)
│   │       └── execute/index.ts      # POST: exécute l'action (→ fetch)
│   │
│   ├── components/
│   │   ├── input/
│   │   │   ├── NaturalInput.tsx      # Input langage naturel
│   │   │   ├── SwaggerInput.tsx      # Input URL swagger
│   │   │   └── SchemaInput.tsx       # Input JSON brut
│   │   │
│   │   ├── form/                     # Composants form (lazy loaded)
│   │   │   ├── FormRenderer.tsx      # Render UI Spec → Form
│   │   │   ├── FieldRenderer.tsx     # Dispatch vers bon composant
│   │   │   ├── TextField.tsx
│   │   │   ├── TextAreaField.tsx
│   │   │   ├── SelectField.tsx
│   │   │   ├── CheckboxField.tsx
│   │   │   ├── RadioField.tsx
│   │   │   ├── NumberField.tsx
│   │   │   ├── DateField.tsx
│   │   │   ├── FileField.tsx
│   │   │   ├── ArrayField.tsx        # Champs répétables
│   │   │   ├── ObjectField.tsx       # Nested objects
│   │   │   └── RelationField.tsx     # FK vers autre entité
│   │   │
│   │   ├── result/
│   │   │   └── ResultDisplay.tsx     # Affiche résultat enrichi
│   │   │
│   │   └── ui/                       # Composants génériques
│   │       ├── Button.tsx
│   │       ├── Card.tsx
│   │       ├── Modal.tsx
│   │       └── Loading.tsx
│   │
│   ├── lib/
│   │   ├── ollama/
│   │   │   ├── client.ts             # Client ai-orchestrator
│   │   │   ├── prompts.ts            # Templates prompts
│   │   │   └── parser.ts             # Parse réponses Ollama
│   │   │
│   │   ├── connectors/
│   │   │   ├── client.ts             # Client connectors-hub
│   │   │   ├── auth.ts               # Gestion auth/session
│   │   │   └── fetch.ts              # Wrapper /api/fetch
│   │   │
│   │   └── ui-spec/
│   │       ├── types.ts              # Types UISpec
│   │       ├── validator.ts          # Valide UISpec
│   │       └── defaults.ts           # Valeurs par défaut
│   │
│   └── styles/
│       └── global.css                # Tailwind + DaisyUI
│
├── Dockerfile
├── conf.prod.gouroubleu.yml
├── .gitlab-ci.yml
└── package.json

UI Spec Format (standard interne)

interface UISpec {
  title: string;
  description?: string;
  groups: FieldGroup[];
  submit: SubmitAction;
}

interface FieldGroup {
  name: string;
  description?: string;
  collapsible?: boolean;
  fields: Field[];
}

interface Field {
  id: string;
  type: FieldType;
  label: string;
  placeholder?: string;
  hint?: string;
  required?: boolean;
  default?: any;
  validation?: ValidationRule[];
  options?: Option[];           // pour select, radio
  items?: Field;                // pour array
  properties?: Field[];         // pour object
  relation?: RelationConfig;    // pour FK
}

type FieldType =
  | 'text' | 'textarea' | 'richtext'
  | 'number' | 'currency'
  | 'email' | 'url' | 'phone'
  | 'select' | 'multiselect' | 'radio' | 'checkbox'
  | 'date' | 'datetime' | 'time'
  | 'file' | 'image'
  | 'color'
  | 'array' | 'object'
  | 'relation';

interface SubmitAction {
  connector: string;
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
  path: string;
  label: string;
  confirmMessage?: string;
}

Prompts Ollama (exemples)

1. Analyse d'intention

Tu es un assistant qui comprend les intentions utilisateur.

Connecteurs disponibles: ${connectorsList}

Input utilisateur: "${userInput}"

Analyse et retourne un JSON:
{
  "understood": true/false,
  "connector": "nom du connector ou null",
  "action": "create|read|update|delete|list|custom",
  "entity": "nom de l'entité (project, user, issue...)",
  "endpoint_hint": "suggestion d'endpoint API",
  "needs_clarification": "question si pas clair, sinon null"
}

2. Génération UI Spec

Tu es un expert UX/UI.

Génère un formulaire user-friendly pour cette action:
- Connector: ${connector}
- Action: ${action}
- Schema API: ${jsonSchema}

Règles:
- Labels en français, clairs
- Groupes logiques
- Champs requis en premier
- Hints utiles
- Valeurs par défaut intelligentes
- Placeholder avec exemples

Retourne un JSON UISpec valide.

Étapes d'implémentation

Phase 1 : Core Qwik + Ollama (priorité)

  1. Setup projet Qwik propre

    • Qwik City avec SSR
    • Tailwind + DaisyUI
    • Structure dossiers
  2. Composants Form de base

    • TextField, SelectField, TextAreaField
    • FormRenderer qui consomme UISpec
    • Lazy loading vérifié
  3. Intégration Ollama

    • Client ai-orchestrator (priority: high)
    • Prompt intention
    • Prompt UI spec
    • Parser réponses
  4. Page principale

    • Input langage naturel
    • Affichage form généré
    • Submit basique

Phase 2 : Connectors + Execution

  1. Client connectors-hub

    • Auth (login via connectors)
    • Wrapper /api/fetch
    • Gestion erreurs
  2. Execution flow

    • Submit form → /api/fetch
    • Affichage résultat
    • Gestion erreurs

Phase 3 : Composants avancés

  1. Champs complexes

    • ArrayField, ObjectField
    • RelationField (autocomplete)
    • FileField
  2. Validation

    • Client-side (lazy loaded)
    • Server-side
    • Messages d'erreur

Phase 4 : Polish

  1. UX améliorée

    • Loading states
    • Animations
    • Keyboard navigation
  2. Historique

    • Actions récentes
    • Favoris
    • Templates perso

Dépendances

{
  "dependencies": {
    "@builder.io/qwik": "latest",
    "@builder.io/qwik-city": "latest",
    "tailwindcss": "^3.4",
    "daisyui": "^4.0"
  }
}

Config Smart-Deploy

name: qwik-interface-generator
type: qwik
port: 5505

env:
  CONNECTORS_API_URL: https://connectors.33800.nowhere84.com
  AI_ORCHESTRATOR_URL: https://ai-orchestrator.33800.nowhere84.com
  OLLAMA_MODEL: llama3.1:8b
  OLLAMA_PRIORITY: high

healthcheck:
  path: /health
  interval: 30s

Tests de validation

Test Critère de succès
Input naturel FR "créer projet gitlab" → form généré
Input naturel EN "create github repo" → form généré
Swagger URL URL swagger → forms pour tous endpoints
Schema JSON JSON collé → form généré
Submit form Données → API appelée → résultat
Micro-bundles Network tab: JS chargé uniquement au clic
Resumability Pas de hydration, reprise immédiate

Risques et mitigations

Risque Mitigation
Ollama lent Priority high + cache réponses similaires
Hallucination Ollama Validation UISpec + fallback
API inconnue Demander URL swagger/docs
Form complexe Groupes collapsibles, wizard multi-step

Estimation

Non applicable (voir règles CLAUDE.md)

Décisions validées

  1. Modèle Ollama : Le meilleur disponible (llama3.1:70b ou deepseek-r1:32b)
  2. Multi-langue : FR + EN
  3. Historique : Oui, stocker les forms générés pour réutilisation

✅ VALIDÉ - Phase 1 en cours