Last active
March 29, 2026 21:07
-
-
Save lassebenni/a2c1ff7f085d83668f937294a3a18fd5 to your computer and use it in GitHub Desktop.
Evolution: Physical Servers → VMs → Serverless (CSS animation)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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