design/vercel
Vercel: Developer Experience jako filozofia projektowania
„Developerzy są uczuleni na złe UX—nie chcą 'zachwycającego onboardingu', jeśli ich spowalnia."
Filozofia projektowania Vercel jest bezwzględnie skoncentrowana na developerach. System projektowy Geist stawia na klarowność, szybkość i gęstość informacji ponad dekorację. Każdy piksel służy przepływowi pracy developera.
Dlaczego Vercel ma znaczenie
Vercel udowadnia, że narzędzia developerskie mogą mieć wyjątkowy design bez bycia „designerskimi". Dashboard jest szybki, gęsty informacyjnie i nie przeszkadza w pracy.
Kluczowe osiągnięcia: - Stworzenie Geist, kroju pisma zaprojektowanego specjalnie dla developerów - Redesign dashboardu zmniejszył First Meaningful Paint o 1,2s - Pionierskie podejście dark-mode-first w narzędziach developerskich - Wyznaczenie standardu dla UX wdrożeń - Ikony kart odzwierciedlające status deploymentu (budowanie, błąd, gotowy)
Kluczowe wnioski
- Tryb ciemny to szacunek, nie funkcja - Developerzy pracują w terminalach i IDE z ciemnym tłem; biały dashboard tworzy irytujące przełączanie kontekstu i zmęczenie oczu
- Status powinien być widoczny wszędzie - Favicony kart, tytuły stron, kropki na osi czasu: status deploymentu powinien być widoczny bez przełączania fokusa czy otwierania kart
- Optymistyczny UI eliminuje postrzeganą latencję - Pokaż oczekiwany stan natychmiast, synchronizuj z rzeczywistością w tle; developerzy zauważają opóźnienia 300ms
- Puste stany to instrukcje, nie ilustracje - Pokaż dokładną komendę do uruchomienia (
git push origin main), nie dekoracyjną grafikę z przyciskiem „Rozpocznij" - Wydajność to design - Redesign dashboardu Vercel zmniejszył First Meaningful Paint o 1,2s; żadna ilość pięknych animacji nie rekompensuje wolnego ładowania
Podstawowa filozofia projektowania
Zasada skoncentrowana na developerze
Developerzy oceniają produkty po tym, jak mało ich spowalniają. Design Vercel to odzwierciedla:
ANTYWZORCE (Co developerzy nienawidzą) PODEJŚCIE VERCEL
───────────────────────────────────────────────────────────────────
„Zachwycające" animacje dodające opóźnienia Natychmiastowe stany bez przejść
Kreatory onboardingu blokujące pracę CLI-first, dashboard opcjonalny
Gęsta dokumentacja ukryta w kartach Informacje widoczne na pierwszy rzut oka
Spinnery ładowania przy każdej akcji Optymistyczne aktualizacje + SWR
Teksty marketingowe w dashboardzie Czysto funkcjonalny UI
Kluczowy wniosek: Developerzy nie chcą być „zachwyceni". Chcą dostarczać kod.
Biblioteka wzorców
1. Doskonałość trybu ciemnego
Tryb ciemny Vercel to nie przełącznik. To domyślne ustawienie. Design jest chirurgiczny: ostro kontrastowa czerń i biel tworzą maksymalny kontrast.
Filozofia kolorów:
:root {
/* Paleta Vercel jest niezwykle prosta */
/* Tła - czysta czerń, bez szarości */
--bg-000: #000000;
--bg-100: #0A0A0A;
--bg-200: #111111;
/* Pierwszy plan - wysoki kontrast bieli */
--fg-100: #FFFFFF;
--fg-200: #EDEDED;
--fg-300: #A1A1A1;
--fg-400: #888888;
/* Obramowania - subtelne, ale widoczne */
--border-100: #333333;
--border-200: #444444;
/* Semantyczne - status deploymentu */
--color-success: #00DC82; /* Zielony - wdrożony */
--color-error: #FF0000; /* Czerwony - błąd */
--color-warning: #FFAA00; /* Bursztynowy - budowanie */
--color-info: #0070F3; /* Niebieski - w kolejce */
/* Akcent - sygnatura Vercel */
--accent: #FFFFFF; /* Biel jako akcent na czerni */
}
Dlaczego czysta czerń działa: - Maksymalny kontrast dla czytelności tekstu - Estetyka inspirowana terminalem, której developerzy ufają - Zmniejsza zmęczenie oczu w ciemnym otoczeniu - Sprawia, że kolorowe wskaźniki statusu wyróżniają się
2. Wskaźniki statusu w kartach
Vercel odzwierciedla status deploymentu w ikonach kart przeglądarki, czyniąc informacje widocznymi nawet gdy karta nie jest aktywna.
┌─ Pasek kart przeglądarki ──────────────────────────────────────────┐
│ │
│ [▶] acme-web - Budowanie [✓] blog - Gotowy [✕] api - Błąd │
│ │
└────────────────────────────────────────────────────────────────────┘
Stany ikony karty:
⏳ W kolejce (szare kółko)
▶ Budowanie (animowany spinner)
✓ Gotowy (zielony znacznik)
✕ Błąd (czerwony X)
Wzorzec implementacji:
// Dynamiczny favicon na podstawie statusu deploymentu
function updateFavicon(status) {
const link = document.querySelector("link[rel~='icon']");
const icons = {
queued: '/favicon-queued.svg',
building: '/favicon-building.svg', // Animowany
ready: '/favicon-ready.svg',
error: '/favicon-error.svg',
};
link.href = icons[status];
}
// Tytuł również odzwierciedla status
function updateTitle(projectName, status) {
const prefixes = {
queued: '⏳',
building: '▶',
ready: '✓',
error: '✕',
};
document.title = `${prefixes[status]} ${projectName} - Vercel`;
}
Kluczowy wniosek: Developerzy mają otwartych wiele kart. Status widoczny na pasku kart oznacza, że nie muszą przełączać kart, by sprawdzić status budowania.
3. Oś czasu deploymentu
Inspektor deploymentu pokazuje przejrzystą oś czasu procesu wdrożenia.
┌─ Oś czasu deploymentu ─────────────────────────────────────────────┐
│ │
│ [o] W kolejce 12:34:56 PM │
│ │ │
│ [o] Budowanie 12:34:58 PM │
│ │ └─ Instalowanie zależności... 3.2s │
│ │ └─ Budowanie... 12.4s │
│ │ └─ Generowanie statycznych stron... 2.1s │
│ │ │
│ [o] Wdrażanie 12:35:14 PM │
│ │ └─ Przesyłanie artefaktów budowania... │
│ │ │
│ [*] Gotowy 12:35:18 PM │
│ └─ https://acme-abc123.vercel.app │
│ │
│ Łącznie: 22s │
│ │
└────────────────────────────────────────────────────────────────────┘
Kodowanie wizualne:
.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);
}
/* Linia łącząca */
.timeline-step:not(:last-child)::after {
content: '';
position: absolute;
left: 4px;
top: 16px;
width: 2px;
height: calc(100% - 6px);
background: var(--border-100);
}
/* Stany kroków */
.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 przeglądarki logów
Przeglądarka logów Vercel jest zintegrowana z przeglądem deploymentu, nie jest osobną stroną.
┌─ Logi budowania ───────────────────────────────────────────────────┐
│ │
│ Filtr: [Wszystko ▼] [Funkcja: api/hello ▼] [Kopiuj] [↓] │
│ │
├────────────────────────────────────────────────────────────────────┤
│ │
│ 12:34:58.123 info Instalowanie zależności... │
│ 12:35:01.456 info dodano 1234 pakiety w 3.2s │
│ 12:35:01.789 info Uruchamianie budowania... │
│ 12:35:14.012 info ✓ Skompilowano pomyślnie │
│ 12:35:14.234 warn Duży rozmiar bundla: pages/index.js (245kb) │
│ 12:35:14.567 info Generowanie statycznych stron... │
│ 12:35:16.890 info ✓ Wygenerowano 42 strony │
│ │
└────────────────────────────────────────────────────────────────────┘
Kluczowe funkcje: - Kopiowanie do schowka jednym kliknięciem - Filtrowanie po funkcji lub wyjściu budowania - Poziomy logów oznaczone kolorami (info, warn, error) - Znaczniki czasu z precyzją do milisekund - Adresy URL do udostępniania konkretnych linii logów
Implementacja:
.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. Puste stany
Puste stany Vercel są funkcjonalne, nie dekoracyjne. Mówią ci, co zrobić dalej.
┌─ Pusty stan: Brak deploymentów ────────────────────────────────────┐
│ │
│ │
│ Brak deploymentów │
│ │
│ Wypchnij do repozytorium, aby utworzyć │
│ swój pierwszy deployment │
│ │
│ │
│ git push origin main │
│ │
│ │
│ [Zobacz dokumentację] │
│ │
│ │
└────────────────────────────────────────────────────────────────────┘
Zasady projektowania: - Brak dekoracyjnych ilustracji - Jasna akcja (komenda git) - Pomocny link do dokumentacji - Monospace dla komend (łatwe do skopiowania)
System projektowania wizualnego
Typografia (Geist)
Vercel stworzył Geist specjalnie dla doświadczeń developerskich:
:root {
/* Geist Sans - UI i tekst główny */
--font-sans: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;
/* Geist Mono - kod i treści techniczne */
--font-mono: 'Geist Mono', 'SF Mono', monospace;
/* Skala rozmiarów */
--text-xs: 12px;
--text-sm: 13px;
--text-base: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 24px;
/* Wysokości linii */
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* Odstępy między literami */
--tracking-tight: -0.02em;
--tracking-normal: 0;
--tracking-wide: 0.02em;
}
/* Liczby tabelaryczne dla danych */
.tabular-nums {
font-variant-numeric: tabular-nums;
}
/* Lub użyj Geist Mono do porównań */
.data-value {
font-family: var(--font-mono);
}
System odstępów
:root {
/* Jednostka bazowa 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;
}
Zaokrąglenia rogów
:root {
/* Subtelne, spójne promienie */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-full: 9999px;
}
Wzorce animacji
Optymistyczne aktualizacje
Vercel używa optymistycznych aktualizacji UI. Akcje czują się natychmiastowe.
// Wzorzec SWR dla aktualizacji w czasie rzeczywistym
const { data, mutate } = useSWR('/api/deployments');
async function triggerDeploy() {
// Natychmiast pokaż stan „wdrażanie"
mutate(
{ ...data, status: 'building' },
false // Nie rewaliduj jeszcze
);
// Następnie faktycznie uruchom
await fetch('/api/deploy', { method: 'POST' });
// Rewaliduj, aby uzyskać rzeczywisty stan
mutate();
}
Subtelne stany ładowania
/* Ładowanie szkieletowe - bez spinnerów */
.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; }
}
Stany przycisków
.button {
transition: background 100ms ease, transform 100ms ease;
}
.button:hover {
background: var(--fg-100);
}
.button:active {
transform: scale(0.98);
}
/* Bez długich przejść - natychmiastowa informacja zwrotna */
Optymalizacje wydajności (oparte na designie)
Redesign dashboardu Vercel obejmował decyzje projektowe, które poprawiły wydajność:
Użyte techniki: - Preconnecting do API, Assets i Avatar origins - Krytyczne wywołania API otrzymują wyższy priorytet przeglądarki - Memoizacja komponentów React (useMemo, useCallback) - ReactDOM.unstable_batchedUpdates zmniejszył ponowne renderowanie o 20% - SWR dla efektywnych aktualizacji danych w czasie rzeczywistym
Kluczowy wniosek: Wydajność JEST designem. Wolny dashboard z pięknymi animacjami jest gorszy niż szybki dashboard bez nich.
Lekcje dla naszej pracy
1. Tryb ciemny jako domyślny
Gdy twoi użytkownicy pracują w ciemnym otoczeniu (terminale, IDE), tryb ciemny nie jest funkcją—to szacunek.
2. Status w każdym rogu
Ikony kart, tytuły stron, wskaźniki na osi czasu: status powinien być widoczny bez zmiany fokusa.
3. Domyślnie optymistyczny
Pokaż oczekiwany stan natychmiast. Aktualizuj z rzeczywistością w tle.
4. Developerzy nienawidzą czekać
Żadnych spinnerów ładowania, jeśli można tego uniknąć. Stany szkieletowe, optymistyczne aktualizacje, prefetching.
5. Puste stany to instrukcje
Nie pokazuj ładnej ilustracji. Pokaż komendę, którą muszą uruchomić.
Najczęściej zadawane pytania
Dlaczego Vercel używa czystej czerni (#000000) zamiast ciemnej szarości jako tła?
Czysta czerń zapewnia maksymalny kontrast dla białego tekstu, tworząc optymalną czytelność. Pasuje również do estetyki terminali i edytorów kodu, których developerzy już używają, sprawiając, że dashboard czuje się jak natywna część ich przepływu pracy. Ciemnoszare tła często wyglądają „łagodniej", ale zmniejszają kontrast i mogą wyglądać na wyblakłe na wyświetlaczach high-DPI.
Jak działają wskaźniki statusu w kartach Vercel?
Vercel dynamicznie aktualizuje favicon przeglądarki na podstawie statusu deploymentu: spinner dla budowania, zielony znacznik dla gotowy, czerwony X dla błędu. Tytuł strony również aktualizuje się z prefiksami emoji (▶, ✓, ✕). Oznacza to, że developerzy mogą monitorować wiele deploymentów w różnych kartach bez przełączania fokusa—status jest widoczny na pierwszy rzut oka na pasku kart przeglądarki.
Jakie jest podejście Vercel do stanów ładowania?
Vercel unika tradycyjnych spinnerów ładowania na rzecz optymistycznego UI i ekranów szkieletowych. Gdy uruchamiasz deployment, UI natychmiast pokazuje stan „budowanie" zanim serwer potwierdzi. Biblioteka SWR obsługuje rewalidację w tle. Dzięki temu akcje czują się natychmiastowe, nawet gdy żądania sieciowe zajmują 200-500ms.
Czym jest Geist i dlaczego Vercel stworzył własny krój pisma?
Geist to rodzina krojów pisma, którą Vercel zaprojektował specjalnie dla interfejsów developerskich. Obejmuje Geist Sans dla tekstu UI i Geist Mono dla kodu. Design jest zoptymalizowany dla małych rozmiarów (12-14px) powszechnych w dashboardach, zawiera liczby tabelaryczne dla wyrównanych kolumn danych i ma wyraźne kształty znaków, aby zapobiec pomyleniu podobnych glifów (l, 1, I).
Jak Vercel obsługuje puste stany inaczej niż inne produkty?
Puste stany Vercel pokazują wykonalne komendy, nie dekoracyjne ilustracje. Pusta strona deploymentów wyświetla git push origin main w monospace (łatwe do skopiowania) zamiast rysunku z ogólnym przyciskiem „Rozpocznij". Filozofia polega na tym, że developerzy chcą dokładnie wiedzieć, co zrobić, a nie być wizualnie uspokojeni.