# News images — Pedestal Health

Branded **portrait** (grid/hero) and **landscape** (OG/social) composites for `resources/news` articles.

## Field mapping

| Output | CMS field | Aspect | Use |
|--------|-----------|--------|-----|
| Portrait composite | `visuals[0]` (Media entry) | 320:427 (960×1281 uploaded) | News grid, carousel, article hero |
| Landscape composite | `featuredImage` (Asset) | 1200×630 | Open Graph / social share |

Always set **both** on news articles. Article `cmsLabel` stays `News — {title}` — only image assets use composite names.

## Composite naming (reuse)

Uploaded composites are named by **content + treatment**, not article title:

`News composite — iStock-518224694 · Ocean · portrait:color-frame · landscape:extended-frame`

Identical source photo + style + treatments + colour → **one shared composite** linked from multiple articles:

| Shared object | Count per composite | Article field |
|---------------|---------------------|---------------|
| Portrait asset | **1** | via Media entry → `visuals[0]` |
| Media entry (portrait wrapper) | **1** | `visuals[0]` |
| Landscape asset | **1** | `featuredImage` |

Search Contentful for `News composite —` before uploading. **Never create a new Media entry per article** when the composite already exists.

## Hosted MCP workflow (pre-rendered composites)

Use when composites are supplied as files (logo batch, local render) or studio is unavailable. Read `cms-edit://customer/task-media-reuse-and-upload` for staged upload rules.

### Reuse-first (required)

After `cms_edit ["index", "sync"]`:

1. Search portrait asset by title: `cms_edit ["asset", "search", "News composite — logo:easl"]` (adjust source/colour/treatment substring for your batch)
2. When portrait asset exists, find the **shared Media entry**: `cms_edit ["list", "--type", "media", "--asset-id", "<portraitAssetId>"]` → note **one** media entry ID
3. Find landscape asset (title ends with `landscape:…`) via search, or copy from a sibling article that already has this composite
4. **Shortcut:** `open` an article that already uses the composite → `read @root visuals` and `read @root featuredImage` → reuse those IDs for every other article in the batch

**Never:**

- `asset upload --with-media` on each article (creates duplicate Media wrappers)
- `create media` per article when a wrapper already exists for that composite
- Name assets or media after article titles

### Link existing composite (preferred)

```
cms_edit ["open", "--id", "<article-entry-id>"]
cms_edit ["set", "@root", "visuals", "<sharedMediaEntryId>", "--links"]
cms_edit ["asset", "set", "@root", "featuredImage", "<sharedLandscapeAssetId>"]
cms_edit ["diff"]
cms_edit ["save"]
```

Repeat for each article using the **same** media entry ID and landscape asset ID.

### Upload new composite (only when search finds no match)

1. Staged upload portrait JPEG → portrait asset ID (`--if-exists-by-filename` + composite `fileName`)
2. Staged upload landscape JPEG → landscape asset ID
3. **Once per composite** (not per article): `cms_edit ["create", "media", "--asset-id", "<portraitAssetId>", "--name", "News composite — … portrait:…"]` → media entry ID
4. Link every article in the batch via **Link existing composite** above

**Batch example (EASL / shared logo):** upload portrait + landscape once, create **one** Media entry once, link the same IDs to all articles that share that logo + colour + treatments.

## News Image Studio (preferred)

Dev/preview only: `/cms/news-images`

1. Select article (filter: missing images, drafts)
2. Review suggestion — abstract source pool only (no human body parts in auto-pick)
3. Adjust source photo, style (photo vs logo), treatments, brand colour
4. Preview portrait + landscape
5. **Apply** — reuses existing composite when match exists; **Replace existing images** forces re-render

Paste Contentful Management token in UI for customer apply, or leave empty for server token.

## Style chooser

| Style | When |
|-------|------|
| **Photo** | Press releases, disease milestones, general news |
| **Logo** | Conference, industry partner, or medical society — only if logo asset ≥ 400px wide |

Low-resolution logos fall back to photo style automatically.

## Portrait treatments

| Treatment | Effect |
|-----------|--------|
| `full-color` | Edge-to-edge photo |
| `color-frame` | 24px brand border |
| `extended-frame` | Asymmetric brand strip |
| `extended-full-frame` | 32px border all sides |
| `gradient-overlay` / `gradient-frame` | Brand gradient from top |
| `concentric-shapes` | Inset photo with layered rects |

## Landscape treatments

| Treatment | Effect |
|-----------|--------|
| `full-color` | Edge-to-edge (may crop from portrait) |
| `gradient` | Photo + brand gradient |
| `extended-frame` | Inset photo on brand backdrop |
| `concentric-shapes` | Layered rects |
| `logo-center` | Partner/conference logo centred |

## Source photos

- Auto-suggest uses **abstract-only** iStock filenames (`ABSTRACT_FILENAMES` in site-common)
- Curated title → iStock map: `content/pedestal-website/news-image-matching.md` (non-abstract rows are manual-only)
- Upload new stock via studio **Upload photo**

## Logos

Conference/partner logos: Contentful assets tagged `news-image-logo`, title `News Image Logo — {slug}`. Upload via studio; minimum 400px width.

## CLI (engineering batch)

See `apps/pedestal-website/docs/news-image-pipeline.md` — `suggest-news-images.ts` → `apply-news-image-plan.ts`. Registry: `scripts/data/news-image-composite-registry.json`.

## Related

- `cms-edit://customer/news-pages` — article fields and workflow
- `cms-edit://customer/articles` — URL and tag rules