📄 image-pipeline-spec.md 5,330 bytes Apr 20, 2026 📋 Raw

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:

  1. Parse post frontmatter for hero_image field
  2. Copy data/blog/posts/{slug}/images/* to dist/blog/{slug}/images/
  3. 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.py to copy images/ folders to dist/
  • [ ] Parse hero_image from 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

  1. workspace-daedalus/blog/posts/the-night-i-broke-dns/images/hero.svg — Hero image
  2. shared/project-docs/blog/image-pipeline-proposal.md — Full design proposal
  3. This spec — Implementation guide

Next: Wire image copying into builder, test end-to-end with DNS post.