| 1 | # Article Visual Modules (#328) |
| 2 | |
| 3 | Reusable, **locally generated** visual modules that give every weekly article a |
| 4 | meaningful visual or an intentional fallback — without third-party/hotlinked |
| 5 | imagery and without enabling Goldmark `unsafe`. |
| 6 | |
| 7 | ## Design principles |
| 8 | |
| 9 | - **Generated first.** Visuals are built from the article's own data (frontmatter |
| 10 | metadata) or author-declared shortcode values. No stock images, no hotlinks, |
| 11 | no `og:image` reuse. |
| 12 | - **Evidence-first.** Modules help scanning/comprehension; they never overstate |
| 13 | weak signals, hide caveats, or imply rankings. Decorative motifs are disclosed |
| 14 | (`aria-hidden`) and never carry the data claim — real figures are always text. |
| 15 | - **Safe by construction.** `unsafe = false` stays. HTML lives in partials / |
| 16 | shortcodes, never in Markdown bodies. |
| 17 | - **No layout breakage.** Missing data yields an intentional fallback card, not an |
| 18 | empty or broken region. Fixed aspect ratios reserve space (no CLS). |
| 19 | |
| 20 | ## Module taxonomy |
| 21 | |
| 22 | | Module | Source | When to use | |
| 23 | | --- | --- | --- | |
| 24 | | **Generated cover card** (`visuals/cover-card.html`) | frontmatter `week`, `tags`, `repos_featured` | Default header for every weekly article. Bar-field count reflects topic breadth; accessible name reports real week/topic/repo figures. | |
| 25 | | **Topic / star visualization** (`visuals/topic-constellation.html`, shortcode `topic-stars`) | `tags` / author list | Surface the week's topic clusters as equal-weight chips. Honest by construction. | |
| 26 | | **Signal & Noise summary** (`visuals/signal-noise.html`, shortcode `signal-noise`) | frontmatter `signal_noise` or shortcode args | Two-column scannable summary of durable signal vs noise floor, with a required caveat slot. | |
| 27 | | **Repo trend chart** (`visuals/repo-trend.html`, shortcode `repo-trend`) | author/pipeline numeric series | Lightweight bar chart for star/momentum history. Bars are decorative; the series is exposed as a visually-hidden text summary. | |
| 28 | | **Intentional fallback card** (`visuals/fallback-card.html`) | `visual = "none"` | Deliberate "no standalone visual this week" card. | |
| 29 | |
| 30 | ## Selection rules (orchestrator `visuals/article-cover.html`) |
| 31 | |
| 32 | 1. `visual = "none"` → intentional fallback card. |
| 33 | 2. A **compliant local cover image** (resolves to a Hugo page-bundle or global |
| 34 | resource) → processed, locally-hosted `<img>`. See safe-cover policy below. |
| 35 | 3. Otherwise → generated SVG cover card. |
| 36 | |
| 37 | ## Declaring modules |
| 38 | |
| 39 | - **Automatic (generated metadata):** the cover card renders from existing |
| 40 | frontmatter (`week`, `tags`, `repos_featured`); the Signal & Noise card renders |
| 41 | when `signal_noise` is present. |
| 42 | - **Frontmatter example:** |
| 43 | |
| 44 | ```yaml |
| 45 | signal_noise: |
| 46 | signal: |
| 47 | - "Agent skills verticalizing into professional packs" |
| 48 | noise: |
| 49 | - "Coordinated activator / star-farm repos" |
| 50 | caveat: "Editorial judgments, not automated classifications; counts are not rankings." |
| 51 | source: "Derived from this week's new_repos sample." |
| 52 | ``` |
| 53 | |
| 54 | - **Inline shortcodes** (pipe-separated values), for body-level placement: |
| 55 | |
| 56 | - `topic-stars topics="agent-skills|local-first" stars="16480000" repos="390"` |
| 57 | - `repo-trend repo="cpaczek/skylight" values="120|340|512|890|2332" labels="W20|W21|W22|W23|W24"` |
| 58 | - `signal-noise signal="A|B" noise="C|D" caveat="…"` |
| 59 | |
| 60 | ## Safe cover policy hook (#329) |
| 61 | |
| 62 | Images are only rendered when `cover.image` resolves to a **locally hosted Hugo |
| 63 | resource** (downloaded + processed). External / hotlinked URLs are intentionally |
| 64 | ignored, and we never rely on fair use or reuse `og:image`. Attribution |
| 65 | (`cover.attribution`) is rendered when present; full CC0/Openverse sourcing, |
| 66 | resizing, attribution, and the image registry are owned by **#329**. Until then, |
| 67 | articles lead with generated visuals + the typographic fallback. |
| 68 | |
| 69 | ## Accessibility & responsiveness |
| 70 | |
| 71 | - SVG motifs are `aria-hidden`; data is always available as text (accessible |
| 72 | names / visually-hidden summaries). |
| 73 | - Responsive at 320/360/390/414/768px: SVGs use `width:100%` + `viewBox`; the |
| 74 | signal/noise grid collapses to one column on mobile; no horizontal scroll. |
| 75 | - Aspect ratios reserve space to avoid CLS; interactive targets meet the 44×44 |
| 76 | minimum established in #327. |