Vision & Contraintes
Plateforme permettant à des enseignants de créer des parcours pédagogiques collaboratifs entre deux groupes. Chaque parcours est une séquence de cards où la progression d'un groupe conditionne le déblocage des étapes de l'autre groupe.
Deux modes
| Mode | Description | Groupes |
|---|---|---|
| Collaboratif | 2 groupes liés, déblocage inter-dépendant | A ⇄ B |
| Solo | 1 groupe, déblocage par validation prof ou verrou gamifié | A seul |
Contraintes non négociables
100 % gratuit · Self-hosted VPS IONOS · Un seul déploiement (multi-tenant) · IA via Ollama existant · Mobile-first élèves · Builder desktop-only profs
Stack technique
| Couche | Choix | Justification |
|---|---|---|
| Frontend | Vue 3 + Vite | Réactivité builder drag & drop + temps réel |
| BaaS | PocketBase (SQLite WAL) | Auth, API, Realtime WebSocket, 1 container, zéro config |
| IA | Ollama mistral:7b | Français, gratuit, déjà en prod sur le VPS |
| Reverse proxy | Nginx 1.24 + Let's Encrypt | Déjà en place, sous-domaines illimités |
| Conteneurisation | Docker Compose | Cohérent avec les autres projets du VPS |
| Build | Vite → fichiers statiques | Pas de Node.js en prod |
Sous-domaines
Modèle de données
Toutes les tables PocketBase. Isolation multi-tenant via org_id. Règle : listRule: @request.auth.org_id = org_id
organizations
id, name, slug (unique), country, plan (free|pro), created
users (Auth PocketBase)
id, email (nullable), role (eleve|prof|responsable), org_id, group_id, display_name, avatar
groups
id, project_id, org_id, name, level, city, country, join_code (4-8 car., personnalisable, unique par projet), linked_group_id (nullable)
city + country affichés dans l'UI élève. join_code personnalisable (ex : "6EME2") + QR code.
projects
id, org_id, title, description, mode (solo|collaborative), status (draft|active|archived), template_id (nullable), created_by, created
cards
id, project_id, group_id, org_id, title, instructions, type (ressource|tache|production|feedback|debat|echange), position, fields (JSON), unlock_type, unlock_config (JSON), unlock_requires_card_id (nullable), locked_by_default
Une card de type ressource peut avoir fields: [] — pas de formulaire, juste un bouton "Marquer comme lu".
card_drafts
id, card_id, group_id, org_id, content (JSON), updated_at
Brouillon côté serveur, sauvegardé toutes les 10 s. Supprimé à la soumission finale.
card_completions
id, card_id, group_id, org_id, completed_at, validated_by_teacher (bool), validated_at, validator_id, teacher_feedback, submitted_by (texte libre, optionnel), content (JSON)
templates
id, title, description, subject, level_a, level_b, duration_weeks, tags (JSON), use_count, published_by_org_id, is_public, cards_snapshot (JSON), created
Types de champs élève (v1)
| Type | Clé | Description | Options |
|---|---|---|---|
| Texte court | text | 1 ligne | placeholder, max_chars |
| Texte long | textarea | Paragraphe | min_words, max_words |
| Nombre | number | Numérique | min, max, unit |
| Photo caméra | photo | Ouvre la caméra directement (attribut capture) | max_size |
| Fichier | file | Sélecteur de fichiers (docs, images existantes) | accept, max_size |
| Audio | audio | Enregistrement micro (MediaRecorder API) | max_duration_sec |
| Lien URL | link | URL validée | allowed_domains |
| Lien vidéo | video_link | YouTube / Drive / Vimeo | — |
| Choix unique | radio | QCM | options (array) |
| Cases à cocher | checklist | Multi-sélection | items (array) |
| Étoiles | rating | Note 1 à N | max, labels |
| Curseur | slider | Valeur entre min et max | min, max, step |
Prévus en v2 : dessin libre, annotation image, vidéo, texte à trous, carte, QR scan, vote de groupe.
Types de verrous
Sécurité : toute vérification se fait côté serveur via hook PocketBase. Les valeurs attendues ne transitent jamais vers le client JS.
Builder
Desktop uniquement. Autosave debounce 1,5 s. Pas de undo/redo en v1.
Couleurs et icônes par type
Canvas
Header : titre · toggle mode · autosave · "Aperçu élève" · "Publier"
Mode collaboratif : 2 lanes côte à côte, flèches SVG (teal A→B, violet B→A, pointillés)
Mode solo : 1 lane centrée
Join code + QR
Code personnalisable (ex: "6EME2", 4–8 caractères). Bouton "QR Code" → projeter ou imprimer, scan = connexion directe.
Aperçu élève
Panneau simulant la vue du groupe A ou B — cards verrouillées/déverrouillées selon config. Lecture seule.
Expérience élève
Connexion
Nom du groupe + code. N appareils simultanés sur le même groupe — chaque élève ouvre l'app sur son téléphone. Soumission partagée en temps réel via WebSocket.
Vue parcours
- Header : nom du projet + groupe + ville/pays + progression X/N
- Statuts : ✅ validé · ✏️ en cours · 🔒 verrouillé · 🎁 code · 🧩 énigme · ⏳ en attente
Remplir une card
- Brouillon sauvegardé en
card_draftstoutes les 10 s - Au moment de soumettre : champ optionnel "Qui envoie ?" →
submitted_by
Comportement offline
À la reconnexion, Vue 3 recharge la liste via REST — les déblocages apparaissent naturellement. Aucune donnée perdue.
Fin de parcours
Écran de célébration (confetti, logo, "Bravo — parcours terminé !") quand toutes les cards sont validées. Le prof reçoit une notification Realtime.
Dashboard prof
Vue "classe vivante"
Bandeau temps réel : "Groupe A — 3 appareils connectés · dernière activité il y a 2 min". Basé sur PocketBase Realtime.
Actions disponibles
- Lire toutes les productions (texte, fichiers, audio)
- Valider / refuser + commentaire optionnel
- Débloquer manuellement une card (override)
- Message broadcast à un groupe
- Voir le
submitted_byde chaque soumission - Retour dans le builder
Multi-tenant
Isolation logique via org_id. Une seule URL app.duneclassealautre.portailemfe.fr.
Onboarding
- Prof s'inscrit → organisation créée automatiquement, il devient
responsable - Invite collègues via lien d'invitation (token, 7 jours) → rejoignent avec
role: prof
Rôles
| Rôle | Crée des projets | Voit tous les projets de l'org | Gère les membres |
|---|---|---|---|
eleve | ✗ | ✗ | ✗ |
prof | ✓ | ✗ | ✗ |
responsable | ✓ | ✓ (lecture) | ✓ |
Intégration Ollama
Jamais d'appel direct depuis le client. Tout passe par hooks PocketBase → ollama.portailemfe.fr (mistral:7b, CPU-only, 5–15 s)
| Déclencheur | Usage |
|---|---|
| "Générer instructions" dans le builder | Rédiger les instructions d'une card depuis titre + type |
| Publication d'un template | Suggérer titre, description, tags |
| Validation d'une complétion texte | Générer un brouillon de feedback (toujours modifiable) |
Gestion des erreurs
- Timeout hook : 30 s max
- Si indisponible : résultat vide + message "Génération indisponible — réessayez"
- Le feedback IA n'est jamais affiché directement aux élèves
Hors scope v1
| Fonctionnalité | Raison du report |
|---|---|
| Auth individuelle élève | Session groupe suffisante en v1 |
| Undo/redo builder | Autosave suffit |
| Drag inter-lanes / flèches drag | Dropdown suffit |
| Enregistrement vidéo | Lien vidéo suffit |
| Dessin libre / annotation image | v2 |
| Statistiques avancées | v2 |
| Marketplace template ouverte | Modération admin d'abord |
| App mobile native | PWA suffisant pour v1 |
| Export PDF | v2 |
| Intégration LMS | v2 |
Architecture de déploiement
VPS IONOS (87.106.196.43)
└── Nginx
├── duneclassealautre.portailemfe.fr → vitrine
├── app.duneclassealautre.portailemfe.fr → Vue 3 + PocketBase :8090
├── ressources.duneclassealautre.portailemfe.fr → guides enseignants
└── ollama.portailemfe.fr → (existant)
~/duneclasse/docker-compose.yml
pocketbase:
image: ghcr.io/muchobien/pocketbase:latest
ports: ["127.0.0.1:8090:8090"]
volumes: [/var/www/duneclasse_pb_data:/pb_data]
Sauvegarde : ~/backup_vps.sh (couvre SQLite via volume)
Décisions architecturales clés
| Décision | Choix retenu | Alternative écartée |
|---|---|---|
| Schéma dynamique | JSON fields dans chaque card | Tables SQL dynamiques par projet |
| Realtime | PocketBase WebSocket natif | Polling ou Socket.io séparé |
| Auth élève | N appareils / même groupe, localStorage | Comptes individuels (v2) |
| Vérification verrous | Hook PocketBase serveur | Vérification client JS |
| Templates | cards_snapshot JSON | Clonage de rows DB |
| IA | Ollama hook serveur, timeout 30s + fallback | API payante |
| Scale v1 | PocketBase SQLite WAL | PostgreSQL (migration path v2) |
| Brouillon | Table card_drafts côté serveur | localStorage seul |
| Identité groupe | city + country affichés | Groupes anonymes |
| Join code | Personnalisable + QR code | Code fixe non modifiable |
| Fin de parcours | Écran célébration confetti | Retour silencieux |
| Couleurs types | Icône + couleur par type | Tout identique |