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: 72chfor 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, slighttranslateY(-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-overlayscrim - Title in
blog-hero-title - Category pill + date + read time in
blog-meta - Minimum height:
280pxon mobile,360pxon 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 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Navigation
- Header: HoffDesk logo (links to dashboard home) | "Blog" | category links | search icon | RSS icon
- Sticky on scroll โ thin bar (56px height),
bg-primarywithborder-defaultbottom 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)
Footer
- Minimal. One line:
ยฉ 2026 HoffDesk ยท Built with โ and OpenClaw ยท RSS - Link back to
hoffdesk.comdashboard 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:
- Focus indicators: All interactive elements get visible
:focus-visiblerings (2px solid accent-primary, offset 2px) - Contrast: All blog text meets 4.5:1 minimum. Blog body at 17px on
bg-primarywithtext-primarypasses at 13.3:1 - Link clarity: Links are underlined in article body. Color alone never indicates a link
- Heading hierarchy: Proper
<h1>โ<h2>โ<h3>nesting on every page - Image alt text: Required for all images (enforced in content template)
- ARIA landmarks:
<nav>,<main>,<article>,<footer>โ proper semantic HTML - 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:
GET /api/blog/postsโ Paginated post list with:slug,title,excerpt,category,date,read_time,authorGET /api/blog/posts/:slugโ Full article with:title,body_html(rendered markdown),category,date,author,read_time,prev_slug,next_slugGET /api/blog/posts?category=:catโ Filtered by categoryGET /blog/feed.xmlโ RSS 2.0 feed- 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.