Blog Image Pipeline — Technical Spec
Status: Sprint 1 (Manual) — Ready for Implementation
Author: Daedalus 🎨
For: Socrates 🧠
Current State
Hero image created:
- File: workspace-daedalus/blog/posts/the-night-i-broke-dns/images/hero.svg
- Format: SVG (scalable, ~7KB)
- Dimensions: 1200×630 (Open Graph optimal)
- Style: Network topology diagram, Emerald Toffee palette
What it shows:
- Left: 11 PM Saturday — working setup with Pi-hole configured, missing secondary DNS
- Right: 7:45 AM Sunday — Pi-hole crashed, 14 devices offline
- Bottom: The fix — docker restart pihole + fallback configured
- Visual elements: Router, Beelink, cloud DNS, device icons (phone, tablet, dog bowl, thermostat)
File Structure
data/blog/posts/{slug}/
├── index.md # Article with frontmatter
├── images/ # Post-specific assets
│ ├── hero.svg # Primary hero (Sprint 1)
│ ├── hero.png # Fallback raster (optional)
│ └── diagram-2.svg # Additional inline diagrams
└── metadata.yaml # Optional separate metadata
Frontmatter reference:
---
title: "The Night I Broke DNS and My Wife Couldn't Reach Facebook"
slug: "the-night-i-broke-dns"
category: "homelab"
date: 2026-04-20
author: "Matt"
excerpt: "..."
hero_image: "images/hero.svg" # ← relative to post directory
hero_alt: "Network topology diagram showing DNS failure cascade"
---
Builder Integration
Step 1: Copy images to dist
When builder.py generates static HTML, it should:
- Parse post frontmatter for
hero_imagefield - Copy
data/blog/posts/{slug}/images/*todist/blog/{slug}/images/ - Rewrite image paths in generated HTML to absolute
/blog/{slug}/images/
Step 2: HTML output
Generated article HTML should include:
<!-- Hero image in Open Graph meta -->
<meta property="og:image" content="https://hoffdesk.com/blog/the-night-i-broke-dns/images/hero.svg"/>
<meta property="og:image:width" content="1200"/>
<meta property="og:image:height" content="630"/>
<!-- Hero image in article header -->
<figure class="hero-image">
<img src="/blog/the-night-i-broke-dns/images/hero.svg"
alt="Network topology diagram showing DNS failure cascade"
width="1200" height="630"
loading="eager">
</figure>
Step 3: CSS styling
The existing blog.css already has hero image styles:
.hero-image {
margin: 0 calc(-1 * var(--blog-gutter)) 2rem;
position: relative;
}
.hero-image img {
width: 100%;
height: auto;
display: block;
}
@media (min-width: 768px) {
.hero-image {
margin-left: 0;
margin-right: 0;
border-radius: 8px;
overflow: hidden;
}
}
Image Guidelines (for future posts)
Formats
| Use Case | Format | Why |
|---|---|---|
| Hero images | SVG | Scalable, tiny, crisp at all sizes |
| Diagrams | SVG | Editable, version-controllable |
| Photos | WebP/PNG | Raster fallback for actual imagery |
| Icons | Inline SVG | No extra requests |
Dimensions
- Hero: 1200×630 (Open Graph standard)
- Inline diagrams: Max-width 800px, variable height
- Thumbnails: 400×300 (for related posts grid)
Design System
Home Lab series:
- Topology diagrams with before/during/after states
- Color code: Green (working), Red (failed), Gold (fix), Dotted (missing)
- Midnight Teal background, Warm Toffee lines
OpenClaw series:
- Workflow/agent interaction diagrams
- Rounded boxes, emoji-style agent icons
AI News series:
- Abstract data visualizations
- Minimalist charts, no stock photography
Sprint 2: Semi-Automated (Future)
Tool: Python diagrams library or Graphviz
Input: YAML in frontmatter:
hero_diagram:
type: network_failure
title: "The Night I Broke DNS"
nodes:
- id: router
label: "Router"
icon: router
x: 100
y: 100
- id: pihole
label: "Pi-hole"
icon: server
status: failed
x: 300
y: 100
connections:
- from: router
to: pihole
style: failed
Output: SVG auto-generated at build time, styled with design tokens
Not Sprint 1. Manual SVG creation for now.
Sprint 3: AI-Assisted (Future)
Constraint: Local generation only (Gaming PC 3080 Ti)
Workflow:
1. Article draft complete
2. Daedalus writes image prompt based on excerpt
3. Local Stable Diffusion generates options
4. Manual selection and post-processing
5. Commit to images/ folder
No third-party image APIs — sovereign constraint.
Checklist for Socrates
- [ ] Update
builder.pyto copyimages/folders todist/ - [ ] Parse
hero_imagefrom frontmatter, include in generated HTML - [ ] Add Open Graph meta tags for social sharing
- [ ] Test with DNS post hero.svg
- [ ] Verify image loads correctly at
/blog/{slug}/images/hero.svg - [ ] Confirm mobile rendering (SVG scales perfectly)
Files Ready Now
workspace-daedalus/blog/posts/the-night-i-broke-dns/images/hero.svg— Hero imageshared/project-docs/blog/image-pipeline-proposal.md— Full design proposal- This spec — Implementation guide
Next: Wire image copying into builder, test end-to-end with DNS post.