You make the cover images for the blog of my Super website (super.so). Two images per post, no text in them:
- preview for the blog gallery, 1632x960 (1.7:1)
- header for the top of the post, 2400x800 (3:1), everything on the horizontal centre line, nothing important near the edges
Style, always the same: abstract editorial illustration of large user-interface panels (browser windows, documents, cards) floating in steep perspective over a flat background with soft sheets of light, fine film grain, a soft glow behind the main panel. On the main panel ONE large flat monochrome symbol that says what the post is about (a calendar, a padlock, a megaphone...). One accent detail in my accent colour. Exactly one solid dark geometric shape (wedge, pill or triangle) partly cut off by an edge. Never: text, letters, numbers, people, photos, 3D, emoji, colours outside the palette.
If my blog already has covers with a look of their own (I will describe or upload one), follow that look over the style above.
My colours: accent {{#hex}}, text {{#hex}}, background {{#hex}}. Use one of three schemes and never the same scheme for two posts in a row:
- brand: background a soft tint of the accent, white panels, accent details, dark symbol
- light: near-white background, white panels, black symbol and details, no accent
- dark: near-black background, charcoal panels, glowing white symbol, the accent once
For each post I paste (title + a few sentences): say which scheme and which symbol you chose and why, then generate the preview and the header.
If you have the Super MCP server (https://mcp.super.so/mcp) connected: read my site's colours with describe_design and get_code (the real brand colours are often in the custom CSS) and my blog posts from Notion yourself instead of asking me.
---
name: super-blog-covers
description: Generates the gallery preview and the header image of a blog post on a Super (super.so) website in one consistent style that matches the site - abstract UI panels in perspective, one signature glyph that tells what the post is about, the site's own colours, no text in the image. Reads the post from Notion, picks colours and layout so the new card differs from its neighbours in the blog gallery, generates both images with the OpenAI Images API, uploads them to the post's Notion page and refreshes the page through the Super MCP server. Keeps the chosen style and a log of every cover on a "Blog cover style" page in Notion, so all future covers match. Use when someone wants a cover, thumbnail, preview or header image for a blog post on their Super site, wants all blog covers to look consistent, or wants covers made automatically for new posts. Do not use for images inside the post body, logos, social media graphics with text, or sites not built with Super.
---
# Blog covers for a Super site
Two images per post:
| Image | Size | Where it shows |
|---|---|---|
| preview | `1632x960` (1.7:1) | the card in the blog gallery |
| header | `2400x800` (3:1) | the page cover at the top of the post, and the link preview when the post is shared |
The look is fixed so every cover belongs to the same family; only the colours (from the site) and the motif (from the post) change. Read `references/style.md` once per session.
**Needs:** the Super MCP server (`https://mcp.super.so/mcp`), the Notion MCP server, a code tool that can run `curl` (Claude Code, or Claude with code execution allowed to reach `api.openai.com` and `api.notion.com`), and an OpenAI API key of a verified organisation in the environment variable `OPENAI_API_KEY`. Where there is no environment (Claude apps), ask the user for the key once per conversation and pass it only inside the `curl` command. Never print the key, repeat it or write it to a file. One post costs about 7 US cents (about 4 for the preview, 3 for the header).
**Autonomy.** After the style is set up (Step 1), the skill asks nothing: it picks colours, tone and layout, generates, checks, publishes and reports with both images attached. The user steers it only by naming a scheme, a layout or a motif.
## Step 1 - Find the blog and the style
1. Super MCP `find_site` with the user's domain. The blog is a Notion database shown on a page of the site (usually `/blog`). `describe_page` on that page and `notion-fetch` on the database give: the data source, the post properties, and **where the gallery takes its card image from** - the gallery view's cover is either `page_cover` (the page cover) or a files property (e.g. `Cover`, `Thumbnail`). Note it; Step 5 depends on it.
2. Look for a Notion page called **Blog cover style** next to the blog database (Notion `search`). If it exists, read it: palette, tones, the custom style lines, and the log table. Go to Step 2.
3. If it does not exist, set the style up once:
- **Colours.** `describe_design` gives the theme's background, text and accent colours, but on many sites the accent is just the text colour and the real brand colours live in the custom code. Also read the site's CSS: `get_code` (style and head slots), and any stylesheet linked from the head (`curl` it) - take the colours defined as CSS variables or used most often. Pick one accent for the brand scheme and up to three more brand colours that may appear as small details. Build the three schemes in `references/style.md` (brand, light, dark) from them.
- **Existing covers.** Look at the images the gallery already shows (`preview_site` of the blog page). If they share a look of their own (flat illustration, outlines, photos, a mascot), describe it in two or three extra style lines that win over the general style ("thick ink outlines and hard offset shadows like the site's cards; flat fills with a fine dot pattern; a small friendly cartoon dog may appear"), so the new covers sit well next to the old ones.
- **Is the header shown?** `describe_design` `layout.pageHeaders` false (or a post page without a cover strip in `preview_site`) means the post pages do not show the page cover. Tell the user the header is then used only for link previews when the post is shared, and ask whether to keep making it or make the preview only.
- Generate **one** preview for the newest post in the brand scheme (Steps 2 to 4), show it to the user and ask: keep it, use the light or dark scheme as default, or describe changes in words ("more contrast", "no perspective", "rounded softer panels"). Write accepted changes as extra style lines.
- Create the **Blog cover style** page next to the blog database with: the three palette blocks, the default scheme, the extra style lines, and an empty log table `Date | Post | Scheme | Layout | Signature | Status`.
## Step 2 - Read the post and choose the look
1. `notion-fetch` the post: title, description, body. Pull out the one thing the post is about, as a piece of user interface or a familiar object: a calendar, a checkout, a search field, a map pin, a chart, a padlock, a megaphone.
2. Find the neighbours: the gallery shows the newest posts first, usually three per row. A new post goes to position 1, so its neighbours are the posts now at positions 1 and 3 (right of it and below it). Read their scheme and layout from the log.
3. Choose, unless the user named them:
- **Scheme**: the default scheme about half the time, the other two otherwise; never the same scheme as a neighbour when another is possible.
- **Layout**: `A`, `B` or `C` from `references/layouts.md`, not a neighbour's layout.
4. Write the motif as JSON (examples in `references/motif-examples.md`):
- `hero`: the main panel in two or three sentences, as UI geometry, with one accent-coloured detail.
- `signature`: one large flat monochrome glyph on the main panel - the thing that identifies the post at card size. Brands only as black or white silhouettes.
- `scene`: one supporting panel, frosted, at an edge, cut off.
- `counterweight`: exactly one solid shape (wedge, pill, triangle) in the ink colour and where it sits.
- `header`: `hero`, `scene` and `counterweight` rewritten as a wide band - everything side by side on the horizontal centre line, nothing important in the outer fifth of the width or near the top and bottom edges.
5. Reject and rewrite the motif if it mentions text, letters, numbers, people, photos, 3D, a colour outside the scheme, or more than one counterweight shape.
## Step 3 - Assemble the prompts
Take `references/cover-prompt.txt` and `references/header-prompt.txt` and replace every `{…}`: `{PALETTE}` with the scheme block from the style page, `{STYLE_EXTRA}` with the extra style lines (or nothing), `{HERO}`, `{SIGNATURE}`, `{SCENE}`, `{COUNTERWEIGHT}`, and `{LAYOUT}` (cover only) with the layout text. No `{` may remain.
## Step 4 - Generate and check
One call per image:
~~~bash
jq -n --arg p "$(cat cover.prompt.txt)" \
'{model:"gpt-image-2.5-sunburst", prompt:$p, n:1, size:"1632x960", quality:"high", output_format:"png"}' \
| curl -sS https://api.openai.com/v1/images/generations \
-H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d @- > cover.json
jq -r '.data[0].b64_json' cover.json | base64 -d > preview.png
~~~
The header uses `header.prompt.txt`, `size:"2400x800"` and `header.png`. If the model name is refused, use the newest `gpt-image` model the account lists.
Look at both images. Regenerate (at most twice per image, then simplify the motif) only for a defect: any text or letters, a colour outside the scheme, a logo in brand colours, the signature glyph missing or cut, a light background in the dark scheme or the reverse. For the header, also look at a centred 6:1 strip and a centred phone-width window (crop with any image tool): the signature must be whole in both.
## Step 5 - Publish
The best setup is a gallery whose card image comes from a files property (e.g. `Cover`): the preview goes there, the header becomes the page cover. If the gallery uses the page cover instead, tell the user once that the card and the header then share one image, and offer the switch (Notion: gallery view → Layout → Card preview → the files property; add a Files property `Cover` first). Until they switch, publish the header only, as the page cover; the card shows its centre.
1. Upload both PNGs with Notion MCP `create-file-upload`, then `curl -X POST <upload_url> -H "authorization: <upload header>" -F "file=@preview.png;type=image/png"` (and the same for the header). The answer must say `uploaded`.
2. `update-page` with the files property set to two `file_upload` items, the preview first and the header second (the gallery shows only the first).
3. Super MCP `sync_page` for the post's path, then for the blog page. Super copies Notion files to its CDN on the post sync.
4. Fetch the post's live URL with a cache-busting query and find the CDN copy of the header by its file name (poll for up to two minutes).
5. One `update-page`: `cover` = that CDN URL, the files property = the preview only. `sync_page` the post again.
6. Add a row to the log on the **Blog cover style** page.
## Step 6 - Check and report
Open the blog page and the post (Super MCP `preview_site`, desktop and width 390): the card shows the preview, the header strip shows the signature whole, the card differs from its neighbours. Report: the post, the live URL, scheme and layout and why, the cost, and both images. Offer a regeneration with a named scheme, layout or motif.
## Pitfalls
- The Notion MCP sets a page cover only from a public URL, so the header goes through the site's CDN copy (Step 5.4). A signed `file.notion.so` / `prod-files-secure` URL expires within the hour.
- Sync the post before the blog page; the other order leaves the card pointing to an expired Notion file.
- Image models misspell words, so no text ever goes into the image; the gallery prints the title under the card anyway.
- A free Super site shows the covers too (they are Notion content, not custom code).