0% ont trouvé ce document utile (0 vote)
0 vues9 pages

instructions

Wezabi est une application mobile d'entraide scolaire peer-to-peer pour les étudiants d'Afrique francophone, utilisant Flutter et Firebase. Elle permet aux utilisateurs de poser des questions, de recevoir des réponses de tuteurs et de voter pour les meilleures réponses, avec un système de points et de rangs. L'application est monétisée via Google AdMob et respecte des règles strictes en matière de conception, de structure de code et de gestion des erreurs.

Transféré par

nkbhyacinthe
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
0 vues9 pages

instructions

Wezabi est une application mobile d'entraide scolaire peer-to-peer pour les étudiants d'Afrique francophone, utilisant Flutter et Firebase. Elle permet aux utilisateurs de poser des questions, de recevoir des réponses de tuteurs et de voter pour les meilleures réponses, avec un système de points et de rangs. L'application est monétisée via Google AdMob et respecte des règles strictes en matière de conception, de structure de code et de gestion des erreurs.

Transféré par

nkbhyacinthe
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd

# ============================================================

# WEZABI — WINDSURF RULES (Cascade AI Rules)


# Application mobile d'entraide scolaire — Afrique francophone
# Flutter / Firebase / Google AdMob
# Version 1.0 — Juin 2026
# ============================================================

# ─────────────────────────────────────────
# 1. IDENTITÉ DU PROJET
# ─────────────────────────────────────────

project:
name: Wezabi
description: >
Application mobile Flutter d'entraide scolaire peer-to-peer
destinée aux étudiants d'Afrique francophone. Les étudiants
posent des questions, les tuteurs répondent, la communauté vote,
et l'auteur valide la meilleure réponse.
platform: Flutter (Android + iOS)
language: Dart
backend: Firebase (Auth, Firestore, Storage, Cloud Messaging, Cloud
Functions)
monetization: Google AdMob (bannière, interstitiel, pub récompensée)
target_market: Afrique francophone (Côte d'Ivoire, Sénégal, Cameroun,
Mali)
app_language: Français uniquement (V1)

# ─────────────────────────────────────────
# 2. STACK TECHNIQUE OBLIGATOIRE
# ─────────────────────────────────────────

tech_stack:
flutter_sdk: ">=3.0.0"
state_management: provider
navigation: go_router

firebase_packages:
- firebase_core
- firebase_auth # Authentification OTP par téléphone
- cloud_firestore # Base de données temps réel
- firebase_storage # Photos d'exercices et avatars
- firebase_messaging # Notifications push FCM
- cloud_functions # Logique serveur (alertes tuteurs, points)

ui_packages:
- cached_network_image # Chargement optimisé des images
- image_picker # Sélection photo exercice et avatar

ads_packages:
- google_mobile_ads # Bannière + interstitiel + récompensée

utility_packages:
- badges # Badge rouge sur avatar (nouvelles réponses)
- flutter_local_notifications # Notifications locales

forbidden_packages:
- getx # Ne jamais utiliser GetX — utiliser Provider
uniquement
- bloc # Ne pas utiliser BLoC — utiliser Provider uniquement
- riverpod # Ne pas utiliser Riverpod — utiliser Provider
uniquement
- http # Ne pas utiliser http — Firebase gère tout le backend

# ─────────────────────────────────────────
# 3. STRUCTURE DES DOSSIERS — OBLIGATOIRE
# ─────────────────────────────────────────

folder_structure:
lib/:
screens/:
auth/:
- splash_screen.dart
- phone_screen.dart
- otp_screen.dart
- onboarding_screen.dart
home/:
- home_screen.dart
question/:
- post_question_screen.dart
- question_detail_screen.dart
ranking/:
- ranking_screen.dart
profile/:
- profile_screen.dart
notifications/:
- notif_screen.dart
search/:
- search_screen.dart
widgets/:
- question_card.dart
- answer_card.dart
- ad_banner_widget.dart
- notif_badge_widget.dart
models/:
- user_model.dart
- question_model.dart
- answer_model.dart
services/:
- auth_service.dart
- firestore_service.dart
- points_service.dart
- notification_service.dart
- ad_service.dart
theme/:
- app_theme.dart
- [Link]
assets/:
mockups/:
- "*.png" # Références visuelles des écrans

# ─────────────────────────────────────────
# 4. IDENTITÉ VISUELLE — COULEURS OFFICIELLES
# ─────────────────────────────────────────

design:
palette:
primaryColor: "#2563EB" # Bleu électrique — boutons, liens, actif
backgroundColor: "#0F172A" # Noir profond — fond de tous les écrans
surfaceColor: "#1E293B" # Gris sombre — cartes, champs de saisie
accentColor: "#F97316" # Orange vif — avatar, badge, accent
successColor: "#10B981" # Vert émeraude — validation, succès
textColor: "#F8FAFC" # Blanc cassé — texte principal
mutedColor: "#64748B" # Gris moyen — texte secondaire
errorColor: "#DC2626" # Rouge — erreurs uniquement

typography:
font_family: "SF Pro Display" # Fallback: system font
heading_weight: 800
body_weight: 400
button_weight: 700

border_radius:
card: 12.0
button: 12.0
chip: 20.0
avatar: 999.0 # Circulaire
modal: 20.0

logo:
icon: "🧠"
background: "linear-gradient(135deg, #2563EB, #1D4ED8)"
border_radius: 18.0
text: "Wezabi"
text_color_we: "#F8FAFC"
text_color_zabi: "#F97316" # "zabi" toujours en orange

nav_bar:
items:
- icon: "Icons.chat_bubble_rounded"
label: "Fil"
index: 0
- icon: "Icons.search_rounded"
label: "Chercher"
index: 1
- type: "FAB"
icon: "Icons.add_rounded"
color: "#2563EB"
index: 2
- icon: "Icons.star_rounded"
label: "Classement"
index: 3

# ─────────────────────────────────────────
# 5. STRUCTURE FIRESTORE — SCHÉMA OBLIGATOIRE
# ─────────────────────────────────────────

firestore_schema:
collection_users:
path: "users/{uid}"
fields:
- uid: String
- name: String
- phone: String
- level: String # Seconde / Première / Terminale / Licence
1/2/3
- city: String
- subjects: List<String> # Matières favorites
- points: int # Points totaux
- rank: String # Apprenti / Tuteur / Mentor / Sage
- answersGiven: int
- questionsAsked: int
- validatedAnswers: int
- fcmToken: String # Token Firebase Cloud Messaging
- createdAt: Timestamp

collection_questions:
path: "questions/{questionId}"
fields:
- text: String # Contenu de la question (max 500 chars)
- subject: String # Maths / Physique / Chimie / Français / SVT
/ Anglais / Histoire-Géo / Philosophie
- level: String
- authorId: String
- authorName: String
- imageUrl: String? # Photo d'exercice (optionnel)
- createdAt: Timestamp
- answersCount: int # Default 0
- votesCount: int # Default 0
- isPinned: bool # Default false (pub récompensée)
- pinnedUntil: Timestamp? # Expiration de l'épinglage
- hasValidatedAnswer: bool # Default false
- unreadAnswers: int # Compteur pour badge avatar auteur

subcollection_answers:
path: "questions/{questionId}/answers/{answerId}"
fields:
- text: String
- authorId: String
- authorName: String
- authorRank: String
- votes: int # Default 0
- voterIds: List<String> # UIDs ayant voté (un vote par user)
- isValidated: bool # Default false
- validatedAt: Timestamp?
- score: int # (votes × 1) + (isValidated ? 5 : 0)
- createdAt: Timestamp

# ─────────────────────────────────────────
# 6. RÈGLES MÉTIER CRITIQUES
# ─────────────────────────────────────────

business_rules:

authentication:
- Inscription et connexion UNIQUEMENT par numéro de téléphone (OTP SMS)
- Aucun champ email dans toute l'application
- Pays disponibles au sélecteur: CI (+225), SN (+221), CM (+237), ML
(+223), BF (+226)

questions:
- Longueur maximale: 500 caractères
- Photo optionnelle via image_picker → Firebase Storage
- Matières disponibles: Maths, Physique, Chimie, Français, SVT,
Anglais, Histoire-Géo, Philosophie
- Niveaux disponibles: Seconde, Première, Terminale, Licence 1, Licence
2, Licence 3
- Les questions épinglées (isPinned=true) s'affichent TOUJOURS en tête
du fil
- Badge "✅ Résolue" affiché si hasValidatedAnswer=true (bordure gauche
verte)

answers:
- Un utilisateur ne peut PAS répondre à sa propre question
- Chaque réponse soumise déclenche immédiatement +5 pts à l'auteur
- Chaque réponse soumise incrémente unreadAnswers de la question
parente
- Chaque réponse soumise envoie une notification push à l'auteur de la
question

votes:
- Un utilisateur ne peut voter QU'UNE SEULE FOIS par réponse
- Un utilisateur ne peut PAS voter pour sa propre réponse
- Vérification via voterIds (List<String>) dans Firestore
- Chaque vote = +2 pts au répondeur + notification push au répondeur
- Le score de la réponse = (votes × 1) + (isValidated ? 5 : 0)

validation:
- Le bouton "✅ Ça m'a aidé" est visible UNIQUEMENT pour l'auteur de la
question
- L'auteur ne peut PAS valider sa propre réponse ([Link] !=
[Link])
- Plusieurs réponses peuvent être validées sur une même question
- Une réponse validée ne peut PAS être dé-validée
- Validation → isValidated=true + score recalculé + +10 pts au
répondeur
- Validation → notification push au répondeur
- Validation → hasValidatedAnswer=true sur la question parente
- Après validation → bouton remplacé par label "✅ Validée" non
cliquable

points_and_ranks:
- +5 pts: réponse donnée (immédiat)
- +2 pts: vote reçu sur une réponse
- +10 pts: réponse validée par l'auteur
- Rangs automatiques mis à jour après chaque gain de points:
0-50 pts → "🌱 Apprenti"
51-200 pts → "📚 Tuteur"
201-500 pts → "🎓 Mentor"
500+ pts → "👑 Sage"

notifications:
- Notification à l'auteur de la question quand une réponse est ajoutée
- Notification au répondeur quand sa réponse reçoit un vote
- Notification au répondeur quand sa réponse est validée
- Notification aux tuteurs d'une matière quand une question est publiée
(max 50 tuteurs)
- Jamais de notification si l'utilisateur est l'auteur de l'action

# ─────────────────────────────────────────
# 7. RÈGLES PUBLICITAIRES ADMOB
# ─────────────────────────────────────────

admob_rules:
banner:
position: "En bas du fil des questions, au-dessus de la nav bar"
screens: ["home_screen"]
never_show_on: ["post_question_screen", "notif_screen",
"question_detail_screen (pendant saisie réponse)"]

interstitial:
trigger: "Toutes les 5 questions consultées (compteur dans Provider)"
screen: "question_detail_screen (à l'ouverture)"
never_on_first_launch: true
counter_reset_after_show: true

rewarded:
screen: "post_question_screen"
placement: "Carte orange avant le bouton Publier"
label: "📌 Épingle ta question 48h pour plus de réponses !"
button: "▶ Voir une pub (30s)"
reward: "isPinned=true dans Firestore pendant 48h"
effect: "Question remonte en tête du fil avec badge 📌"

general_rules:
- Jamais de pub pendant la saisie d'une réponse
- Jamais de pub sur l'écran de notifications
- Respecter les délais minimum entre interstitiels (min 30s)
- Utiliser les IDs de test AdMob en mode développement

# ─────────────────────────────────────────
# 8. CONVENTIONS DE CODE
# ─────────────────────────────────────────

coding_conventions:
dart:
- Utiliser const constructors partout où c'est possible
- Nommer les widgets en PascalCase (ex: QuestionCard, AnswerCard)
- Nommer les fichiers en snake_case (ex: question_card.dart)
- Nommer les variables en camelCase (ex: answerCount)
- Toujours typer les variables explicitement (pas de var sauf cas
évident)
- Utiliser final pour les variables immuables
- Séparer la logique métier des widgets (services/)

flutter:
- Chaque écran est un StatelessWidget ou StatefulWidget dans son propre
fichier
- Utiliser Consumer<Provider> pour accéder aux données du Provider
- Utiliser StreamBuilder pour les données Firestore en temps réel
- Toujours gérer les états: loading, error, empty, data
- Utiliser CachedNetworkImage pour toutes les images réseau
- Ne jamais hardcoder les couleurs — utiliser app_theme.dart uniquement

firebase:
- Toujours gérer les erreurs Firebase avec try/catch
- Utiliser les transactions Firestore pour les opérations atomiques
(votes, points)
- Ne jamais exposer les règles de sécurité Firestore côté client
- Utiliser Cloud Functions pour toute logique serveur sensible (points,
alertes)

performance:
- Paginer les listes avec 20 éléments par page (Firestore pagination)
- Utiliser des indexes Firestore pour les requêtes de tri
- Compresser les images avant upload (max 800px, qualité 70%)
- Lazy loading pour les images dans les listes
# ─────────────────────────────────────────
# 9. GESTION DES ERREURS — MESSAGES UTILISATEUR
# ─────────────────────────────────────────

error_messages:
auth:
invalid_phone: "Numéro de téléphone invalide. Vérifie le format."
invalid_otp: "Code incorrect. Vérifie le SMS reçu."
otp_expired: "Code expiré. Demande un nouveau code."
network_error: "Pas de connexion. Vérifie ta connexion internet."

question:
empty_text: "Écris ta question avant de publier."
too_long: "Ta question dépasse 500 caractères."
no_subject: "Sélectionne une matière."
no_level: "Sélectionne ton niveau scolaire."
upload_error: "Erreur lors de l'envoi de la photo. Réessaie."

answer:
empty_text: "Écris ta réponse avant d'envoyer."
own_question: "Tu ne peux pas répondre à ta propre question."

vote:
already_voted: "Tu as déjà voté pour cette réponse."
own_answer: "Tu ne peux pas voter pour ta propre réponse."

general:
network: "Connexion perdue. Vérifie ta connexion."
unknown: "Une erreur est survenue. Réessaie."

# ─────────────────────────────────────────
# 10. COMPORTEMENTS INTERDITS
# ─────────────────────────────────────────

forbidden:
- Ne jamais utiliser de couleurs hardcodées dans les widgets (toujours
app_theme.dart)
- Ne jamais afficher le bouton "✅ Ça m'a aidé" à un non-auteur de la
question
- Ne jamais permettre à un utilisateur de voter pour sa propre réponse
- Ne jamais permettre à un utilisateur de valider sa propre réponse
- Ne jamais afficher de publicité pendant la saisie d'une réponse
- Ne jamais utiliser un autre système d'authentification que Firebase
Phone Auth
- Ne jamais stocker le mot de passe ou des données sensibles localement
- Ne jamais afficher les scores des autres utilisateurs comme des données
personnelles
- Ne jamais supprimer une réponse validée
- Ne jamais modifier les points manuellement côté client (uniquement via
Cloud Functions)

# ─────────────────────────────────────────
# 11. RÉFÉRENCE VISUELLE
# ─────────────────────────────────────────

visual_reference:
mockups_folder: "assets/mockups/"
description: >
Avant de coder chaque écran, consulte l'image de référence
correspondante dans assets/mockups/. Ces images représentent
exactement le design attendu. Respecte scrupuleusement :
les couleurs, l'espacement, la typographie, les icônes,
la disposition des éléments et les états (loading, error, empty, data).
screens:
- [Link] → Palette couleurs + structure dossiers
- [Link] → Splash, téléphone, OTP, onboarding
- [Link] → Fil des questions + filtres
- [Link] → Poster une question
- [Link] → Réponses + validation
- [Link] → Notifications + badge avatar
- [Link] → Classement + rangs
- [Link] → Profil utilisateur
- [Link] → Monétisation AdMob

# ─────────────────────────────────────────
# 12. INSTRUCTIONS GÉNÉRALES POUR CASCADE
# ─────────────────────────────────────────

cascade_instructions:
- >
À chaque fois que tu crées un nouvel écran, consulte d'abord
l'image de référence dans assets/mockups/ avant d'écrire le code.
- >
Utilise TOUJOURS les couleurs définies dans app_theme.dart.
Ne jamais hardcoder une couleur hexadécimale dans un widget.
- >
Après chaque écran créé, vérifie que tous les états sont gérés :
état loading (CircularProgressIndicator bleu), état erreur
(message centré avec bouton retry), état vide (message encourageant),
état données (contenu normal).
- >
Les textes de l'interface sont TOUS en français.
Les commentaires dans le code peuvent être en anglais.
- >
Chaque service (auth_service, firestore_service, etc.) doit être
injecté via Provider. Ne jamais instancier un service directement
dans un widget.
- >
Toujours tester le cas où l'utilisateur n'a pas de connexion internet.
Afficher un message d'erreur approprié sans crash.
- >
Le scoring des réponses (votes × 1 + isValidated × 5) doit être
recalculé côté serveur via Cloud Functions, jamais côté client.
- >
Pour les notifications push, utiliser Firebase Cloud Messaging (FCM).
Stocker le fcmToken dans le document users/{uid} à chaque connexion.

Vous aimerez peut-être aussi