feat(projects): add playground architecture diagram and notes

Update the Playground entry on the projects page: diagram,
prerender, privacy and operations bullets, one challenge,
one learning, and the Traefik, nginx and Tailscale technologies.
This commit is contained in:
lobo committed 2026-10-21 08:04:25 +02:00
1 parent e13db8c1de
commit 910822028b
5 files changed
+119 -9

No files matched your search

@@ -0,0 +1,99 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630" role="img" aria-labelledby="title desc">
<title id="title">Playground</title>
<desc id="desc">Architecture of this site: a push to Gitea on the home server runs lint, i18n check, unit tests, a production build with prerendering, a prerender check and Lighthouse, then builds a Docker image into the registry. Watchtower on the Hostinger VPS pulls it over Tailscale, Traefik terminates HTTPS and nginx serves the prerendered HTML. Traefik also forwards git.andreas-dahm.eu to Gitea over Tailscale. The browser gets prerendered HTML first, then Angular and the service worker take over; the WebGPU and WebGL demos run on the client.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1e2530"/>
<stop offset="100%" stop-color="#15181d"/>
</linearGradient>
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#26c6da"/>
<stop offset="100%" stop-color="#ffa726"/>
</linearGradient>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4a5563"/>
</marker>
<marker id="arrowCyan" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#26c6da"/>
</marker>
</defs>
<style>
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; }
.sans { font-family: Roboto, Arial, sans-serif; }
.lbl { fill: #8b97a6; font-size: 17px; letter-spacing: .04em; }
.chip { fill: #cdd6e0; font-size: 19px; }
.cap { fill: #6c7887; font-size: 15px; letter-spacing: .18em; }
.name { fill: #cdd6e0; font-size: 22px; font-weight: 600; }
.sub { fill: #8b97a6; font-size: 16px; }
.arr { fill: #8b97a6; font-size: 15px; }
</style>
<rect width="1200" height="630" fill="url(#bg)"/>
<rect x="0" y="0" width="1200" height="4" fill="url(#accent)"/>
<text x="64" y="72" class="mono" fill="#26c6da" font-size="26" font-weight="600">Playground</text>
<text x="64" y="102" class="sans lbl">push to main, prerender at build time, serve static</text>
<rect x="120" y="140" width="320" height="390" rx="18" fill="#1a222c" stroke="#26c6da" stroke-width="2"/>
<text x="144" y="168" class="sans cap" text-anchor="start">HOME SERVER "TRIBBLE"</text>
<rect x="144" y="186" width="272" height="98" rx="10" fill="#212a35" stroke="#2f3a47"/>
<text x="164" y="220" class="sans name">Gitea</text>
<text x="164" y="246" class="sans sub">git, Actions runner, registry</text>
<text x="164" y="268" class="sans sub">git.andreas-dahm.eu</text>
<text x="144" y="316" class="sans cap" text-anchor="start">ACTIONS RUNNER</text>
<rect x="144" y="328" width="130" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="209" y="353" class="sans chip" style="font-size:15px" text-anchor="middle">lint</text>
<rect x="286" y="328" width="130" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="351" y="353" class="sans chip" style="font-size:15px" text-anchor="middle">i18n check</text>
<rect x="144" y="376" width="130" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="209" y="401" class="sans chip" style="font-size:15px" text-anchor="middle">unit tests</text>
<rect x="286" y="376" width="130" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="351" y="401" class="sans chip" style="font-size:15px" text-anchor="middle">build + prerender</text>
<rect x="144" y="424" width="130" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="209" y="449" class="sans chip" style="font-size:15px" text-anchor="middle">prerender check</text>
<rect x="286" y="424" width="130" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="351" y="449" class="sans chip" style="font-size:15px" text-anchor="middle">Lighthouse</text>
<rect x="144" y="476" width="272" height="40" rx="10" fill="#243040" stroke="#33475c"/>
<text x="280" y="501" class="mono chip" style="font-size:17px" text-anchor="middle">Docker image → registry</text>
<rect x="556" y="140" width="320" height="390" rx="18" fill="#1a222c" stroke="#ffa726" stroke-width="2"/>
<text x="580" y="168" class="sans cap" text-anchor="start">HOSTINGER VPS</text>
<rect x="580" y="186" width="272" height="98" rx="10" fill="#2a2118" stroke="#5c4326"/>
<text x="600" y="220" class="sans name">Traefik</text>
<text x="600" y="246" class="sans sub">HTTPS, Let's Encrypt</text>
<text x="600" y="268" class="sans sub">andreas-dahm.eu</text>
<rect x="580" y="300" width="272" height="98" rx="10" fill="#212a35" stroke="#2f3a47"/>
<text x="600" y="334" class="sans name">nginx</text>
<text x="600" y="360" class="sans sub">prerendered HTML, gzip</text>
<text x="600" y="382" class="sans sub">no access log</text>
<rect x="580" y="440" width="272" height="76" rx="10" fill="#243040" stroke="#33475c"/>
<text x="600" y="474" class="sans name">Watchtower</text>
<text x="600" y="500" class="sans sub">pulls the new image</text>
<path d="M 716 284 V 292" stroke="#4a5563" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<path d="M 716 440 V 406" stroke="#4a5563" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<text x="730" y="424" class="sans arr" text-anchor="start">deploy</text>
<rect x="936" y="140" width="216" height="390" rx="18" fill="#1a222c" stroke="#2f3a47" stroke-width="2"/>
<text x="960" y="168" class="sans cap" text-anchor="start">BROWSER</text>
<rect x="952" y="186" width="184" height="76" rx="10" fill="#212a35" stroke="#2f3a47"/>
<text x="972" y="220" class="sans name" style="font-size:17px">Prerendered HTML</text>
<text x="972" y="246" class="sans sub">title + meta per route</text>
<rect x="952" y="300" width="184" height="76" rx="10" fill="#212a35" stroke="#2f3a47"/>
<text x="972" y="334" class="sans name" style="font-size:17px">Angular + PWA</text>
<text x="972" y="360" class="sans sub">service worker, offline</text>
<rect x="952" y="414" width="184" height="76" rx="10" fill="#212a35" stroke="#2f3a47"/>
<text x="972" y="448" class="sans name" style="font-size:17px">WebGPU / WebGL</text>
<text x="972" y="474" class="sans sub">demos on the client</text>
<path d="M 1044 262 V 292" stroke="#4a5563" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<path d="M 1044 376 V 406" stroke="#4a5563" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<path d="M 40 235 H 112" stroke="#26c6da" stroke-width="2" fill="none" marker-end="url(#arrowCyan)"/>
<text x="44" y="224" class="mono arr" text-anchor="start">git push</text>
<path d="M 548 224 H 448" stroke="#4a5563" stroke-width="2" fill="none" marker-end="url(#arrow)"/>
<text x="498" y="212" class="sans arr" text-anchor="middle">via Tailscale</text>
<path d="M 424 496 H 548" stroke="#26c6da" stroke-width="2" fill="none" marker-end="url(#arrowCyan)"/>
<text x="486" y="466" class="sans arr" text-anchor="middle">new image</text>
<text x="486" y="484" class="sans arr" text-anchor="middle">via Tailscale</text>
<path d="M 884 224 H 928" stroke="#4a5563" stroke-width="2" fill="none" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
<text x="906" y="212" class="sans arr" text-anchor="middle">HTTPS</text>
<line x1="64" y1="566" x2="1136" y2="566" stroke="#2a333e"/>
<text x="64" y="598" class="mono" fill="#5b6673" font-size="15">angular · prerender · nginx · traefik · gitea actions · docker</text>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB