projects: cover art on every case study
Six generated covers wired in via an optional cover key - 2528x1696 sources optimised to 1600px webp, 49-144KB each. They sit on the page background rather than the diagrams' light card, since the art is already generated in the site palette on near-black. Cover carries the story at a glance, the diagram still carries the architecture below it.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 116 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
@@ -18,6 +18,9 @@ const projects = defineCollection({
|
|||||||
order: z.number().default(50),
|
order: z.number().default(50),
|
||||||
// Optional diagram key → rendered by the Diagram component (M3).
|
// Optional diagram key → rendered by the Diagram component (M3).
|
||||||
diagram: z.string().optional(),
|
diagram: z.string().optional(),
|
||||||
|
// Optional cover art → /covers/<slug>.webp, rendered above the case header.
|
||||||
|
// Sells the story at a glance; the diagram still carries the architecture.
|
||||||
|
cover: z.string().optional(),
|
||||||
links: z
|
links: z
|
||||||
.array(z.object({ label: z.string(), href: z.string().url() }))
|
.array(z.object({ label: z.string(), href: z.string().url() }))
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ period: "2025 – Present"
|
|||||||
stack: ["Kubernetes", "Edge", "NVIDIA GPU", "CD pipelines", "Helm", "Python"]
|
stack: ["Kubernetes", "Edge", "NVIDIA GPU", "CD pipelines", "Helm", "Python"]
|
||||||
featured: true
|
featured: true
|
||||||
order: 10
|
order: 10
|
||||||
|
cover: "edge-ai-platform"
|
||||||
diagram: "edge-ai"
|
diagram: "edge-ai"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ period: "2019 – 2025"
|
|||||||
stack: ["VMware / vSphere", "Azure (Blob, AVS)", "Microsoft 365", "SD-WAN", "Aruba ClearPass", "Palo Alto / FortiGate", "Veeam"]
|
stack: ["VMware / vSphere", "Azure (Blob, AVS)", "Microsoft 365", "SD-WAN", "Aruba ClearPass", "Palo Alto / FortiGate", "Veeam"]
|
||||||
featured: false
|
featured: false
|
||||||
order: 40
|
order: 40
|
||||||
|
cover: "global-infra-modernisation"
|
||||||
---
|
---
|
||||||
|
|
||||||
## Problem
|
## Problem
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ period: "2025 – Present"
|
|||||||
stack: ["GPU passthrough", "ESXi", "DCGM Exporter", "Prometheus", "Bash", "Watchdogs"]
|
stack: ["GPU passthrough", "ESXi", "DCGM Exporter", "Prometheus", "Bash", "Watchdogs"]
|
||||||
featured: false
|
featured: false
|
||||||
order: 30
|
order: 30
|
||||||
|
cover: "gpu-as-code"
|
||||||
---
|
---
|
||||||
|
|
||||||
## Problem
|
## Problem
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ period: "2025 – Present"
|
|||||||
stack: ["Ansible", "AWX", "GitOps", "ACR / NVCR", "Image pre-pull", "Secrets mgmt"]
|
stack: ["Ansible", "AWX", "GitOps", "ACR / NVCR", "Image pre-pull", "Secrets mgmt"]
|
||||||
featured: true
|
featured: true
|
||||||
order: 20
|
order: 20
|
||||||
|
cover: "iac-fleet-automation"
|
||||||
diagram: "iac-fleet"
|
diagram: "iac-fleet"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ period: "2019 – 2022"
|
|||||||
stack: ["Unimus (NCM)", "NetBox (IPAM / SoT)", "Config backup & DR", "Bulk config push", "Credential vaulting + rotation", "Multi-vendor switching"]
|
stack: ["Unimus (NCM)", "NetBox (IPAM / SoT)", "Config backup & DR", "Bulk config push", "Credential vaulting + rotation", "Multi-vendor switching"]
|
||||||
featured: false
|
featured: false
|
||||||
order: 45
|
order: 45
|
||||||
|
cover: "network-automation-fleet"
|
||||||
diagram: "network-fleet"
|
diagram: "network-fleet"
|
||||||
links:
|
links:
|
||||||
- label: "Unimus"
|
- label: "Unimus"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ period: "Ongoing"
|
|||||||
stack: ["Talos", "OpenShift", "ArgoCD", "Proxmox", "Local LLM", "Cloudflare Tunnel"]
|
stack: ["Talos", "OpenShift", "ArgoCD", "Proxmox", "Local LLM", "Cloudflare Tunnel"]
|
||||||
featured: true
|
featured: true
|
||||||
order: 15
|
order: 15
|
||||||
|
cover: "self-hosted-ai-homelab"
|
||||||
diagram: "homelab"
|
diagram: "homelab"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,19 @@ const { Content } = await render(entry);
|
|||||||
<div class="container case__inner">
|
<div class="container case__inner">
|
||||||
<a class="case__back mono" href="/projects/">← All projects</a>
|
<a class="case__back mono" href="/projects/">← All projects</a>
|
||||||
|
|
||||||
|
{p.cover && (
|
||||||
|
<figure class="case__cover" data-reveal>
|
||||||
|
<img
|
||||||
|
src={`/covers/${p.cover}.webp`}
|
||||||
|
alt={`${p.title} — cover art`}
|
||||||
|
width="1600"
|
||||||
|
height="1073"
|
||||||
|
loading="eager"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</figure>
|
||||||
|
)}
|
||||||
|
|
||||||
<header class="case__head" data-reveal>
|
<header class="case__head" data-reveal>
|
||||||
<p class="eyebrow">Case study</p>
|
<p class="eyebrow">Case study</p>
|
||||||
<h1 class="case__title">{p.title}</h1>
|
<h1 class="case__title">{p.title}</h1>
|
||||||
@@ -65,6 +78,21 @@ const { Content } = await render(entry);
|
|||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
/* Cover art is generated in the site palette on near-black, so it sits on the
|
||||||
|
page background directly - no light card (that's for the fixed-colour SVG
|
||||||
|
diagrams, which need a constant surface to stay legible in dark mode). */
|
||||||
|
.case__cover {
|
||||||
|
margin: 0 0 var(--space-6);
|
||||||
|
border: 1px solid var(--border-accent);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.case__cover img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.case__title {
|
.case__title {
|
||||||
margin-top: var(--space-3);
|
margin-top: var(--space-3);
|
||||||
font-size: var(--step-4);
|
font-size: var(--step-4);
|
||||||
|
|||||||
Reference in New Issue
Block a user