Vercel: Developer Experience als Design
Wie Vercel die Entwicklererfahrung zum Produkt machte: Dark-Mode-first Design, Tab-Status-Indikatoren, optimistische UI und funktionale Leerzustände. Mit CSS- und JavaScript-Implementierungsmustern.
Vercel: Developer Experience als Design
„Entwickler sind allergisch gegen schlechte UX – sie wollen kein ‚entzückendes Onboarding', wenn es sie ausbremst."
Vercels Designphilosophie ist kompromisslos entwicklerzentriert. Das Geist-Designsystem priorisiert Klarheit, Geschwindigkeit und Informationsdichte über Dekoration. Jedes Pixel dient dem Workflow des Entwicklers.
Warum Vercel wichtig ist
Vercel beweist, dass Entwicklertools herausragendes Design haben können, ohne „designlastig" zu sein. Das Dashboard ist schnell, informationsdicht und steht nicht im Weg.
Zentrale Errungenschaften: - Entwicklung von Geist, einer Schriftart, die speziell für Entwickler entworfen wurde - Dashboard-Redesign reduzierte First Meaningful Paint um 1,2 Sekunden - Pionierarbeit bei Dark-Mode-First-Design in Entwicklertools - Setzte den Standard für Deployment-UX - Tab-Icons, die den Deployment-Status widerspiegeln (Building, Error, Ready)
Kernerkenntnisse
- Dark Mode ist Respekt, kein Feature - Entwickler arbeiten in Terminals und IDEs mit dunklen Hintergründen; ein weißes Dashboard erzeugt störende Kontextwechsel und Augenbelastung
- Status gehört überall hin, wo man ihn sehen kann - Tab-Favicons, Seitentitel, Timeline-Punkte: Der Deployment-Status sollte sichtbar sein, ohne den Fokus zu wechseln oder Tabs zu öffnen
- Optimistisches UI eliminiert wahrgenommene Latenz - Zeige den erwarteten Zustand sofort, synchronisiere im Hintergrund mit der Realität; Entwickler bemerken 300ms Verzögerungen
- Leere Zustände sind Anleitungen, keine Illustrationen - Zeige den exakten auszuführenden Befehl (
git push origin main), keine dekorative Grafik mit „Los geht's"-Button - Performance ist Design - Vercels Dashboard-Redesign reduzierte First Meaningful Paint um 1,2 Sekunden; keine noch so schönen Animationen kompensieren langsame Ladezeiten
Zentrale Designphilosophie
Das entwicklerzentrierte Prinzip
Entwickler beurteilen Produkte danach, wie wenig sie sie ausbremsen. Vercels Design spiegelt dies wider:
ANTI-PATTERNS (Was Entwickler hassen) VERCELS ANSATZ
───────────────────────────────────────────────────────────────────
„Entzückende" Animationen mit Verzögerung Sofortige, übergangslose Zustände
Onboarding-Wizards, die Arbeit blockieren CLI-first, Dashboard optional
Dichte Dokumentation in Tabs versteckt Informationen auf einen Blick sichtbar
Ladeanzeigen bei jeder Aktion Optimistische Updates + SWR
Marketing-Texte im Dashboard Rein funktionales UI
Zentrale Erkenntnis: Entwickler wollen nicht „entzückt" werden. Sie wollen deployen.
Pattern-Bibliothek
1. Dark Mode Exzellenz
Vercels Dark Mode ist kein Toggle. Er ist der Standard. Das Design ist chirurgisch präzise: starkes Schwarz-Weiß erzeugt maximalen Kontrast.
Farbphilosophie:
:root {
/* Die Vercel-Palette ist bemerkenswert einfach */
/* Hintergründe - reines Schwarz, kein Grau */
--bg-000: #000000;
--bg-100: #0A0A0A;
--bg-200: #111111;
/* Vordergrund - hoher Kontrast Weiß */
--fg-100: #FFFFFF;
--fg-200: #EDEDED;
--fg-300: #A1A1A1;
--fg-400: #888888;
/* Rahmen - subtil aber sichtbar */
--border-100: #333333;
--border-200: #444444;
/* Semantisch - Deployment-Status */
--color-success: #00DC82; /* Grün - deployed */
--color-error: #FF0000; /* Rot - fehlgeschlagen */
--color-warning: #FFAA00; /* Amber - building */
--color-info: #0070F3; /* Blau - in Warteschlange */
/* Der Akzent - Vercels Markenzeichen */
--accent: #FFFFFF; /* Weiß als Akzent auf Schwarz */
}
Warum reines Schwarz funktioniert: - Maximaler Kontrast für Textlesbarkeit - Terminal-inspirierte Ästhetik, der Entwickler vertrauen - Reduziert Augenbelastung in dunklen Umgebungen - Lässt farbige Statusanzeigen hervorstechen
2. Tab-Statusanzeigen
Vercel spiegelt den Deployment-Status in Browser-Tab-Icons wider, sodass Informationen auch sichtbar sind, wenn der Tab nicht fokussiert ist.
┌─ Browser Tab-Leiste ───────────────────────────────────────────────┐
│ │
│ [▶] acme-web - Building [✓] blog - Ready [✕] api - Error │
│ │
└────────────────────────────────────────────────────────────────────┘
Tab-Icon-Zustände:
⏳ In Warteschlange (grauer Kreis)
▶ Building (animierter Spinner)
✓ Ready (grünes Häkchen)
✕ Error (rotes X)
Implementierungsmuster:
// Dynamisches Favicon basierend auf Deployment-Status
function updateFavicon(status) {
const link = document.querySelector("link[rel~='icon']");
const icons = {
queued: '/favicon-queued.svg',
building: '/favicon-building.svg', // Animiert
ready: '/favicon-ready.svg',
error: '/favicon-error.svg',
};
link.href = icons[status];
}
// Titel spiegelt ebenfalls den Status wider
function updateTitle(projectName, status) {
const prefixes = {
queued: '⏳',
building: '▶',
ready: '✓',
error: '✕',
};
document.title = `${prefixes[status]} ${projectName} - Vercel`;
}
Zentrale Erkenntnis: Entwickler haben viele Tabs offen. Status, der in der Tab-Leiste sichtbar ist, bedeutet, dass sie nicht die Tabs wechseln müssen, um den Build-Status zu prüfen.
3. Deployment-Timeline
Der Deployment-Inspector zeigt eine klare Timeline des Deployment-Prozesses.
┌─ Deployment-Timeline ──────────────────────────────────────────────┐
│ │
│ [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 │
│ │
│ Gesamt: 22s │
│ │
└────────────────────────────────────────────────────────────────────┘
Visuelle Kodierung:
.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);
}
/* Verbindungslinie */
.timeline-step:not(:last-child)::after {
content: '';
position: absolute;
left: 4px;
top: 16px;
width: 2px;
height: calc(100% - 6px);
background: var(--border-100);
}
/* Schritt-Zustände */
.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. Log-Viewer-Design
Vercels Log-Viewer ist in die Deployment-Übersicht integriert, nicht auf einer separaten Seite.
┌─ Build Logs ───────────────────────────────────────────────────────┐
│ │
│ Filter: [Alle ▼] [Function: api/hello ▼] [Kopieren] [↓] │
│ │
├────────────────────────────────────────────────────────────────────┤
│ │
│ 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 │
│ │
└────────────────────────────────────────────────────────────────────┘
Hauptmerkmale: - Ein-Klick-Kopieren in die Zwischenablage - Filterung nach Funktion oder Build-Ausgabe - Farbcodierte Log-Level (info, warn, error) - Zeitstempel mit Millisekunden-Präzision - Teilbare URLs für bestimmte Log-Zeilen
Implementierung:
.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. Leere Zustände
Vercels leere Zustände sind funktional, nicht dekorativ. Sie zeigen dir, was als Nächstes zu tun ist.
┌─ Leerer Zustand: Keine Deployments ────────────────────────────────┐
│ │
│ │
│ Noch keine Deployments │
│ │
│ Pushe zu deinem Repository, um dein │
│ erstes Deployment zu erstellen │
│ │
│ │
│ git push origin main │
│ │
│ │
│ [Dokumentation ansehen] │
│ │
│ │
└────────────────────────────────────────────────────────────────────┘
Design-Prinzipien: - Keine dekorativen Illustrationen - Klare Handlungsaufforderung (der git-Befehl) - Hilfreicher Link zur Dokumentation - Monospace für Befehle (kopierfreundlich)
Visuelles Design-System
Typografie (Geist)
Vercel hat Geist speziell für Developer-Experiences entwickelt:
:root {
/* Geist Sans - UI und Fließtext */
--font-sans: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;
/* Geist Mono - Code und technische Inhalte */
--font-mono: 'Geist Mono', 'SF Mono', monospace;
/* Größenskala */
--text-xs: 12px;
--text-sm: 13px;
--text-base: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 24px;
/* Zeilenhöhen */
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* Zeichenabstand */
--tracking-tight: -0.02em;
--tracking-normal: 0;
--tracking-wide: 0.02em;
}
/* Tabellarische Zahlen für Daten */
.tabular-nums {
font-variant-numeric: tabular-nums;
}
/* Oder Geist Mono für Vergleiche verwenden */
.data-value {
font-family: var(--font-mono);
}
Abstands-System
:root {
/* 4px Basiseinheit */
--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 {
/* Subtile, konsistente Radien */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-full: 9999px;
}
Animationsmuster
Optimistische Updates
Vercel verwendet optimistische UI-Updates. Aktionen fühlen sich sofort an.
// SWR-Pattern für Echtzeit-Updates
const { data, mutate } = useSWR('/api/deployments');
async function triggerDeploy() {
// Zeige sofort den "deploying"-Status
mutate(
{ ...data, status: 'building' },
false // Noch nicht revalidieren
);
// Dann tatsächlich auslösen
await fetch('/api/deploy', { method: 'POST' });
// Revalidieren, um echten Status zu erhalten
mutate();
}
Subtile Ladezustände
/* Skeleton-Loading - keine Spinner */
.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; }
}
Button-Zustände
.button {
transition: background 100ms ease, transform 100ms ease;
}
.button:hover {
background: var(--fg-100);
}
.button:active {
transform: scale(0.98);
}
/* Keine langen Übergänge - sofortiges Feedback */
Performance-Optimierungen (Design-informiert)
Vercels Dashboard-Redesign beinhaltete Design-Entscheidungen, die die Performance verbesserten:
Verwendete Techniken: - Preconnecting zu API-, Assets- und Avatar-Origins - Kritische API-Aufrufe erhalten höhere Browser-Priorität - Memoizing von React-Komponenten (useMemo, useCallback) - ReactDOM.unstable_batchedUpdates reduzierte Re-Renders um 20% - SWR für effiziente Echtzeit-Datenaktualisierungen
Zentrale Erkenntnis: Performance IST Design. Ein langsames Dashboard mit schönen Animationen ist schlechter als ein schnelles Dashboard ohne jegliche Animationen.
Erkenntnisse für unsere Arbeit
1. Dark Mode als Standard
Wenn deine Nutzer in dunklen Umgebungen arbeiten (Terminals, IDEs), ist Dark Mode kein Feature – es ist Respekt.
2. Status in jeder Ecke
Tab-Icons, Seitentitel, Timeline-Indikatoren: Status sollte ohne Fokus sichtbar sein.
3. Standardmäßig optimistisch
Zeige den erwarteten Zustand sofort. Aktualisiere im Hintergrund mit der Realität.
4. Entwickler hassen Warten
Keine Lade-Spinner, wenn du sie vermeiden kannst. Skeleton-Zustände, optimistische Updates, Prefetching.
5. Leerzustände sind Anleitungen
Zeige keine hübsche Illustration. Zeige den Befehl, den sie ausführen müssen.
Häufig gestellte Fragen
Warum verwendet Vercel reines Schwarz (#000000) statt Dunkelgrau für Hintergründe?
Reines Schwarz bietet maximalen Kontrast für weißen Text und schafft optimale Lesbarkeit. Es entspricht auch der Ästhetik von Terminals und Code-Editoren, die Entwickler bereits verwenden, wodurch sich das Dashboard wie ein nativer Teil ihres Workflows anfühlt. Dunkelgraue Hintergründe wirken oft „weicher", reduzieren aber den Kontrast und können auf High-DPI-Displays ausgewaschen erscheinen.
Wie funktionieren Vercels Tab-Status-Indikatoren?
Vercel aktualisiert das Browser-Favicon dynamisch basierend auf dem Deployment-Status: ein Spinner für Building, grünes Häkchen für Ready, rotes X für Error. Der Seitentitel wird ebenfalls mit Emoji-Präfixen aktualisiert (▶, ✓, ✕). Das bedeutet, Entwickler können mehrere Deployments über Tabs hinweg überwachen, ohne den Fokus zu wechseln – der Status ist auf einen Blick in der Browser-Tab-Leiste sichtbar.
Was ist Vercels Ansatz bei Ladezuständen?
Vercel vermeidet traditionelle Lade-Spinner zugunsten von optimistischer UI und Skeleton-Screens. Wenn du ein Deployment auslöst, zeigt die UI sofort den „building"-Status, bevor der Server bestätigt. Die SWR-Library übernimmt die Hintergrund-Revalidierung. Das lässt Aktionen sofort wirken, selbst wenn Netzwerkanfragen 200-500ms dauern.
Was ist Geist und warum hat Vercel eine eigene Schriftart erstellt?
Geist ist eine Schriftfamilie, die Vercel speziell für Entwickler-Interfaces entworfen hat. Sie umfasst Geist Sans für UI-Text und Geist Mono für Code. Das Design optimiert für kleine Größen (12-14px), die in Dashboards üblich sind, enthält tabellarische Zahlen für ausgerichtete Datenspalten und hat unterscheidbare Zeichenformen, um Verwechslungen zwischen ähnlichen Glyphen zu verhindern (l, 1, I).
Wie geht Vercel mit Leerzuständen anders um als andere Produkte?
Vercels Leerzustände zeigen ausführbare Befehle, keine dekorativen Illustrationen. Eine leere Deployments-Seite zeigt git push origin main in Monospace (was das Kopieren erleichtert) anstelle eines Cartoons mit einem generischen „Get started"-Button. Die Philosophie ist, dass Entwickler genau wissen wollen, was zu tun ist, nicht visuell beruhigt werden.