HTML-to-Image Design Delivery
Use this skill when the user asks for a visual design deliverable (magazine cover, poster, social graphic, flyer, quote card, announcement visual) and image generation tools (FAL, Higgsfield, etc.) are unavailable, unconfigured, or inappropriate for the task.
The technique: build the design as a self-contained HTML page, then screenshot it with Playwright to deliver a PNG image to the user.
When To Use
- User sends a photo (selfie, portrait, product shot) and asks "make this a magazine cover" / "turn this into a poster" / "make it look like [Forbes/Time/Vogue/etc.]"
- Any fixed-size editorial layout with text overlays on a photo
- Branded quote cards, announcements, social media graphics
- Fixed-size banners where HTML precision is easier than prompt-only image gen
- Image gen is not configured (FAL_KEY missing, no Higgsfield account, etc.)
When NOT To Use
- The user wants a generic text-to-image (no specific brand layout) — let them know image gen is unconfigured first
- The deliverable needs to be interactive or animated (use plain HTML delivery instead)
- A video or reel is needed (use branded-reel-pipeline or short-form-video-production)
The Workflow
1. Build the HTML artifact
Create a self-contained HTML file with:
User photo embedded as base64 data URI — encode the image first:
import base64
with open('photo.jpg', 'rb') as f:
b64 = base64.b64encode(f.read()).decode()
Then in HTML: <img src="data:image/jpeg;base64,{b64}">
CSS overlays and gradients — use position: absolute overlay divs with background gradients (e.g., linear-gradient(180deg, rgba(0,0,0,0.55) 0%, ... rgba(0,0,0,0.4) 100%)) so text stays readable over the photo.
Typographic treatment — use Google Fonts for brand-relevant typography (Playfair Display for editorial/Forbes-style serif, Inter for modern sans). Import via @import url(...) in CSS.
Fixed dimensions — wrap everything in a container div with exact pixel dimensions matching the intended output (e.g., width: 720px; height: 1280px for portrait magazine covers).
All visual elements as CSS — mastheads, accent bars, cover lines, barcodes, diamonds, price tags, taglines. No images needed except the user photo.
2. Serve locally (required for base64 images)
Browser security blocks file:// protocol from loading base64 images in some environments. Always serve via HTTP:
python3 -m http.server <port> --bind 127.0.0.1
Run this in the directory containing your HTML file.
3. Screenshot with Playwright
Install Playwright in a temp directory:
mkdir -p /tmp/screenshot && cd /tmp/screenshot
npm init -y && npm install playwright
Create a screenshot script:
const { chromium } = require('playwright');
(async () => {
const b = await chromium.launch();
const p = await b.newPage({ viewport: { width: 720, height: 1280 } });
await p.goto('http://127.0.0.1:<port>/<file>.html', {
waitUntil: 'networkidle',
timeout: 15000
});
await p.screenshot({ path: '/output/path.png', fullPage: true });
await b.close();
console.log('DONE');
})();
Run it: node screenshot.js
4. Deliver the image
Send the resulting PNG to the user via MEDIA:/absolute/path/to/output.png.
5. Clean up
- Kill the HTTP server
- Remove temp npm install directory
Magazine Cover Templates
Forbes-style layout
- Masthead: Playfair Display, 900 weight, ~72px, letter-spacing 14px, white with text-shadow
- Subhead: "The Creator Economy Issue" or similar, Inter 300, 11px, letter-spacing 6px
- Red accent bar: 80px wide, 2px height, #e60000
- Diamond shape: 14x14px rotated 45deg with 2px white border
- Top cover line: "EXCLUSIVE · [MONTH YEAR]" in small caps
- Main headline: Inter 900, 58px, white, -1px letter-spacing — punchy, aspirational
- Subheadline: Inter 300, 22px, semi-transparent white
- Cover lines: 3-4 bullet-style lines on bottom-left, white, ~16px
- Barcode area: repeating-linear-gradient barcode, "$7.99 US/CAN" price tag
- Tagline bottom-left: "forbes.com · @handle"
General layout rules
- 720x1280px portrait (standard phone-screen portrait ratio)
- Gradient overlay: dark at top (for logo visibility) → semi-transparent middle → dark at bottom (for text readability)
- Center author photo as main cover image
- Light text on the dark overlay
- Use
box-shadow on the cover itself for a physical magazine feel
Pitfalls
- Always serve via HTTP — file:// with base64 images causes blank renders in headless browsers.
- Match viewport to output — set
{ viewport: { width, height } } to the exact pixel dimensions of the intended output.
- Use
waitUntil: 'networkidle' — ensures Google Fonts and images fully load before the screenshot fires.
- Check the Playwright install path — Playwright chromium needs to be downloaded first (
npx playwright install chromium). If that's already done in a system cache, npm install playwright picks it up automatically.
- Clean up after yourself — HTTP server and temp npm installs consume disk space.
- Let the user know image gen wasn't available and you used HTML→screenshot instead, so they understand why it's not a "real" magazine cover.
- Don't use too many Google Fonts — each import adds load time. Stick to 1-2 families max.===ME:content/html-to-image-design-delivery
1---2name: html-to-image-design-delivery-23description: Convert HTML design artifacts to image deliverables (PNG) when image generation APIs are unavailable. Covers magazine covers, posters, social graphics, and any fixed-size visual asset built as HTML and exported via Playwright screenshot.4---56# HTML-to-Image Design Delivery78Use this skill when the user asks for a **visual design deliverable** (magazine cover, poster, social graphic, flyer, quote card, announcement visual) and image generation tools (FAL, Higgsfield, etc.) are unavailable, unconfigured, or inappropriate for the task.910The technique: build the design as a self-contained HTML page, then screenshot it with Playwright to deliver a PNG image to the user.1112## When To Use1314- User sends a photo (selfie, portrait, product shot) and asks "make this a magazine cover" / "turn this into a poster" / "make it look like [Forbes/Time/Vogue/etc.]"15- Any fixed-size editorial layout with text overlays on a photo16- Branded quote cards, announcements, social media graphics17- Fixed-size banners where HTML precision is easier than prompt-only image gen18- Image gen is not configured (FAL_KEY missing, no Higgsfield account, etc.)1920## When NOT To Use2122- The user wants a generic text-to-image (no specific brand layout) — let them know image gen is unconfigured first23- The deliverable needs to be interactive or animated (use plain HTML delivery instead)24- A video or reel is needed (use branded-reel-pipeline or short-form-video-production)2526## The Workflow2728### 1. Build the HTML artifact2930Create a self-contained HTML file with:3132- **User photo embedded as base64 data URI** — encode the image first:33 ```python34 import base6435 with open('photo.jpg', 'rb') as f:36 b64 = base64.b64encode(f.read()).decode()37 ```38 Then in HTML: `<img src="data:image/jpeg;base64,{b64}">`3940- **CSS overlays and gradients** — use `position: absolute` overlay divs with background gradients (e.g., `linear-gradient(180deg, rgba(0,0,0,0.55) 0%, ... rgba(0,0,0,0.4) 100%)`) so text stays readable over the photo.4142- **Typographic treatment** — use Google Fonts for brand-relevant typography (Playfair Display for editorial/Forbes-style serif, Inter for modern sans). Import via `@import url(...)` in CSS.4344- **Fixed dimensions** — wrap everything in a container div with exact pixel dimensions matching the intended output (e.g., `width: 720px; height: 1280px` for portrait magazine covers).4546- **All visual elements as CSS** — mastheads, accent bars, cover lines, barcodes, diamonds, price tags, taglines. No images needed except the user photo.4748### 2. Serve locally (required for base64 images)4950Browser security blocks file:// protocol from loading base64 images in some environments. Always serve via HTTP:5152```bash53python3 -m http.server <port> --bind 127.0.0.154```5556Run this in the directory containing your HTML file.5758### 3. Screenshot with Playwright5960Install Playwright in a temp directory:6162```bash63mkdir -p /tmp/screenshot && cd /tmp/screenshot64npm init -y && npm install playwright65```6667Create a screenshot script:6869```js70const { chromium } = require('playwright');71(async () => {72 const b = await chromium.launch();73 const p = await b.newPage({ viewport: { width: 720, height: 1280 } });74 await p.goto('http://127.0.0.1:<port>/<file>.html', {75 waitUntil: 'networkidle',76 timeout: 1500077 });78 await p.screenshot({ path: '/output/path.png', fullPage: true });79 await b.close();80 console.log('DONE');81})();82```8384Run it: `node screenshot.js`8586### 4. Deliver the image8788Send the resulting PNG to the user via `MEDIA:/absolute/path/to/output.png`.8990### 5. Clean up9192- Kill the HTTP server93- Remove temp npm install directory9495## Magazine Cover Templates9697### Forbes-style layout98- **Masthead**: Playfair Display, 900 weight, ~72px, letter-spacing 14px, white with text-shadow99- **Subhead**: "The Creator Economy Issue" or similar, Inter 300, 11px, letter-spacing 6px100- **Red accent bar**: 80px wide, 2px height, #e60000101- **Diamond shape**: 14x14px rotated 45deg with 2px white border102- **Top cover line**: "EXCLUSIVE · [MONTH YEAR]" in small caps103- **Main headline**: Inter 900, 58px, white, -1px letter-spacing — punchy, aspirational104- **Subheadline**: Inter 300, 22px, semi-transparent white105- **Cover lines**: 3-4 bullet-style lines on bottom-left, white, ~16px106- **Barcode area**: repeating-linear-gradient barcode, "$7.99 US/CAN" price tag107- **Tagline bottom-left**: "forbes.com · @handle"108109### General layout rules110- 720x1280px portrait (standard phone-screen portrait ratio)111- Gradient overlay: dark at top (for logo visibility) → semi-transparent middle → dark at bottom (for text readability)112- Center author photo as main cover image113- Light text on the dark overlay114- Use `box-shadow` on the cover itself for a physical magazine feel115116## Pitfalls117118- **Always serve via HTTP** — file:// with base64 images causes blank renders in headless browsers.119- **Match viewport to output** — set `{ viewport: { width, height } }` to the exact pixel dimensions of the intended output.120- **Use `waitUntil: 'networkidle'`** — ensures Google Fonts and images fully load before the screenshot fires.121- **Check the Playwright install path** — Playwright chromium needs to be downloaded first (`npx playwright install chromium`). If that's already done in a system cache, `npm install playwright` picks it up automatically.122- **Clean up after yourself** — HTTP server and temp npm installs consume disk space.123- **Let the user know** image gen wasn't available and you used HTML→screenshot instead, so they understand why it's not a "real" magazine cover.124- **Don't use too many Google Fonts** — each import adds load time. Stick to 1-2 families max.===ME:content/html-to-image-design-delivery