Vercel : L'expérience développeur comme design

Comment Vercel a fait de l'expérience développeur le produit : design dark-mode-first, indicateurs de statut d'onglet, UI optimiste et états vides fonctionnels. Avec motifs d'implémentation CSS et JavaScript.

7 min de lecture 1322 mots
Vercel : L'expérience développeur comme design screenshot

Vercel : l'expérience développeur comme philosophie de design

« Les développeurs sont allergiques à la mauvaise UX — ils ne veulent pas d'un "onboarding enchanteur" si ça les ralentit. »

La philosophie de design de Vercel est résolument centrée sur le développeur. Le design system Geist privilégie la clarté, la rapidité et la densité d'information plutôt que la décoration. Chaque pixel est au service du workflow du développeur.


Pourquoi Vercel compte

Vercel démontre que les outils pour développeurs peuvent bénéficier d'un design exceptionnel sans être « tape-à-l'œil ». Le dashboard est rapide, dense en information et sait se faire oublier.

Réalisations clés : - Création de Geist, une police de caractères conçue spécifiquement pour les développeurs - La refonte du dashboard a réduit le First Meaningful Paint de 1,2 s - Pionnier du design dark-mode-first dans l'outillage développeur - Référence en matière d'UX de déploiement - Icônes d'onglet reflétant l'état du déploiement (en cours de build, erreur, prêt)


Points clés à retenir

  1. Le dark mode est un signe de respect, pas une fonctionnalité — Les développeurs travaillent dans des terminaux et des IDE sur fond sombre ; un dashboard blanc crée des ruptures visuelles brutales et une fatigue oculaire
  2. Le statut doit être visible partout où le regard se pose — Favicons d'onglet, titres de page, points de la timeline : l'état du déploiement doit être visible sans changer de focus ni ouvrir d'autres onglets
  3. L'UI optimiste élimine la latence perçue — Afficher immédiatement l'état attendu, synchroniser avec la réalité en arrière-plan ; les développeurs remarquent les délais de 300 ms
  4. Les états vides sont des instructions, pas des illustrations — Afficher la commande exacte à exécuter (git push origin main), pas un graphique décoratif avec un bouton « Commencer »
  5. La performance, c'est du design — La refonte du dashboard de Vercel a réduit le First Meaningful Paint de 1,2 s ; aucune animation, aussi belle soit-elle, ne compense des temps de chargement lents

Philosophie de design fondamentale

Le principe centré développeur

Les développeurs jugent les produits à la mesure de ce qu'ils les ralentissent. Le design de Vercel reflète cette réalité :

ANTI-PATTERNS (Ce que les développeurs détestent)  APPROCHE DE VERCEL
───────────────────────────────────────────────────────────────────
Animations "enchantantes" qui ajoutent du délai   États instantanés, sans transition
Assistants d'onboarding qui bloquent le travail   CLI d'abord, dashboard optionnel
Documentation dense cachée dans des onglets        Information visible d'un coup d'œil
Spinners de chargement à chaque action             Mises à jour optimistes + SWR
Discours marketing dans le dashboard               UI purement fonctionnelle

Insight clé : Les développeurs ne veulent pas être « enchantés ». Ils veulent livrer.


Bibliothèque de patterns

1. Excellence du dark mode

Le dark mode de Vercel n'est pas une option à activer. C'est le choix par défaut. Le design est chirurgical : un noir et blanc franc crée un contraste maximal.

Philosophie des couleurs :

:root {
  /* The Vercel palette is remarkably simple */

  /* Backgrounds - pure black, no gray */
  --bg-000: #000000;
  --bg-100: #0A0A0A;
  --bg-200: #111111;

  /* Foreground - high contrast white */
  --fg-100: #FFFFFF;
  --fg-200: #EDEDED;
  --fg-300: #A1A1A1;
  --fg-400: #888888;

  /* Borders - subtle but visible */
  --border-100: #333333;
  --border-200: #444444;

  /* Semantic - deployment status */
  --color-success: #00DC82;  /* Green - deployed */
  --color-error: #FF0000;    /* Red - failed */
  --color-warning: #FFAA00;  /* Amber - building */
  --color-info: #0070F3;     /* Blue - queued */

  /* The accent - Vercel's signature */
  --accent: #FFFFFF;         /* White as accent on black */
}

Pourquoi le noir pur fonctionne : - Contraste maximal pour la lisibilité du texte - Esthétique inspirée du terminal, en laquelle les développeurs ont confiance - Réduit la fatigue oculaire dans les environnements sombres - Fait ressortir les indicateurs de statut colorés


2. Indicateurs de statut dans les onglets

Vercel reflète l'état du déploiement dans les icônes des onglets du navigateur, rendant l'information visible même lorsque l'onglet n'est pas au premier plan.

┌─ Barre d'onglets du navigateur ────────────────────────────────────┐
│                                                                    │
│  [▶] acme-web - Building    [✓] blog - Ready    [✕] api - Error   │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

États des icônes d'onglet :
  ⏳ En file d'attente (cercle gris)
  ▶  En cours de build (spinner animé)
  ✓  Prêt (coche verte)
  ✕  Erreur (X rouge)

Pattern d'implémentation :

// Dynamic favicon based on deployment status
function updateFavicon(status) {
  const link = document.querySelector("link[rel~='icon']");

  const icons = {
    queued: '/favicon-queued.svg',
    building: '/favicon-building.svg',  // Animated
    ready: '/favicon-ready.svg',
    error: '/favicon-error.svg',
  };

  link.href = icons[status];
}

// Title also reflects status
function updateTitle(projectName, status) {
  const prefixes = {
    queued: '⏳',
    building: '▶',
    ready: '✓',
    error: '✕',
  };

  document.title = `${prefixes[status]} ${projectName} - Vercel`;
}

Insight clé : Les développeurs ont de nombreux onglets ouverts. Un statut visible dans la barre d'onglets leur évite de changer d'onglet pour vérifier l'état du build.


3. Timeline de déploiement

L'inspecteur de déploiement affiche une timeline claire du processus de déploiement.

┌─ Timeline de déploiement ──────────────────────────────────────────┐
│                                                                    │
│  [o] En file d'attente                       12:34:56 PM           │
│  │                                                                 │
│  [o] Build en cours                          12:34:58 PM           │
│  │ └─ Installation des dépendances... 3,2 s                        │
│  │ └─ Build... 12,4 s                                              │
│  │ └─ Génération des pages statiques... 2,1 s                      │
│  │                                                                 │
│  [o] Déploiement                             12:35:14 PM           │
│  │ └─ Upload des artefacts de build...                              │
│  │                                                                 │
│  [*] Prêt                                    12:35:18 PM           │
│    └─ https://acme-abc123.vercel.app                               │
│                                                                    │
│  Total : 22 s                                                      │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Encodage visuel :

.timeline-step {
  position: relative;
  padding-left: 24px;
}

.timeline-step::before {
  content: '';
  position: absolute;
  left: 0;
  top: 6px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--step-color);
}

/* Connecting line */
.timeline-step:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 16px;
  width: 2px;
  height: calc(100% - 6px);
  background: var(--border-100);
}

/* Step states */
.timeline-step[data-status="complete"]::before {
  background: var(--color-success);
}

.timeline-step[data-status="active"]::before {
  background: var(--color-warning);
  animation: pulse 1.5s infinite;
}

.timeline-step[data-status="error"]::before {
  background: var(--color-error);
}

.timeline-step[data-status="pending"]::before {
  background: var(--fg-400);
}

4. Design du visualiseur de logs

Le visualiseur de logs de Vercel est intégré dans la vue d’ensemble du déploiement, et non sur une page séparée.

┌─ Build Logs ───────────────────────────────────────────────────────┐
│                                                                    │
│  Filter: [All ▼]  [Function: api/hello ▼]           [Copy] [↓]    │
│                                                                    │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  12:34:58.123  info   Installing dependencies...                   │
│  12:35:01.456  info   added 1234 packages in 3.2s                  │
│  12:35:01.789  info   Running build...                             │
│  12:35:14.012  info   ✓ Compiled successfully                      │
│  12:35:14.234  warn   Large bundle size: pages/index.js (245kb)    │
│  12:35:14.567  info   Generating static pages...                   │
│  12:35:16.890  info   ✓ Generated 42 pages                         │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Fonctionnalités clés : - Copie dans le presse-papiers en un clic - Filtrage par fonction ou sortie de build - Niveaux de log avec code couleur (info, warn, error) - Horodatages avec précision à la milliseconde - URLs partageables pour des lignes de log spécifiques

Implémentation :

.log-line {
  display: flex;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.6;
  padding: 2px 12px;
}

.log-line:hover {
  background: var(--bg-200);
}

.log-timestamp {
  color: var(--fg-400);
  min-width: 100px;
  margin-right: 12px;
}

.log-level {
  min-width: 48px;
  margin-right: 12px;
}

.log-level[data-level="info"] { color: var(--fg-300); }
.log-level[data-level="warn"] { color: var(--color-warning); }
.log-level[data-level="error"] { color: var(--color-error); }

.log-message {
  color: var(--fg-100);
  white-space: pre-wrap;
  word-break: break-word;
}

5. États vides

Les états vides de Vercel sont fonctionnels, pas décoratifs. Ils indiquent à l’utilisateur la prochaine action à effectuer.

┌─ Empty State: No Deployments ──────────────────────────────────────┐
│                                                                    │
│                                                                    │
│                         No deployments yet                         │
│                                                                    │
│               Push to your repository to create                    │
│                    your first deployment                           │
│                                                                    │
│                                                                    │
│           git push origin main                                     │
│                                                                    │
│                                                                    │
│                         [View Documentation]                       │
│                                                                    │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Principes de design : - Aucune illustration décorative - Action claire (la commande git) - Lien utile vers la documentation - Police monospace pour les commandes (facilite la copie)


Système de design visuel

Typographie (Geist)

Vercel a créé Geist spécifiquement pour les expériences développeur :

:root {
  /* Geist Sans - UI and body text */
  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Geist Mono - code and technical content */
  --font-mono: 'Geist Mono', 'SF Mono', monospace;

  /* Size scale */
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-lg: 16px;
  --text-xl: 18px;
  --text-2xl: 24px;

  /* Line heights */
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;

  /* Letter spacing */
  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.02em;
}

/* Tabular numbers for data */
.tabular-nums {
  font-variant-numeric: tabular-nums;
}

/* Or use Geist Mono for comparisons */
.data-value {
  font-family: var(--font-mono);
}

Système d’espacement

:root {
  /* 4px base unit */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
}

Border Radius

:root {
  /* Rayons subtils et cohérents */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-xl: 12px;
  --radius-full: 9999px;
}

Patterns d'animation

Mises à jour optimistes

Vercel utilise des mises à jour UI optimistes. Les actions semblent instantanées.

// Pattern SWR pour les mises à jour en temps réel
const { data, mutate } = useSWR('/api/deployments');

async function triggerDeploy() {
  // Afficher immédiatement l'état "deploying"
  mutate(
    { ...data, status: 'building' },
    false  // Ne pas revalider tout de suite
  );

  // Puis déclencher réellement
  await fetch('/api/deploy', { method: 'POST' });

  // Revalider pour obtenir l'état réel
  mutate();
}

États de chargement subtils

/* Chargement skeleton - pas de spinners */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--bg-200) 0%,
    var(--bg-100) 50%,
    var(--bg-200) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: var(--radius-md);
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

États des boutons

.button {
  transition: background 100ms ease, transform 100ms ease;
}

.button:hover {
  background: var(--fg-100);
}

.button:active {
  transform: scale(0.98);
}

/* Pas de longues transitions - retour instantané */

Optimisations de performance (guidées par le design)

La refonte du tableau de bord de Vercel incluait des décisions de design qui ont amélioré les performances :

Techniques utilisées : - Préconnexion aux origines API, Assets et Avatar - Les appels API critiques reçoivent une priorité navigateur plus élevée - Mémoïsation des composants React (useMemo, useCallback) - ReactDOM.unstable_batchedUpdates a réduit les re-rendus de 20 % - SWR pour des mises à jour en temps réel efficaces

Point clé : La performance EST du design. Un tableau de bord lent avec de belles animations est pire qu'un tableau de bord rapide sans aucune animation.


Leçons pour notre travail

1. Le mode sombre par défaut

Quand vos utilisateurs travaillent dans des environnements sombres (terminaux, IDE), le mode sombre n'est pas une fonctionnalité — c'est du respect.

2. Le statut partout

Icônes d'onglets, titres de pages, indicateurs de timeline : le statut doit être visible sans avoir à se concentrer dessus.

3. Optimiste par défaut

Afficher l'état attendu immédiatement. Mettre à jour avec la réalité en arrière-plan.

4. Les développeurs détestent attendre

Pas de spinners de chargement si vous pouvez les éviter. États skeleton, mises à jour optimistes, prefetching.

5. Les états vides sont des instructions

N'affichez pas une jolie illustration. Montrez la commande qu'ils doivent exécuter.


Foire aux questions

Pourquoi Vercel utilise-t-il du noir pur (#000000) plutôt que du gris foncé pour les arrière-plans ?

Le noir pur offre un contraste maximal pour le texte blanc, créant une lisibilité optimale. Il correspond également à l'esthétique des terminaux et éditeurs de code que les développeurs utilisent déjà, ce qui donne au tableau de bord l'impression de faire naturellement partie de leur environnement de travail. Les arrière-plans gris foncé semblent souvent plus « doux » mais réduisent le contraste et peuvent paraître délavés sur les écrans haute résolution.

Comment fonctionnent les indicateurs de statut dans les onglets de Vercel ?

Vercel met à jour dynamiquement le favicon du navigateur en fonction du statut de déploiement : un spinner pour la compilation, une coche verte pour « prêt », un X rouge pour une erreur. Le titre de la page est également mis à jour avec des préfixes emoji (▶, ✓, ✕). Cela signifie que les développeurs peuvent surveiller plusieurs déploiements à travers les onglets sans changer de focus — le statut est visible d'un coup d'œil dans la barre d'onglets du navigateur.

Quelle est l'approche de Vercel concernant les états de chargement ?

Vercel évite les spinners de chargement traditionnels au profit de l'UI optimiste et des écrans skeleton. Lorsque vous déclenchez un déploiement, l'interface affiche immédiatement l'état « building » avant la confirmation du serveur. La bibliothèque SWR gère la revalidation en arrière-plan. Cela donne aux actions une impression d'instantanéité même lorsque les requêtes réseau prennent 200 à 500 ms.

Qu'est-ce que Geist et pourquoi Vercel a-t-il créé une police personnalisée ?

Geist est une famille typographique que Vercel a conçue spécifiquement pour les interfaces développeur. Elle comprend Geist Sans pour le texte d'interface et Geist Mono pour le code. Le design est optimisé pour les petites tailles (12-14px) courantes dans les tableaux de bord, inclut des chiffres tabulaires pour l'alignement des colonnes de données, et possède des formes de caractères distinctes pour éviter la confusion entre glyphes similaires (l, 1, I).

Comment Vercel gère-t-il les états vides différemment des autres produits ?

Les états vides de Vercel affichent des commandes exploitables, pas des illustrations décoratives. Une page de déploiements vide affiche git push origin main en police monospace (facilitant le copier-coller) plutôt qu'un dessin avec un bouton générique « Commencer ». La philosophie est que les développeurs veulent savoir exactement quoi faire, pas être visuellement apaisés.