Vercel: Experiência do Desenvolvedor como Design

Como a Vercel transformou a experiência do desenvolvedor no produto: design dark-mode-first, indicadores de status em abas, UI otimista e empty states funcionais. Com padrões de implementação em CSS e JavaScript.

5 min de leitura 1161 palavras
Vercel: Experiência do Desenvolvedor como Design screenshot

Vercel: Experiência do Desenvolvedor como Design

"Desenvolvedores são alérgicos a UX ruim—eles não querem 'onboarding encantador' se isso os deixar mais lentos."

A filosofia de design da Vercel é impiedosamente centrada no desenvolvedor. O sistema de design Geist prioriza clareza, velocidade e densidade de informação em vez de decoração. Cada pixel serve ao fluxo de trabalho do desenvolvedor.


Por que a Vercel Importa

A Vercel prova que ferramentas para desenvolvedores podem ter design excepcional sem serem "design demais". O dashboard é rápido, denso em informações e sai do caminho.

Conquistas principais: - Criou o Geist, uma fonte projetada especificamente para desenvolvedores - O redesign do dashboard diminuiu o First Meaningful Paint em 1,2s - Pioneira no design dark-mode-first em ferramentas para desenvolvedores - Definiu o padrão para UX de deploy - Ícones de aba que refletem o status do deploy (building, error, ready)


Principais Aprendizados

  1. Modo escuro é respeito, não uma funcionalidade - Desenvolvedores trabalham em terminais e IDEs com fundos escuros; um dashboard branco cria trocas de contexto incômodas e cansaço visual
  2. Status pertence a todo lugar que você possa ver - Favicons das abas, títulos de página, pontos na timeline: o status do deploy deve ser visível sem trocar o foco ou abrir abas
  3. UI otimista elimina latência percebida - Mostre o estado esperado imediatamente, sincronize com a realidade em segundo plano; desenvolvedores percebem atrasos de 300ms
  4. Estados vazios são instruções, não ilustrações - Mostre o comando exato a executar (git push origin main), não um gráfico decorativo com botão "Começar"
  5. Performance é design - O redesign do dashboard da Vercel diminuiu o First Meaningful Paint em 1,2s; nenhuma quantidade de animações bonitas compensa tempos de carregamento lentos

Filosofia Central de Design

O Princípio Centrado no Desenvolvedor

Desenvolvedores julgam produtos pelo quanto eles os deixam mais lentos. O design da Vercel reflete isso:

ANTI-PADRÕES (O que desenvolvedores odeiam)    ABORDAGEM DA VERCEL
───────────────────────────────────────────────────────────────────
Animações "encantadoras" que adicionam delay   Estados instantâneos, sem transição
Wizards de onboarding que bloqueiam o trabalho CLI-first, dashboard opcional
Documentação densa escondida em abas           Informação visível de relance
Spinners de loading em cada ação               Updates otimistas + SWR
Texto de marketing no dashboard                UI puramente funcional

Insight principal: Desenvolvedores não querem ser "encantados". Eles querem fazer deploy.


Biblioteca de Padrões

1. Excelência no Modo Escuro

O modo escuro da Vercel não é um toggle. É o padrão. O design é cirúrgico: preto e branco austeros criam contraste máximo.

Filosofia de cores:

:root {
  /* A paleta da Vercel é notavelmente simples */

  /* Fundos - preto puro, sem cinza */
  --bg-000: #000000;
  --bg-100: #0A0A0A;
  --bg-200: #111111;

  /* Primeiro plano - branco de alto contraste */
  --fg-100: #FFFFFF;
  --fg-200: #EDEDED;
  --fg-300: #A1A1A1;
  --fg-400: #888888;

  /* Bordas - sutis mas visíveis */
  --border-100: #333333;
  --border-200: #444444;

  /* Semântico - status do deploy */
  --color-success: #00DC82;  /* Verde - deployed */
  --color-error: #FF0000;    /* Vermelho - failed */
  --color-warning: #FFAA00;  /* Âmbar - building */
  --color-info: #0070F3;     /* Azul - queued */

  /* O destaque - assinatura da Vercel */
  --accent: #FFFFFF;         /* Branco como destaque no preto */
}

Por que preto puro funciona: - Contraste máximo para legibilidade do texto - Estética inspirada em terminal que desenvolvedores confiam - Reduz cansaço visual em ambientes escuros - Faz indicadores de status coloridos se destacarem


2. Indicadores de Status na Aba

A Vercel reflete o status do deploy nos ícones das abas do navegador, tornando a informação visível mesmo quando a aba não está em foco.

┌─ Barra de Abas do Navegador ───────────────────────────────────────┐
│                                                                    │
│  [▶] acme-web - Building    [✓] blog - Ready    [✕] api - Error   │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Estados do Ícone da Aba:
  ⏳ Queued (círculo cinza)
  ▶  Building (spinner animado)
  ✓  Ready (checkmark verde)
  ✕  Error (X vermelho)

Padrão de implementação:

// Favicon dinâmico baseado no status do deploy
function updateFavicon(status) {
  const link = document.querySelector("link[rel~='icon']");

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

  link.href = icons[status];
}

// O título também reflete o status
function updateTitle(projectName, status) {
  const prefixes = {
    queued: '⏳',
    building: '▶',
    ready: '✓',
    error: '✕',
  };

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

Insight principal: Desenvolvedores têm muitas abas abertas. Status visível na barra de abas significa que eles não precisam trocar de aba para verificar o status do build.


3. Timeline de Deploy

O inspetor de deploy mostra uma timeline clara do processo de deploy.

┌─ Timeline de Deploy ───────────────────────────────────────────────┐
│                                                                    │
│  [o] Queued                                  12:34:56 PM           │
│  │                                                                 │
│  [o] Building                                12:34:58 PM           │
│  │ └─ Installing dependencies... 3.2s                              │
│  │ └─ Building... 12.4s                                            │
│  │ └─ Generating static pages... 2.1s                              │
│  │                                                                 │
│  [o] Deploying                               12:35:14 PM           │
│  │ └─ Uploading build outputs...                                   │
│  │                                                                 │
│  [*] Ready                                   12:35:18 PM           │
│    └─ https://acme-abc123.vercel.app                               │
│                                                                    │
│  Total: 22s                                                        │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Codificação visual:

.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);
}

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

/* Estados das etapas */
.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 do Visualizador de Logs

O visualizador de logs da Vercel é integrado à visão geral do deploy, não uma página separada.

┌─ Build Logs ───────────────────────────────────────────────────────┐
│                                                                    │
│  Filtro: [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                         │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Recursos principais: - Copiar para área de transferência com um clique - Filtrar por função ou output do build - Níveis de log com cores (info, warn, error) - Timestamps com precisão de milissegundos - URLs compartilháveis para linhas específicas de log

Implementação:

.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. Estados Vazios

Os estados vazios da Vercel são funcionais, não decorativos. Eles dizem o que fazer a seguir.

┌─ Estado Vazio: Sem Deploys ────────────────────────────────────────┐
│                                                                    │
│                                                                    │
│                       Nenhum deploy ainda                          │
│                                                                    │
│               Faça push para seu repositório para criar            │
│                       seu primeiro deploy                          │
│                                                                    │
│                                                                    │
│           git push origin main                                     │
│                                                                    │
│                                                                    │
│                        [Ver Documentação]                          │
│                                                                    │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Princípios de design: - Sem ilustrações decorativas - Ação clara (o comando git) - Link útil para a documentação - Monospace para comandos (fácil de copiar)


Sistema de Design Visual

Tipografia (Geist)

A Vercel criou o Geist especificamente para experiências de desenvolvedores:

:root {
  /* Geist Sans - UI e corpo de texto */
  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Geist Mono - código e conteúdo técnico */
  --font-mono: 'Geist Mono', 'SF Mono', monospace;

  /* Escala de tamanhos */
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-lg: 16px;
  --text-xl: 18px;
  --text-2xl: 24px;

  /* Alturas de linha */
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;

  /* Espaçamento entre letras */
  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.02em;
}

/* Números tabulares para dados */
.tabular-nums {
  font-variant-numeric: tabular-nums;
}

/* Ou use Geist Mono para comparações */
.data-value {
  font-family: var(--font-mono);
}

Sistema de Espaçamento

:root {
  /* Unidade base de 4px */
  --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;
}

Raio de Borda

:root {
  /* Raios sutis e consistentes */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-xl: 12px;
  --radius-full: 9999px;
}

Padrões de Animação

Updates Otimistas

A Vercel usa updates de UI otimistas. Ações parecem instantâneas.

// Padrão SWR para updates em tempo real
const { data, mutate } = useSWR('/api/deployments');

async function triggerDeploy() {
  // Mostrar estado "deploying" imediatamente
  mutate(
    { ...data, status: 'building' },
    false  // Não revalidar ainda
  );

  // Então realmente disparar
  await fetch('/api/deploy', { method: 'POST' });

  // Revalidar para obter o estado real
  mutate();
}

Estados de Carregamento Sutis

/* Carregamento skeleton - sem 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; }
}

Estados de Botão

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

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

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

/* Sem transições longas - feedback instantâneo */

Otimizações de Performance (Informadas pelo Design)

O redesign do dashboard da Vercel incluiu decisões de design que melhoraram a performance:

Técnicas usadas: - Preconnecting para origens de API, Assets e Avatar - Chamadas críticas de API recebem prioridade maior do navegador - Memoização de componentes React (useMemo, useCallback) - ReactDOM.unstable_batchedUpdates reduziu re-renders em 20% - SWR para updates de dados em tempo real eficientes

Insight principal: Performance É design. Um dashboard lento com animações bonitas é pior que um dashboard rápido sem nenhuma.


Lições para Nosso Trabalho

1. Modo Escuro como Padrão

Quando seus usuários trabalham em ambientes escuros (terminais, IDEs), modo escuro não é uma funcionalidade—é respeito.

2. Status em Todo Canto

Ícones de aba, títulos de página, indicadores de timeline: status deve ser visível sem foco.

3. Otimista por Padrão

Mostre o estado esperado imediatamente. Atualize com a realidade em segundo plano.

4. Desenvolvedores Odeiam Esperar

Sem spinners de carregamento se você puder evitá-los. Estados skeleton, updates otimistas, prefetching.

5. Estados Vazios São Instruções

Não mostre uma ilustração bonita. Mostre o comando que eles precisam executar.


Perguntas Frequentes

Por que a Vercel usa preto puro (#000000) em vez de cinza escuro para fundos?

Preto puro fornece contraste máximo para texto branco, criando legibilidade ideal. Também combina com a estética de terminais e editores de código que desenvolvedores já usam, fazendo o dashboard parecer parte nativa do fluxo de trabalho deles. Fundos cinza escuro frequentemente parecem "mais suaves" mas reduzem o contraste e podem parecer desbotados em displays de alta DPI.

Como funcionam os indicadores de status na aba da Vercel?

A Vercel atualiza dinamicamente o favicon do navegador baseado no status do deploy: um spinner para building, checkmark verde para ready, X vermelho para error. O título da página também atualiza com prefixos de emoji (▶, ✓, ✕). Isso significa que desenvolvedores podem monitorar múltiplos deploys em várias abas sem trocar o foco—status é visível de relance na barra de abas do navegador.

Qual é a abordagem da Vercel para estados de carregamento?

A Vercel evita spinners de carregamento tradicionais em favor de UI otimista e telas skeleton. Quando você dispara um deploy, a UI imediatamente mostra o estado "building" antes do servidor confirmar. A biblioteca SWR lida com revalidação em segundo plano. Isso faz as ações parecerem instantâneas mesmo quando requests de rede levam 200-500ms.

O que é Geist e por que a Vercel criou uma fonte personalizada?

Geist é uma família de fontes que a Vercel projetou especificamente para interfaces de desenvolvedores. Inclui Geist Sans para texto de UI e Geist Mono para código. O design é otimizado para tamanhos pequenos (12-14px) comuns em dashboards, inclui números tabulares para colunas de dados alinhadas, e tem formas de caracteres distintas para prevenir confusão entre glifos similares (l, 1, I).

Como a Vercel lida com estados vazios diferentemente de outros produtos?

Os estados vazios da Vercel mostram comandos acionáveis, não ilustrações decorativas. Uma página de deploys vazia exibe git push origin main em monospace (facilitando a cópia) em vez de um desenho com um botão genérico "Começar". A filosofia é que desenvolvedores querem saber exatamente o que fazer, não serem visualmente acalmados.