deploy/.env ──env_file──► conteneur api ──► Settings (back/app/config.py, pydantic-settings)
│ nom de variable = champ en MAJUSCULES
│ booléen : 1/true/yes/on = vrai, 0/false/no/off = faux
▼
GET /config (back/app/main.py, config) ──► AppConfig (app/lib/models.dart)
Settings() est lu une fois au démarrage de chaque worker. Changer une valeur = modifier .env puis
docker compose up -d api (recrée le conteneur).
- L'app lit
/config au lancement. Tant qu'il n'a pas répondu, AppConfig vaut ses défauts
(ads_enabled et subscription_enabled faux).
deploy/docker-compose.yml impose SEED_DEMO=0, DATABASE_URL et REDIS_URL (prioritaires sur .env).
| Variable |
Défaut |
Effet |
Back (lu dans) |
App (lu dans) |
ADS_ENABLED |
false |
faux : aucun crédit de pub, l'app ne charge rien |
services/ads.py (grant), routers/ads.py (ad_reward_dev), main.py (/config) |
session.dart (adsAvailable), api/ads.dart (watch), screens/leaderboard/day_sheet.dart, screens/profile/profile_screen.dart (choix de confidentialité), screens/profile/subscription_screen.dart (ligne « sans pub ») |
SUBSCRIPTION_ENABLED |
false |
faux : verify et bonus en 403, page Slidz+ et icônes Slidz+ cachées |
routers/subscriptions.py (verify_subscription), routers/me.py (claim_bonus), main.py |
session.dart (démarre Purchases), screens/profile/subscription_screen.dart, profile_screen.dart, app_icon_screen.dart, screens/leaderboard/day_sheet.dart, ad_card.dart, screens/feed/feed_cards.dart |
FEED_CARD_AD_XP_ENABLED |
true |
carte « pub contre XP » dans le fil |
main.py seulement |
screens/feed/feed_cards.dart |
FEED_CARD_AD_XP_AFTER |
5 |
réponses dans la session avant la carte |
main.py seulement |
screens/feed/feed_cards.dart |
ADS_TRUST_CLIENT |
false |
ouvre POST /me/ads/reward sans Google. Jamais en production |
routers/ads.py |
api/ads.dart (appel de secours après 15 s) |
Détail de ce que SUBSCRIPTION_ENABLED coupe ou non : Slidz+. Pubs :
Publicités.
| Variable |
Défaut |
Back |
Envoyé à l'app |
XP_AD |
500 |
services/ads.py |
xp_ad |
ADS_PER_DAY |
3 |
services/ads.py, routers/me.py (ads_max) |
ads_per_day |
XP_AD_CHALLENGES |
300 |
services/ads.py |
xp_ad_challenges |
ADS_MAX_PER_DAY |
6 |
services/ads.py |
non |
XP_SUB_BONUS |
1500 |
routers/me.py |
xp_sub_bonus |
QUESTIONS_PER_DAY / _PLUS |
10 / 30 |
routers/creation.py |
oui |
GROUPS_PER_OWNER / GROUP_MAX_MEMBERS |
5 / 20 |
routers/groups.py |
oui |
AD_UNIT_REWARDED_IOS / _ANDROID |
blocs de test Google |
main.py |
ad_units |
PRODUCT_MONTHLY / PRODUCT_YEARLY |
com.soupappstudio.slidz.plus.* |
services/storekit.py, services/subscription_stats.py |
products |
| Variable |
Défaut |
Effet |
Back (lu dans) |
SEED_DEMO |
true (0 imposé en prod) |
compte lucas.drift + 30 jours d'activité de démo si events est vide |
main.py (lifespan), seed.py |
SEED_SOCIAL |
false |
joueurs, conversations, commentaires de démo |
main.py, seed.py |
MODERATION_MANUAL |
false |
vrai : aucune question publiée sans relecture |
services/moderation.py |
MODERATION_MIN_PUBLISHED |
3 |
questions publiées avant publication sans relecture |
services/moderation.py |
ANTHROPIC_API_KEY |
vide |
vide : pas de filtre automatique ni d'avis de triche |
services/moderation.py (ask_model, aussi utilisé par services/cheat.py) |
MODERATION_MODEL / CHEAT_MODEL |
claude-haiku-5-5 / claude-sonnet-5-5 |
modèles appelés |
services/moderation.py, services/cheat.py |
FCM_CREDENTIALS_FILE |
/run/secrets/slidz/firebase.json |
fichier absent : aucun push |
services/push.py (firebase) |
ADMIN_PSEUDOS |
vide |
chaque pseudo listé devient admin au démarrage (jamais retiré) |
main.py (lifespan) |
CORS_ORIGINS |
vide |
vide : pas de middleware CORS |
main.py |
ANALYTICS_TZ |
Europe/Paris |
fuseau des journées de la console |
services/localtime.py |
JWT_SECRET / JWT_DAYS |
valeur de dev / 30 |
signature et durée des jetons |
security.py |
| Option |
Effet |
Lu dans |
SERVER |
adresse de l'API (sinon https://api.slidzapp.com en release, localhost:8000 simulateur iOS, 10.0.2.2:8000 émulateur Android) |
lib/api/api.dart |
SLIDZ_SCREEN |
écran ouvert au lancement (debug seulement) |
lib/main.dart |
SLIDZ_MENU |
ouvre le menu des thèmes (debug seulement) |
lib/main.dart |
ADS_TEST_DEVICE |
appareil de test AdMob, affiche l'erreur de chargement |
lib/api/ads.dart |
SLIDZ_LIVE, SLIDZ_SERVER |
tests de contrat contre un back (localhost:8000 par défaut) |
test/live_api_test.dart, test/live_flow_test.dart |
Pas de flag « badges » : les badges sont toujours actifs.
CLAUDE.md dit « Badges, Slidz+ et pubs derrière des flags (à faux) » : en production ADS_ENABLED=1 depuis le
7 octobre 2026 et SUBSCRIPTION_ENABLED activé le 10 octobre 2026 (feuille de route). Aucun flag n'existe pour les
badges.
deploy/DEPLOY.md dit « Le premier compte listé dans ADMIN_PSEUDOS devient administrateur » : le code promeut
tous les pseudos de la liste. Retirer un pseudo de la liste ne retire pas le droit (python -m app.cli revoke-admin).
JWT_SECRET a une valeur par défaut de développement dans config.py : rien n'empêche l'API de démarrer si la
variable manque en production.
/config envoie les icônes Slidz+ même quand SUBSCRIPTION_ENABLED est faux ; seule l'app les filtre.
- Création de groupe et quota de 30 questions ne dépendent pas de
SUBSCRIPTION_ENABLED (seulement de
user.subscribed).
Code : back/app/config.py (Settings), back/app/main.py (lifespan, config), app/lib/models.dart
(AppConfig), app/lib/session.dart, app/lib/api/ads.dart, app/lib/api/api.dart, app/lib/main.dart,
deploy/docker-compose.yml