From 22cdc1bc342e80bbce46a1d87910a444912cba22 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Fri, 13 Mar 2026 13:57:29 +0100 Subject: [PATCH 1/5] feat(design): add DDD-004 home page post index design decision Defines the complete design contract for the home page post index: reverse-chronological post list with type badge, title, description, date, and tags per entry. All tokens map to existing CSS custom properties. Status: Proposal. Resolves #5 Co-Authored-By: Claude Signed-off-by: Ben Peter --- .../DDD-004-home-post-index.md | 549 ++++++++++++++++++ 1 file changed, 549 insertions(+) create mode 100644 docs/design-decisions/DDD-004-home-post-index.md diff --git a/docs/design-decisions/DDD-004-home-post-index.md b/docs/design-decisions/DDD-004-home-post-index.md new file mode 100644 index 0000000..ef1b6e2 --- /dev/null +++ b/docs/design-decisions/DDD-004-home-post-index.md @@ -0,0 +1,549 @@ +# DDD-004: Home Page Post Index + +Status: **Proposal** + +## Context + +The home page is the post index. There is no marketing copy, hero section, or other content — the entire page is a reverse-chronological list of posts. Each entry shows five elements: a type badge, a title, a description, a date, and tags. The design challenge is creating a list that is both dense enough to serve as an efficient archive and airy enough to remain readable. + +### Governing constraints + +**Site structure (docs/site-structure.md)** + +The home page specification from `docs/site-structure.md`: + +``` +URL: / + +The home page IS the post index. Latest posts, reverse chronological. Each entry shows: + +- Type label (build-log, pattern, tool-report, til) — small, muted, unobtrusive +- Title — primary visual element per entry +- Description — 1-2 sentences, body text weight +- Date — muted +- Tags — small, clickable, visually quiet + +Entries separated by breathing room and perhaps the faintest rule line +(--color-border-subtle). Not cards, boxes, or backgrounds. + +No pagination until 20+ posts. +``` + +**Content model (docs/content-model.md)** + +Five metadata fields are sourced from post front matter and exposed via `query-index.json`: + +| Field | Type | Notes | +|---|---|---| +| `title` | text | Primary heading per entry | +| `description` | text | 1-2 sentence summary, required | +| `date` | date | Determines sort order | +| `type` | enum | One of: `build-log`, `pattern`, `tool-report`, `til` | +| `tags` | list | Lowercase, hyphenated (e.g., `aem`, `claude-code`) | + +The four post types and their display labels: + +| Slug | Display label (DOM) | CSS-rendered | +|---|---|---| +| `build-log` | Build Log | BUILD LOG | +| `pattern` | Pattern | PATTERN | +| `tool-report` | Tool Report | TOOL REPORT | +| `til` | TIL | TIL | + +Tags follow flat namespace convention: lowercase, hyphenated. No title-casing. No categories. + +**Aesthetic rules (CLAUDE.md)** + +The relevant rules governing this surface: + +- `--color-background` (#F6F4EE light) is the dominant visual. The page is warm white paper. +- `--color-heading` (#3F5232 light) is the strongest color on the page. Everything else recedes. +- Borders and rules use `--color-border-subtle`. They almost melt into the background. +- No cards with shadows, no gradients, no rounded containers, no hero images, no decorative icons. +- Typography creates hierarchy, not color blocks or boxes. +- `--color-accent` (gold) appears at most once per screen. Never as a theme color. +- Green and gold are NOT co-equal theme colors. This is a warm-white site where color is a quiet guest. + +**DDD-001 layout contract** + +DDD-001 establishes the two-tier width model: `--layout-max` (1200px) as the outer guardrail and `--measure` (68ch) as the comfortable reading column. The post index constrains to `--measure`, not `--layout-max`. This is a deliberate choice: entries are reading content, not navigation chrome. Constraining to `--measure` keeps the list in the same visual column as post body text (DDD-005), establishing spatial continuity between the index and the posts it links to. + +The padding tokens (`--content-padding-mobile`, `--content-padding-tablet`, `--content-padding-desktop`) and section spacing (`--section-spacing: 48px`) apply unchanged from DDD-001. + +**DDD-002 / DDD-003 precedent** + +- **Focus ring pattern**: `outline: 2px solid var(--color-heading); outline-offset: 2px` on `:focus-visible`. Used in both the header and footer. The post index uses the same pattern for title links and tag links. +- **Link styling conventions**: `--color-link` for interactive text links. `text-decoration: none` as default; `text-decoration: underline` on hover. +- **Border-subtle usage**: `1px solid var(--color-border-subtle)` as an entry separator, matching the structural role of the footer's top border and the header's bottom border — a near-invisible rule that signals structure without imposing weight. + +**Design tokens (styles/tokens.css)** + +All tokens referenced in this document exist in `styles/tokens.css`. No new tokens are proposed. Every visual element in the post index maps to an existing CSS custom property. + +**V1 scope exclusions (CLAUDE.md)** + +Do not build these as part of the post index: + +- No pagination (build when 20+ posts exist) +- No featured post or hero entry +- No card shadows, rounded containers, or background fills per entry +- No sidebar or secondary navigation +- No reading time estimates +- No "related posts" section +- No dark mode toggle (OS is the toggle via `prefers-color-scheme`) + +**EDS data source (PREREQUISITE — blocks implementation)** + +The post index block differs fundamentally from the header and footer blocks. Instead of loading a CMS-authored content fragment, it fetches `query-index.json` — the EDS content index generated from blog post metadata. + +This requires a `helix-query.yaml` file at the project root that configures: +- **Include path**: `/blog/**` (all blog posts) +- **Required columns**: `path`, `title`, `description`, `date`, `type`, `tags` + +Without `helix-query.yaml`, the query index will not expose post metadata, and the block will have nothing to render. This file must be created and merged to `main` before the `post-index` block can be implemented or tested. + +The query index is automatically available at `/query-index.json` once `helix-query.yaml` is configured. The block fetches it client-side, sorts by `date` descending, and renders the entry list. See Open Question 4 for exact column naming and Open Question 6 for the auto-block vs. authored block decision. + +--- + +## Proposal + +### Layout + +The post index is a vertical stack of `
` entries. Each entry has five stacked elements. No flexbox grid is needed for the entry stack — standard block flow handles the vertical arrangement. The metadata line (date + tags) uses inline flow with CSS-generated middot separators. + +The width constraint is `max-width: var(--measure); margin-inline: auto` on the block element. This keeps entries in the reading column. + +#### Entry anatomy + +``` ++---------------------------------------------+ +| <-- max-width: --measure (68ch) ----------> | +| | +| BUILD LOG | +| --font-heading, --body-font-size-xs, | +| --color-text-muted, uppercase via CSS | +| | +| Building a Design System for EDS | +| --font-heading, --heading-font-size-m, | +| --color-heading, weight 600, link | +| | +| A practitioner's approach to design | +| tokens in Edge Delivery Services. | +| --font-body, --body-font-size-s, | +| --color-text, --line-height-body (1.7) | +| | +| March 12, 2026 . aem . eds . performance | +| --font-body, --body-font-size-xs, | +| date: --color-text-muted | +| tags: --color-link | +| | +|.............................................| +| 1px --color-border-subtle (between entries)| ++---------------------------------------------+ +``` + +#### List rhythm (two entries) + +``` ++---------------------------------------------+ +| <-- max-width: --measure (68ch) ----------> | +| | +| [sr-only h1: "Posts"] | +| | +| BUILD LOG | +| Building a Design System for EDS | +| A practitioner's approach to design | +| tokens in Edge Delivery Services. | +| March 12, 2026 . aem . eds . performance | +| | +| <-- margin-block-end: --section-spacing -> | +|.............................................| +| <-- 1px --color-border-subtle ----------> | +| | +| TOOL REPORT | +| Claude Code as a Pair Programmer | +| Six weeks of daily use: what it | +| gets right and where it still slips. | +| February 28, 2026 . claude-code . ai-workflow| +| | ++---------------------------------------------+ +``` + +#### Mobile wireframe (< 600px) + +``` ++-------------------------------------------------+ +| <-- viewport (375px) -----------------------> | +| | +| <20px> <20px> | +| BUILD LOG | +| Building a Design System | +| for EDS | +| A practitioner's approach to | +| design tokens in Edge Delivery | +| Services. | +| March 12, 2026 . aem . eds | +| . performance | +| | +| --content-padding-mobile (20px) | +| --section-spacing below entry (48px) | +|.................................................| +| 1px --color-border-subtle | ++-------------------------------------------------+ +``` + +At 375px viewport with 20px padding each side, 335px is available. Title at `--heading-font-size-m` (22px) wraps after approximately 18-20 characters. The metadata line wraps after the date on very narrow viewports — this is acceptable since `text-align: left` keeps the wrap point predictable. + +#### Desktop wireframe (>= 900px) + +``` ++----------------------------------------------------------------------+ +| <-- viewport (900px+) ---------------------------------------------> | +| | +| <32px> <32px> | +| +--------------------------------------------+ | +| | max-width: --measure (68ch ~ 550-600px) | | +| | | | +| | BUILD LOG | | +| | Building a Design System for EDS | | +| | A practitioner's approach to design tokens | | +| | in Edge Delivery Services. | | +| | March 12, 2026 . aem . eds . performance | | +| | | | +| | --content-padding-desktop (32px) | | +| +--------------------------------------------+ | +|......................................................................| +| 1px --color-border-subtle (between entries) | ++----------------------------------------------------------------------+ +``` + +At 900px+ the `--measure` constraint is reached. The entry column is centered within `--layout-max`. Whitespace flanks the reading column on wide viewports, consistent with DDD-001's two-tier width model. + +### Typography + +| Element | Font | Size | Weight | Color | Line-height | +|---|---|---|---|---|---| +| Type badge | `--font-heading` | `--body-font-size-xs` (15px / 14px) | 400 | `--color-text-muted` | 1 | +| Title (`

`) | `--font-heading` | `--heading-font-size-m` (22px / 21px) | 600 | `--color-heading` | `--line-height-heading` (1.25) | +| Description (`

`) | `--font-body` | `--body-font-size-s` (17px / 16px) | 400 | `--color-text` | `--line-height-body` (1.7) | +| Date (`

` uses "Build Log: " to match the DOM text of the badge, not the CSS-transformed rendering). + +**All four types use identical visual treatment.** There are no per-type colors, borders, or icons. The site's aesthetic rules prohibit decorative differentiation — color blocks and decorative elements are explicitly excluded. The type label text itself ("Build Log", "Pattern", "Tool Report", "TIL") provides sufficient differentiation. Readers who need to filter by type can use tag links; visual decoration per type would add noise without adding navigation value. + +**Title at `--heading-font-size-m`**: The page has a visually hidden `

` that sits at the top of the heading hierarchy. Post titles are `

` elements. `--heading-font-size-m` (22px / 21px) provides clear visual hierarchy within a dense list without competing with the site identity in the header. Larger sizes (`--heading-font-size-l` or above) would create an overwrought index that reads as a series of shouting headings rather than a navigable list. + +### Spacing & Rhythm + +| Spacing zone | Value | Token | Rationale | +|---|---|---|---| +| Entry separation: border | `1px solid var(--color-border-subtle)` | `--color-border-subtle` | Near-invisible separator — signals boundary without imposing visual weight. Not on last entry. | +| Entry separation: margin | `margin-block-end: var(--section-spacing)` | `--section-spacing` (48px) | Entries are semantically distinct items. 48px is the standard section gap. Exact value is an Open Question (see OQ 1). | +| Badge to title | `margin-block-start: 0` on `

` | — | Badge and title read as a unit. Tight stack, no gap between them. | +| Title to description | Default paragraph flow | `--space-paragraph` | Natural paragraph rhythm. | +| Description to metadata | Default paragraph flow | `--space-paragraph` | Natural flow; the `