ADR-0048 — Le tableau de bord est desktop-only (>= 1024 px), les surfaces publiques mobile-first
L'application authentifiee (tout ce qui vit sous src/app/(dashboard) : le cockpit d'une boutique et sa scene, le chat @Atlas, le Studio, l'espace vendeur, /account, /admin, /ops, /collab) est une surface a trois…
Statut
Accepté · 2026-09-26
Piliers : app-shell, ai-platform, design-system
Origine : docs/decisions/0043-le-tableau-de-bord-est-desktop-only.md du dépôt applicatif, ancien numéro 0043. Le dépôt applicatif portait deux ADR 0043 : « Le plan C (agence) est retiré » garde 0043, celle-ci prend 0048, le seul numéro libre de la série. Provenance historique : migration des docs de l’app.
Contexte
L'application authentifiee (tout ce qui vit sous src/app/(dashboard) : le
cockpit d'une boutique et sa scene, le chat @Atlas, le Studio, l'espace
vendeur, /account, /admin, /ops, /collab) est une surface a trois
colonnes redimensionnables, une preview de boutique, une toolbar a modes et
un pied de page a onglets. Aucune de ces pieces n'a de sens sous 1024 px.
Deux tentatives ont coexiste et se contredisaient :
- une porte serveur sur le User-Agent dans
(dashboard)/layout.tsx, qui laissait passer un iPad en mode bureau (UA Mac) et une fenetre de bureau etroite, et bloquait un telephone qu'on aurait pu tourner ; - un « layout mobile » du chat (
shells/platform/mobile-layout.ts), ajoute dans le commit « chat thread survives reload... », qui repliait la scene en chat plein ecran sous un seuil JS. Il a casse cinq tests de redimensionnement des panneaux, et chaque surface du tableau de bord aurait du recevoir la meme deuxieme grammaire.
Pendant ce temps l'audit e2e (e2e/.audit/gaps.json) montrait que la plage
qui compte vraiment, 1024 a 1440 px (un portable), avait des chevauchements
reels : le stepper centre en absolu par-dessus le nom de la boutique, le
statut de l'agent tronque en « Work… ».
Les surfaces publiques sont l'inverse : le site marketing, la doc, /auth
et l'OTP, /onboarding (ouvert juste apres l'inscription, souvent depuis
l'e-mail OTP sur un telephone), /drop/[token], /embed/*, /status. Un
inconnu les ouvre sur son telephone.
Décision
Le tableau de bord est desktop-only a partir de 1024 px (lg de Tailwind),
les surfaces publiques restent mobile-first. La porte est UNE regle CSS dans
src/app/(dashboard)/layout.tsx : sous lg, un ecran noir plein ecran
explique dans la langue de l'utilisateur que BoostEcom est concu pour un
ordinateur, avec « Copier le lien » et « Envoyer a… » (navigator.share,
absent si le navigateur ne l'expose pas) ; l'application dessous est en
display: none, donc hors de l'arbre d'accessibilite et de l'ordre de
tabulation. Aucun code du tableau de bord ne porte de variante mobile.
Alternatives écartées
| Option | Pourquoi non |
|---|---|
| Garder la porte User-Agent | Faux dans les deux sens : un iPad en mode bureau passe, une fenetre de bureau a 800 px aussi et rend un cockpit casse. La largeur est ce qui compte, pas l'appareil |
Media query JS (useIsMobile, matchMedia) | Rien a hydrater pour une decision que le CSS prend seul, et un flash du cockpit avant l'effet. C'est aussi la porte d'entree des variantes mobiles qu'on retire |
Un overlay aria-hidden par-dessus une app toujours rendue | L'app reste focusable au clavier sous l'overlay. display: none la retire des deux arbres sans JS |
| Rendre le tableau de bord responsive | Une seconde grammaire pour chaque surface, que personne ne teste, pour un usage que le canal WhatsApp couvre deja. Le layout mobile du chat en etait le premier morceau, et il a casse les panneaux |
Porter la porte dans src/proxy.ts | Le proxy ne connait pas la largeur du viewport, seulement l'UA : c'est la premiere option |
Mettre /onboarding derriere la porte | Il vit dans (minimal), il est atteint depuis l'e-mail OTP, souvent sur telephone, et il doit rester utilisable |
Conséquences
- Toute surface sous
src/app/(dashboard)peut supposer au moins 1024 px : pas demax-widthmedia query, pas deuseIsMobile, pas de drawer mobile. Le budget d'effort va a 1024-1440 px, la vraie largeur d'un portable. - Un composant partage avec une surface publique (
src/components/**rendu aussi par(marketing),(docs),(minimal)ou/embed) garde ses variantes mobiles : la regle vaut pour le code du tableau de bord, pas pour le design system. - Les portails (dialogs, menus, toasts) sont montes hors de l'enveloppe
masquee. Sous 1024 px rien ne peut en ouvrir, puisque l'application n'est
pas rendue ; une modale ouverte avant un redimensionnement reste dessous
l'overlay (
z-[9999]), les toasts restent au-dessus. - Garde :
src/test/dashboard-is-desktop-only.test.tsechoue si la porte quitte le layout, ou si du code du tableau de bord importe un hook mobile ou ajoute une media querymax-width. - Signal pour revisiter : une part mesuree de sessions authentifiees sous 1024 px qui ne se convertit pas vers un ordinateur ou vers WhatsApp.