ADRADR-0048 · Le tableau de bord est desktop-only (>= 1024 px), les surfaces publiques mobile-first

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

OptionPourquoi non
Garder la porte User-AgentFaux 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 rendueL'app reste focusable au clavier sous l'overlay. display: none la retire des deux arbres sans JS
Rendre le tableau de bord responsiveUne 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.tsLe proxy ne connait pas la largeur du viewport, seulement l'UA : c'est la premiere option
Mettre /onboarding derriere la porteIl 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 de max-width media query, pas de useIsMobile, 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.ts echoue si la porte quitte le layout, ou si du code du tableau de bord importe un hook mobile ou ajoute une media query max-width.
  • Signal pour revisiter : une part mesuree de sessions authentifiees sous 1024 px qui ne se convertit pas vers un ordinateur ou vers WhatsApp.