Skip to content

Instantly share code, notes, and snippets.

@lassebenni
Last active March 29, 2026 21:07
Show Gist options
  • Select an option

  • Save lassebenni/a2c1ff7f085d83668f937294a3a18fd5 to your computer and use it in GitHub Desktop.

Select an option

Save lassebenni/a2c1ff7f085d83668f937294a3a18fd5 to your computer and use it in GitHub Desktop.
Evolution: Physical Servers → VMs → Serverless (CSS animation)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Evolution: Bare Metal → VMs → Containers → Serverless</title>
<style>
body {
margin: 0;
padding: 20px;
background: #1a1a2e;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.scene {
width: 720px;
max-width: 100%;
position: relative;
}
svg {
max-width: 100%;
height: auto;
}
/* 16s total cycle, 4 phases of ~4s each */
/* Phase 1: Bare metal (0-4s = 0%-25%) */
.phase1 {
opacity: 0;
animation: showP1 16s infinite;
}
@keyframes showP1 {
0% { opacity: 0; }
2% { opacity: 1; }
22% { opacity: 1; }
26% { opacity: 0; }
100% { opacity: 0; }
}
/* Phase 2: VMs (4-8s = 25%-50%) */
.phase2 {
opacity: 0;
animation: showP2 16s infinite;
}
@keyframes showP2 {
0% { opacity: 0; }
26% { opacity: 0; }
30% { opacity: 1; }
47% { opacity: 1; }
51% { opacity: 0; }
100% { opacity: 0; }
}
/* Phase 3: Containers on a VM (8-12s = 50%-75%) */
.phase3 {
opacity: 0;
animation: showP3 16s infinite;
}
@keyframes showP3 {
0% { opacity: 0; }
51% { opacity: 0; }
55% { opacity: 1; }
72% { opacity: 1; }
76% { opacity: 0; }
100% { opacity: 0; }
}
/* Phase 4: Serverless (12-16s = 75%-100%) */
.phase4 {
opacity: 0;
animation: showP4 16s infinite;
}
@keyframes showP4 {
0% { opacity: 0; }
76% { opacity: 0; }
80% { opacity: 1; }
96% { opacity: 1; }
100% { opacity: 0; }
}
/* Serverless container appear/run/disappear pulses */
.container-pulse.c1 { opacity: 0; animation: cLife1 16s infinite; }
.container-pulse.c2 { opacity: 0; animation: cLife2 16s infinite; }
.container-pulse.c3 { opacity: 0; animation: cLife3 16s infinite; }
@keyframes cLife1 {
0%, 80% { opacity: 0; transform: scale(0.8); }
83% { opacity: 1; transform: scale(1); }
88% { opacity: 1; transform: scale(1); }
91% { opacity: 0; transform: scale(0.8); }
100% { opacity: 0; }
}
@keyframes cLife2 {
0%, 85% { opacity: 0; transform: scale(0.8); }
87% { opacity: 1; transform: scale(1); }
92% { opacity: 1; transform: scale(1); }
94% { opacity: 0; transform: scale(0.8); }
100% { opacity: 0; }
}
@keyframes cLife3 {
0%, 89% { opacity: 0; transform: scale(0.8); }
91% { opacity: 1; transform: scale(1); }
95% { opacity: 1; transform: scale(1); }
97% { opacity: 0; transform: scale(0.8); }
100% { opacity: 0; }
}
/* Phase indicator dots */
.dot { fill: #333; }
.dot.d1 { animation: dA1 16s infinite; }
.dot.d2 { animation: dA2 16s infinite; }
.dot.d3 { animation: dA3 16s infinite; }
.dot.d4 { animation: dA4 16s infinite; }
@keyframes dA1 {
0%, 2% { fill: #64b5f6; } 22% { fill: #64b5f6; } 26% { fill: #333; } 100% { fill: #333; }
}
@keyframes dA2 {
0%, 28% { fill: #333; } 30% { fill: #ab47bc; } 47% { fill: #ab47bc; } 51% { fill: #333; } 100% { fill: #333; }
}
@keyframes dA3 {
0%, 53% { fill: #333; } 55% { fill: #ffb74d; } 72% { fill: #ffb74d; } 76% { fill: #333; } 100% { fill: #333; }
}
@keyframes dA4 {
0%, 78% { fill: #333; } 80% { fill: #66bb6a; } 96% { fill: #66bb6a; } 100% { fill: #333; }
}
</style>
</head>
<body>
<div class="scene">
<svg viewBox="0 0 720 420" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif">
<!-- Background -->
<rect width="720" height="420" rx="12" fill="#1a1a2e"/>
<!-- Main title -->
<text x="360" y="32" text-anchor="middle" fill="#e0e0e0" font-size="17" font-weight="bold">The Evolution of Running Code</text>
<!-- Phase indicator dots -->
<circle class="dot d1" cx="330" cy="50" r="5"/>
<circle class="dot d2" cx="350" cy="50" r="5"/>
<circle class="dot d3" cx="370" cy="50" r="5"/>
<circle class="dot d4" cx="390" cy="50" r="5"/>
<!-- ==================== PHASE 1: Bare Metal ==================== -->
<g class="phase1">
<text x="360" y="80" text-anchor="middle" fill="#64b5f6" font-size="15" font-weight="bold">1. Bare Metal</text>
<text x="360" y="100" text-anchor="middle" fill="#888" font-size="11">You own or rent an entire physical machine</text>
<!-- Datacenter rack -->
<rect x="220" y="130" width="280" height="220" rx="8" fill="#0d47a1" opacity="0.1" stroke="#42a5f5" stroke-width="1.5"/>
<text x="230" y="148" fill="#42a5f5" font-size="10" opacity="0.6">DATACENTER RACK</text>
<!-- Single physical server -->
<rect x="250" y="165" width="220" height="150" rx="6" fill="#1565c0" opacity="0.2" stroke="#64b5f6" stroke-width="2"/>
<text x="360" y="190" text-anchor="middle" fill="#64b5f6" font-size="13" font-weight="bold">Your Physical Server</text>
<!-- Your code block -->
<rect x="290" y="210" width="140" height="50" rx="4" fill="#263238" stroke="#81c784" stroke-width="1.5"/>
<text x="360" y="233" text-anchor="middle" fill="#81c784" font-size="12" font-weight="bold">Your Code</text>
<text x="360" y="250" text-anchor="middle" fill="#81c784" font-size="10" opacity="0.7">pipeline.py</text>
<!-- Wasted space -->
<rect x="290" y="270" width="140" height="30" rx="3" fill="transparent" stroke="#555" stroke-width="1" stroke-dasharray="4,3"/>
<text x="360" y="290" text-anchor="middle" fill="#555" font-size="10">unused capacity</text>
<!-- Cost note -->
<text x="360" y="378" text-anchor="middle" fill="#ef5350" font-size="11">Pay 24/7, even when idle</text>
<text x="360" y="395" text-anchor="middle" fill="#888" font-size="10">You manage everything: hardware, OS, patches, networking</text>
</g>
<!-- ==================== PHASE 2: Virtual Machines ==================== -->
<g class="phase2">
<text x="360" y="80" text-anchor="middle" fill="#ab47bc" font-size="15" font-weight="bold">2. Virtual Machines</text>
<text x="360" y="100" text-anchor="middle" fill="#888" font-size="11">Multiple OS instances on one physical machine (or rent a cloud VM)</text>
<!-- Physical server outline -->
<rect x="120" y="130" width="480" height="220" rx="8" fill="#4a148c" opacity="0.08" stroke="#7e57c2" stroke-width="1" stroke-dasharray="6,3"/>
<text x="130" y="148" fill="#7e57c2" font-size="10" opacity="0.6">PHYSICAL SERVER (shared)</text>
<!-- VM 1 -->
<rect x="145" y="165" width="130" height="150" rx="6" fill="#4a148c" opacity="0.15" stroke="#ab47bc" stroke-width="1.5"/>
<text x="210" y="185" text-anchor="middle" fill="#ab47bc" font-size="11" font-weight="bold">VM 1</text>
<rect x="162" y="200" width="96" height="40" rx="3" fill="#263238" stroke="#81c784" stroke-width="1"/>
<text x="210" y="220" text-anchor="middle" fill="#81c784" font-size="10" font-weight="bold">Your Code</text>
<text x="210" y="255" text-anchor="middle" fill="#ab47bc" font-size="9">Full OS + runtime</text>
<rect x="162" y="265" width="96" height="24" rx="3" fill="transparent" stroke="#555" stroke-width="1" stroke-dasharray="3,3"/>
<text x="210" y="281" text-anchor="middle" fill="#555" font-size="9">unused</text>
<!-- VM 2 -->
<rect x="295" y="165" width="130" height="150" rx="6" fill="#4a148c" opacity="0.15" stroke="#ab47bc" stroke-width="1.5"/>
<text x="360" y="185" text-anchor="middle" fill="#ab47bc" font-size="11" font-weight="bold">VM 2</text>
<rect x="312" y="200" width="96" height="40" rx="3" fill="#263238" stroke="#ffb74d" stroke-width="1"/>
<text x="360" y="220" text-anchor="middle" fill="#ffb74d" font-size="10" font-weight="bold">Other App</text>
<text x="360" y="255" text-anchor="middle" fill="#ab47bc" font-size="9">Full OS + runtime</text>
<rect x="312" y="265" width="96" height="24" rx="3" fill="transparent" stroke="#555" stroke-width="1" stroke-dasharray="3,3"/>
<text x="360" y="281" text-anchor="middle" fill="#555" font-size="9">unused</text>
<!-- VM 3 -->
<rect x="445" y="165" width="130" height="150" rx="6" fill="#4a148c" opacity="0.15" stroke="#ab47bc" stroke-width="1.5"/>
<text x="510" y="185" text-anchor="middle" fill="#ab47bc" font-size="11" font-weight="bold">VM 3</text>
<rect x="462" y="200" width="96" height="40" rx="3" fill="#263238" stroke="#4fc3f7" stroke-width="1"/>
<text x="510" y="220" text-anchor="middle" fill="#4fc3f7" font-size="10" font-weight="bold">Other App</text>
<text x="510" y="255" text-anchor="middle" fill="#ab47bc" font-size="9">Full OS + runtime</text>
<rect x="462" y="265" width="96" height="24" rx="3" fill="transparent" stroke="#555" stroke-width="1" stroke-dasharray="3,3"/>
<text x="510" y="281" text-anchor="middle" fill="#555" font-size="9">unused</text>
<!-- Cost note -->
<text x="360" y="378" text-anchor="middle" fill="#ef5350" font-size="11">Pay per VM, still idle most of the time</text>
<text x="360" y="395" text-anchor="middle" fill="#888" font-size="10">You manage the OS, patches, and scaling per VM</text>
</g>
<!-- ==================== PHASE 3: Containers on a VM ==================== -->
<g class="phase3">
<text x="360" y="80" text-anchor="middle" fill="#ffb74d" font-size="15" font-weight="bold">3. Containers (Docker)</text>
<text x="360" y="100" text-anchor="middle" fill="#888" font-size="11">Lightweight isolation: many containers share one OS on a VM</text>
<!-- VM outline -->
<rect x="120" y="130" width="480" height="220" rx="8" fill="#e65100" opacity="0.06" stroke="#ffb74d" stroke-width="1.5"/>
<text x="130" y="148" fill="#ffb74d" font-size="10" opacity="0.6">YOUR VM</text>
<!-- Shared OS layer -->
<rect x="140" y="310" width="440" height="28" rx="4" fill="#e65100" opacity="0.12" stroke="#ffb74d" stroke-width="1" stroke-dasharray="4,3"/>
<text x="360" y="328" text-anchor="middle" fill="#ffb74d" font-size="10">Shared OS kernel + Docker engine</text>
<!-- Container 1 -->
<rect x="155" y="165" width="120" height="130" rx="6" fill="#263238" stroke="#81c784" stroke-width="1.5"/>
<text x="215" y="185" text-anchor="middle" fill="#81c784" font-size="11" font-weight="bold">Container 1</text>
<rect x="168" y="198" width="94" height="36" rx="3" fill="#1b5e20" opacity="0.2" stroke="#81c784" stroke-width="1"/>
<text x="215" y="220" text-anchor="middle" fill="#81c784" font-size="10">Your pipeline</text>
<text x="215" y="258" text-anchor="middle" fill="#81c784" font-size="9" opacity="0.7">deps only</text>
<!-- Container 2 -->
<rect x="300" y="165" width="120" height="130" rx="6" fill="#263238" stroke="#4fc3f7" stroke-width="1.5"/>
<text x="360" y="185" text-anchor="middle" fill="#4fc3f7" font-size="11" font-weight="bold">Container 2</text>
<rect x="313" y="198" width="94" height="36" rx="3" fill="#0d47a1" opacity="0.2" stroke="#4fc3f7" stroke-width="1"/>
<text x="360" y="220" text-anchor="middle" fill="#4fc3f7" font-size="10">Web API</text>
<text x="360" y="258" text-anchor="middle" fill="#4fc3f7" font-size="9" opacity="0.7">deps only</text>
<!-- Container 3 -->
<rect x="445" y="165" width="120" height="130" rx="6" fill="#263238" stroke="#ce93d8" stroke-width="1.5"/>
<text x="505" y="185" text-anchor="middle" fill="#ce93d8" font-size="11" font-weight="bold">Container 3</text>
<rect x="458" y="198" width="94" height="36" rx="3" fill="#4a148c" opacity="0.2" stroke="#ce93d8" stroke-width="1"/>
<text x="505" y="220" text-anchor="middle" fill="#ce93d8" font-size="10">Database</text>
<text x="505" y="258" text-anchor="middle" fill="#ce93d8" font-size="9" opacity="0.7">deps only</text>
<!-- Cost note -->
<text x="360" y="378" text-anchor="middle" fill="#ef5350" font-size="11">Pay for the VM, but use it more efficiently</text>
<text x="360" y="395" text-anchor="middle" fill="#888" font-size="10">You still manage the VM, Docker, and scheduling</text>
</g>
<!-- ==================== PHASE 4: Serverless ==================== -->
<g class="phase4">
<text x="360" y="80" text-anchor="middle" fill="#66bb6a" font-size="15" font-weight="bold">4. Serverless</text>
<text x="360" y="100" text-anchor="middle" fill="#888" font-size="11">Upload code or an image, the platform handles everything else</text>
<!-- Cloud platform (dotted, abstract) -->
<rect x="120" y="130" width="480" height="220" rx="8" fill="#1b5e20" opacity="0.06" stroke="#66bb6a" stroke-width="1" stroke-dasharray="6,3"/>
<text x="130" y="148" fill="#66bb6a" font-size="10" opacity="0.6">CLOUD PLATFORM (managed)</text>
<!-- Dotted VM outlines (infrastructure exists but hidden) -->
<rect x="160" y="170" width="120" height="80" rx="6" fill="transparent" stroke="#444" stroke-width="1" stroke-dasharray="4,4"/>
<rect x="300" y="170" width="120" height="80" rx="6" fill="transparent" stroke="#444" stroke-width="1" stroke-dasharray="4,4"/>
<rect x="440" y="170" width="120" height="80" rx="6" fill="transparent" stroke="#444" stroke-width="1" stroke-dasharray="4,4"/>
<text x="360" y="275" text-anchor="middle" fill="#555" font-size="10">infrastructure exists, but the provider manages it</text>
<!-- Container 1: appears, runs, disappears -->
<g class="container-pulse c1">
<rect x="175" y="185" width="90" height="45" rx="4" fill="#263238" stroke="#81c784" stroke-width="2"/>
<text x="220" y="206" text-anchor="middle" fill="#81c784" font-size="10" font-weight="bold">Container</text>
<text x="220" y="221" text-anchor="middle" fill="#81c784" font-size="9">run → exit</text>
</g>
<!-- Container 2 -->
<g class="container-pulse c2">
<rect x="315" y="185" width="90" height="45" rx="4" fill="#263238" stroke="#ffb74d" stroke-width="2"/>
<text x="360" y="206" text-anchor="middle" fill="#ffb74d" font-size="10" font-weight="bold">Function</text>
<text x="360" y="221" text-anchor="middle" fill="#ffb74d" font-size="9">run → exit</text>
</g>
<!-- Container 3 -->
<g class="container-pulse c3">
<rect x="455" y="185" width="90" height="45" rx="4" fill="#263238" stroke="#4fc3f7" stroke-width="2"/>
<text x="500" y="206" text-anchor="middle" fill="#4fc3f7" font-size="10" font-weight="bold">Container</text>
<text x="500" y="221" text-anchor="middle" fill="#4fc3f7" font-size="9">run → exit</text>
</g>
<!-- Label -->
<text x="360" y="305" text-anchor="middle" fill="#66bb6a" font-size="11">Containers and functions spin up on demand, then disappear</text>
<!-- Cost note -->
<text x="360" y="378" text-anchor="middle" fill="#66bb6a" font-size="11">Pay only for the seconds your code runs</text>
<text x="360" y="395" text-anchor="middle" fill="#888" font-size="10">No OS patches, no idle VMs, no capacity planning</text>
</g>
</svg>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment