| name | blog |
| description | Write a new LLM Gateway blog post in the house style, draft the prose with the copywriting skill, and generate its OpenGraph image with gpt-image-2. Use when the user says "blog", "blog post", "write a blog post", "draft a blog", "add a blog post", "publish a blog", or "write an article" for the marketing site. For shipped-feature release notes use the `changelog` skill instead. |
Blog
Write a public blog post for LLM Gateway, in the house style, with the prose drafted/polished by the copywriting skill, and generate its OpenGraph image with gpt-image-2.
This skill is the blog counterpart of the changelog skill. The difference: blog posts are longer SEO/marketing content (guides, comparisons, announcements, engineering deep-dives) rather than short release notes, the prose is run through the copywriting skill, and the image is generated here (not just handed off as a prompt).
What you need first
Before writing, understand the topic concretely. Never invent prices, limits, capabilities, or quotes.
- If the post documents a feature, read the relevant docs page under
apps/docs/content/ and inspect the shipping PR/commit (git show <sha> --stat, then the changed UI/API/gateway files) to confirm exact behavior, field names, error codes, and plan gating (free vs Pro vs Enterprise).
- If it's a comparison or guide, gather the concrete facts you'll cite (real numbers, real provider names, real endpoints).
- Decide the primary SEO keyword/phrase the post should rank for (e.g. "API key rotation", "LLM orchestration"). It belongs in the title, the summary, an early paragraph, and at least one
## header.
Where entries live
- Entries:
apps/ui/src/content/blog/<YYYY-MM-DD>-<kebab-slug>.md
- Images:
apps/ui/public/blog/<kebab-slug>.png
- Schema is enforced by
apps/ui/content-collections.ts. Required: id, slug, date, title, summary. Optional: draft, categories (defaults []), image (src/alt/width/height).
Step 1 — Pick the date, id, slug, categories
Step 2 — Draft the prose with the copywriting skill
Invoke the copywriting skill (via the Skill tool) to draft and tighten the body copy. Give it: the topic, the primary keyword, the target reader, the key facts you gathered, and the LLM Gateway voice notes below. Iterate on its output, then drop the result into the markdown body.
Read the two or three most recent files in apps/ui/src/content/blog/ before writing and mirror their structure and tone.
House style (match existing posts)
- Lead with the problem, then the fix. Open by naming the pain concretely; then state what LLM Gateway does about it. Bold the product name once: LLM Gateway.
- Benefits over features, specific over vague. Real numbers, real endpoints, real provider names. No "seamless", "revolutionary", "streamline".
- Confident and plain. Active voice, short paragraphs, no exclamation points, no "very/really/simply".
- Scannable structure.
## section headers (verb-led or outcome-led), bullets and tables for options/comparisons, fenced code blocks for any curl/JSON/diff example. Use https://api.llmgateway.io/v1/... and $LLM_GATEWAY_API_KEY in API examples.
- State plan gating explicitly when a capability is gated.
- SEO conventions (this is the main difference from changelog): work the primary keyword into the title, the
summary, the first 1–2 paragraphs, and a header. Add a short "Frequently Asked Questions" section with 2–4 ### question headers near the end (these target long-tail queries). Link to related internal posts/docs with root-relative links (e.g. /blog/soc2-type-ii, https://docs.llmgateway.io/...).
- Close with a CTA block: 2–3 bullets linking to signup, the relevant docs, and one related post — e.g.
**[Try LLM Gateway free](https://llmgateway.io/signup)**.
- Plain Markdown only — no MDX/JSX components.
Frontmatter
---
id: "blog-<slug>"
slug: "<slug>"
date: "<YYYY-MM-DD>"
title: "<Title with the primary keyword, ~4–9 words>"
summary: "<1–3 sentences with the keyword: the problem, what shipped/what the reader learns, and the plan if gated. This is the OG description and the listing blurb.>"
categories: ["<Category>"]
image:
src: "/blog/<slug>.png"
alt: "<Descriptive alt text including the concept the image shows>"
width: 1536
height: 1024
---
<body — the copywriting-skill output>
Step 3 — Generate the OpenGraph image with gpt-image-2
The image is an abstract, on-brand illustration with no text — AI-rendered text and logos are unreliable, and the title already lives on the page. (If the user instead wants a branded card with the headline/logo baked in, render it with the repo's next/og template system — see apps/ui/src/lib/og.tsx for the brand spec — rather than gpt-image-2.)
Resolution. Generate 1536×1024 (3:2 landscape). gpt-image-2 supports 1024x1024, 1536x1024, 1024x1536; landscape crops cleanly to the ~1.91:1 social card. Match image.width/height in the frontmatter to what you generate.
Write the prompt
A 2–4 sentence prompt in the house image style — a glossy 3D-rendered circuit-board scene, not a flat/minimal gradient backdrop:
- Set the scene: a dark navy computer circuit board in glossy 3D isometric perspective, with bright neon-teal light traces flowing across it toward a central raised chip.
- Put the post's concept at the center: a glowing element mounted on the central chip (concept over literalism — e.g. a glowing doorway for the gateway, a glowing rotating key for key rotation), surrounded by supporting glossy rounded 3D icons that fit the topic (chat bubbles, keys, charts, coins…) in vivid purple, lime green, and mint, each on small pedestals on the board.
- Add the render feel: subtle depth of field at the edges, soft reflections, premium 3D render, vibrant against the dark board.
- Reserves the top-left corner: include "the top-left corner is intentionally empty clean negative space, with no logo, no icon, no wordmark and no brand text there." The real logo is composited in afterward (see "Always composite the official logo" below), never drawn by the model.
- Ends with: "no logos, no UI chrome. Wide 3:2 landscape composition, 1536×1024." (If you want a branded card, you may keep a short headline/subtitle in the prompt — gpt-image-2 renders short text well — but never the logo.)
Generate it (LLM Gateway Images API, gpt-image-2)
Requires LLM_GATEWAY_API_KEY in the environment. Generate to a temp file first — the logo is composited in the next step:
curl -s https://api.llmgateway.io/v1/images/generations \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-image-2","size":"1536x1024","prompt":"<the prompt above, on one line>"}' \
| jq -r '.data[0].b64_json' | base64 -d > /tmp/<slug>-bg.png
View /tmp/<slug>-bg.png to confirm it's on-brand and the top-left is clear; regenerate with a tweaked prompt if not.
Always composite the official logo (never let gpt-image-2 draw it)
gpt-image-2 cannot reproduce the LLM Gateway logo — it hallucinates a wrong mark. So always overlay the real asset. Render the white wordmark lockup (apps/ui/public/brand/logo-with-name-white.svg) and composite it into the reserved top-left corner. Needs rsvg-convert and ImageMagick (magick):
rsvg-convert -h 84 apps/ui/public/brand/logo-with-name-white.svg -o /tmp/llmgw-logo.png
magick /tmp/<slug>-bg.png /tmp/llmgw-logo.png -geometry +72+72 -composite apps/ui/public/blog/<slug>.png
file apps/ui/public/blog/<slug>.png
View the final file to confirm the real logo sits cleanly in the top-left. (Use apps/ui/public/brand/logo-white.svg for just the icon mark if a wordmark doesn't fit the composition.)
If no key is available, fall back to handing off: output the prompt in a fenced block (keeping the "top-left empty" instruction) plus the two composite commands, and tell the user to generate the background and run the composite, dropping the result at apps/ui/public/blog/<slug>.png. The post builds fine without the file; the image just 404s until it exists.
Step 4 — Validate
pnpm format
turbo run build --filter=ui
pnpm format normalizes the markdown; the ui build fails if the frontmatter doesn't match the content-collections schema. Then commit (conventional commit, ≤50-char title), e.g. docs(blog): add api key rotation post.