← 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`