← All playbooks · Raw API

news-images

# News images — Headwater Science

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

## Product model

**Source photo = Contentful asset** with a **stable SEO-sensible filename** (e.g. `diverse-team-lab.jpg`). That basename is part of the composite identity.

```text
News composite — {sourceBasename} · {color} · portrait:{treatment}
News composite — {sourceBasename} · {color} · landscape:{treatment}
```

Curated title→stock tables are **not product core**.

```text
media playbook (if new source)
  → POST /api/cms/news-images/render
      reused:true  → link existing IDs
      reused:false → signed download URLs
  → curl downloads → cms-edit staged upload (Upstash Redis) → asset upload --staged
  → create media + set visuals + featuredImage → save
```

**Never** set raw source as `featuredImage` alone.

## Storage

| Step | Where | Auth |
|------|--------|------|
| Source + reuse lookup | Contentful Preview API | Site preview token |
| Render CMS JPEGs | Site `/render` | No CMA |
| Short-lived files | Site Upstash Redis + HMAC download URL | `UPSTASH_*` + `NEWS_IMAGE_RENDER_HMAC_SECRET` |
| Agent staging | cms-edit Redis staged upload | OAuth user |
| CMS write | cms-edit | OAuth CMA |

No management token on marketing Vercel for the agent path.

## Agent: create or reuse

Staging origin: **https://headwater-website-git-develop-se-studio.vercel.app**

```http
POST /api/cms/news-images/render
{ "sourceAssetId": "<id>", "slug": "<article-slug>" }
```

**Reuse response** (`reused: true`): `portraitAssetId`, `landscapeAssetId`, `mediaEntryId` — link only.

**Fresh response** (`reused: false`):

```bash
curl -fsSL "$portrait.downloadUrl" -o "/tmp/$portrait.fileName"
curl -fsSL "$landscape.downloadUrl" -o "/tmp/$landscape.fileName"
# then cms_edit_request_staged_upload → curl to cms-edit uploadUrl → asset upload --staged
# create media (portrait); set visuals + featuredImage; save
```

Downloads expire (~30m). Max **4 MB** per file (cms-edit staged limit). Rate limited like Studio apply.

## Human Studio

`/cms/news-images?slug=…&sourceAssetId=…` on staging. Preview without CMA. **Apply** requires pasted personal CMA token only.

## Related

- `cms-edit://customer/task-news-images`
- `cms-edit://customer/task-media-reuse-and-upload`