๐Ÿ“„ blog-frontend-design.md 13,915 bytes Apr 20, 2026 ๐Ÿ“‹ Raw

HoffDesk Blog โ€” Frontend Design Specification

Author: Daedalus ๐ŸŽจ
Date: 2026-04-20
Status: Approved โ€” Phase 3 unblocked
Depends on: Sprint 1 Design Tokens (shared/design-tokens/sprint-1.md)


Design Philosophy

The blog extends the HoffDesk "Functional Luxury" aesthetic into long-form content. The same dark palette, the same typography discipline โ€” but with a reading experience that prioritizes sustained engagement over glanceable status.

If the dashboard is a control panel, the blog is a library: same building, different room.

Core principle: The words are the product. Every design decision serves readability first, aesthetics second.


Layout Architecture

Page Structure

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  HEADER (sticky)                     โ”‚
โ”‚  [Logo] [Categories] [Search] [RSS]  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                      โ”‚
โ”‚  HERO / FEATURED POST                โ”‚
โ”‚  (full-width, large image, overlay)  โ”‚
โ”‚                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                      โ”‚
โ”‚  POST GRID                           โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”            โ”‚
โ”‚  โ”‚  Card   โ”‚ โ”‚  Card   โ”‚  (2-col)   โ”‚
โ”‚  โ”‚         โ”‚ โ”‚         โ”‚  desktop   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”            โ”‚
โ”‚  โ”‚  Long-form Card      โ”‚  (1-col)  โ”‚
โ”‚  โ”‚  (featured mid-scroll)โ”‚           โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚
โ”‚                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  FOOTER                              โ”‚
โ”‚  [About] [RSS] [HoffDesk Home]       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Mobile Layout (Primary Target)

  • Single column, full-width cards
  • Sticky header collapses to hamburger menu
  • Featured post renders as full-bleed hero image with text overlay
  • Post cards stack vertically with generous spacing
  • Reading view: 20px side padding, max-width: 72ch for body text

Desktop Layout (>1024px)

  • Two-column post grid on index page
  • Article view: centered single column, max-width: 720px
  • Sidebar appears on article pages with: category list, recent posts, RSS link
  • Sidebar width: 280px, hidden on mobile

Typography โ€” Blog Extensions

Extends the Sprint 1 type scale. Blog content has different needs than dashboard widgets.

Token Size Weight Line Height Usage
blog-hero-title 2rem (32px) 700 1.2 Featured post headline
blog-post-title 1.5rem (24px) 700 1.25 Article title
blog-card-title 1.125rem (18px) 600 1.3 Card titles on index
blog-body 1.0625rem (17px) 400 1.7 Article body โ€” slightly larger for reading comfort
blog-body-sm 0.9375rem (15px) 400 1.6 Excerpts, card descriptions
blog-quote 1.25rem (20px) 400 italic 1.5 Pull quotes in articles
blog-caption 0.8125rem (13px) 500 1.4 Image captions, bylines
blog-meta 0.75rem (12px) 500 1.4 Dates, category tags, read time

Font stack: Same as dashboard โ€” Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif. Zero external font loads.

Key difference from dashboard: Blog body text is 17px (vs 16px dashboard) with 1.7 line-height (vs 1.5) for sustained reading comfort. This is intentional โ€” 16px works for glanceable data, 17px works for paragraphs people actually read.


Color Usage โ€” Blog-Specific

All dashboard tokens apply. Blog adds:

Token Value Usage
blog-accent #818cf8 Link text, category pills (slightly lighter than accent-primary for readability in body copy)
blog-accent-hover #a5b4fc Link hover state
blog-code-bg #1a1d27 Inline code background (bg-secondary reuse)
blog-code-block-bg #13151d Fenced code blocks (slightly darker for visual separation)
blog-blockquote-border #6366f1 Left border on pull quotes
blog-img-overlay rgba(15, 17, 23, 0.6) Hero image text overlay scrim

Category Colors

Each content category gets a distinct accent for pill badges and visual scanning:

Category Color Token Name
Home Lab Growing Pains #f97316 (orange) cat-homelab
OpenClaw Hacks & Tutorials #6366f1 (indigo โ€” primary accent) cat-openclaw
AI News & Trends #22d3ee (cyan) cat-ai

Component Specifications

Post Card

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  [Category Pill]               โ”‚
โ”‚                                โ”‚
โ”‚  Post Title                    โ”‚
โ”‚  Two-line excerpt max...       โ”‚
โ”‚                                โ”‚
โ”‚  Apr 20 ยท 8 min read          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Background: bg-secondary (#1a1d27)
  • Border: 1px solid border-default (#2e3142)
  • Border radius: radius-md (12px)
  • Padding: space-6 (24px)
  • Hover: bg-tertiary, shadow-card-hover, slight translateY(-2px)
  • Transition: transition-base (250ms ease)
  • No images on cards โ€” text-only for performance and simplicity (Sprint 1)

Hero / Featured Post

  • Full-width container
  • Optional background image with blog-img-overlay scrim
  • Title in blog-hero-title
  • Category pill + date + read time in blog-meta
  • Minimum height: 280px on mobile, 360px on desktop
  • Text left-aligned, bottom-anchored

Category Pill

  • Background: category color at 12% opacity (e.g., rgba(99,102,241,0.12) for OpenClaw)
  • Text: category color at full opacity
  • Border radius: radius-sm (6px)
  • Padding: 4px 10px
  • Font: blog-meta (12px, weight 500)
  • Hover: background opacity โ†’ 20%

Article Page

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  โ† Back to Blog    [Category Pill]   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                      โ”‚
โ”‚  Title (blog-post-title)             โ”‚
โ”‚  By [Author] ยท Apr 20, 2026          โ”‚
โ”‚  ยท 8 min read                       โ”‚
โ”‚                                      โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€       โ”‚
โ”‚                                      โ”‚
โ”‚  Article body (blog-body, 17px)      โ”‚
โ”‚  max-width: 720px, centered          โ”‚
โ”‚                                      โ”‚
โ”‚  - Headings in text-primary          โ”‚
โ”‚  - Links in blog-accent              โ”‚
โ”‚  - Code blocks on blog-code-block-bg โ”‚
โ”‚  - Blockquotes with left border      โ”‚
โ”‚  - Images: full-width, radius-md     โ”‚
โ”‚                                      โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€       โ”‚
โ”‚                                      โ”‚
โ”‚  [Prev Post]          [Next Post]    โ”‚
โ”‚                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  FOOTER                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Header: HoffDesk logo (links to dashboard home) | "Blog" | category links | search icon | RSS icon
  • Sticky on scroll โ€” thin bar (56px height), bg-primary with border-default bottom border
  • Mobile: Logo + hamburger. Hamburger reveals slide-down menu with category links + search
  • Search: Simple text input, filters post titles and excerpts client-side (no backend search needed for Sprint 1)
  • Minimal. One line: ยฉ 2026 HoffDesk ยท Built with โ˜• and OpenClaw ยท RSS
  • Link back to hoffdesk.com dashboard home
  • Link to RSS feed

Responsive Breakpoints

Same as dashboard:

Breakpoint Width Behavior
Mobile < 640px Single column, full-width cards, no sidebar
Tablet 640โ€“1024px Two-column grid, sidebar hidden
Desktop > 1024px Two-column grid + sidebar on article pages

Mobile is the primary target. Every layout must look excellent on a 375px viewport before we consider wider screens.


Performance Budget

Blog pages must meet the same performance standards as the dashboard:

Metric Target
LCP < 2.5s
FID < 100ms
CLS < 0.1
Total JS < 15KB (HTMX + Alpine if needed)
Total CSS < 25KB (Tailwind purged)
External requests 0 fonts, 0 analytics, 0 CDN scripts

No third-party JS. No Google Fonts. No analytics scripts. HoffDesk runs its own infrastructure โ€” we track our own metrics if we track them at all.


Accessibility (WCAG 2.1 AA)

Following the Sprint 1 a11y review findings:

  1. Focus indicators: All interactive elements get visible :focus-visible rings (2px solid accent-primary, offset 2px)
  2. Contrast: All blog text meets 4.5:1 minimum. Blog body at 17px on bg-primary with text-primary passes at 13.3:1
  3. Link clarity: Links are underlined in article body. Color alone never indicates a link
  4. Heading hierarchy: Proper <h1> โ†’ <h2> โ†’ <h3> nesting on every page
  5. Image alt text: Required for all images (enforced in content template)
  6. ARIA landmarks: <nav>, <main>, <article>, <footer> โ€” proper semantic HTML
  7. Reading flow: No content reorder tricks. Visual order = DOM order

Architectural Decisions (Resolved)

Question Decision Rationale
Post pages Full HTML pages (not HTMX partials) SEO is primary โ€” static HTML at edge, indexable
Category/tag archives Card grid (2-col desktop, 1-col mobile) Matches post index; visual scanning on wider screens
Admin UI Functional-minimal first, skinned later Socrates builds plumbing; Daedalus designs admin in Sprint 2
Image handling (MVP) Simple <img> only No images on cards in Sprint 1; <picture>/srcset deferred to Sprint 2
RSS feed Full content, RSS 2.0 Content strategy mandates full-content; RSS 2.0 has wider support
Search (Sprint 1) Client-side (Fuse.js preferred) Lunr.js or Fuse.js; backend FTS5 reserved for when we have volume

Tech Stack

Layer Technology Notes
Templating Jinja2 (for static generation) Pre-rendered HTML, not dynamic SSR
Styling Custom CSS (design tokens) Same token system as dashboard, extended for blog
Interactivity HTMX (admin only) + vanilla JS (search) Public pages are static; HTMX only for admin interface
Search Fuse.js (client-side) Tiny JS, runs in browser; loads post index JSON
RSS RSS 2.0, full content Auto-generated by builder.py
Images <img> (MVP) Simple; <picture>/srcset in Sprint 2
Hosting Cloudflare Pages Static output from builder pipeline

File Structure (Sprint 1)

blog/
โ”œโ”€โ”€ templates/
โ”‚   โ”œโ”€โ”€ base.html.j2            # Shared layout (head, header, footer)
โ”‚   โ”œโ”€โ”€ blog_index.html.j2      # Post listing page
โ”‚   โ”œโ”€โ”€ blog_article.html.j2    # Individual article page (full HTML for SEO)
โ”‚   โ”œโ”€โ”€ blog_category.html.j2   # Category archive page
โ”‚   โ”œโ”€โ”€ blog_tag.html.j2        # Tag archive page
โ”‚   โ””โ”€โ”€ feed.xml.j2             # RSS 2.0 feed template
โ”œโ”€โ”€ static/
โ”‚   โ”œโ”€โ”€ blog.css                # Blog-specific styles
โ”‚   โ””โ”€โ”€ search.js               # Fuse.js client-side search (Sprint 1)
โ”œโ”€โ”€ content/
โ”‚   โ”œโ”€โ”€ homelab/
โ”‚   โ”œโ”€โ”€ openclaw/
โ”‚   โ””โ”€โ”€ ai-news/
โ””โ”€โ”€ builder.py                  # Static site generation

Socrates Integration Notes

What the frontend needs from the backend:

  1. GET /api/blog/posts โ€” Paginated post list with: slug, title, excerpt, category, date, read_time, author
  2. GET /api/blog/posts/:slug โ€” Full article with: title, body_html (rendered markdown), category, date, author, read_time, prev_slug, next_slug
  3. GET /api/blog/posts?category=:cat โ€” Filtered by category
  4. GET /blog/feed.xml โ€” RSS 2.0 feed
  5. Content stored as: Markdown files in blog/content/ with YAML frontmatter, rendered server-side to HTML

Frontmatter spec:

---
title: "Your Post Title"
slug: "your-post-title"
category: "openclaw"  # homelab | openclaw | ai-news
date: 2026-04-20
author: "Matt"
excerpt: "One or two sentences that appear in the card and RSS feed."
read_time: 8  # estimated minutes
tags: ["openclaw", "automation", "tutorial"]
---

This spec is the contract for blog frontend. Changes here propagate to implementation. Socrates builds the backend to match these API needs.