Install
$ agentstack add skill-widnyana-eyay-toolkits-cover-image ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Cover Image Generator
Generate blog cover images and Open Graph/social preview images as PNG files. Each cover is a self-contained HTML document with inline CSS, captured as a screenshot via Chrome headless at exactly 1200x630 pixels.
The output is a static PNG suitable for Hugo front matter (image:), HTML ``, and Twitter card metadata. No external images, no JavaScript, no server-side rendering required at capture time.
Overview
Cover images serve as the primary visual identity for a blog post across social platforms, search results, and link previews. Each image is designed from scratch per post, reflecting the topic, tone, and key concepts of the content.
What this skill produces:
- A 1200x630px PNG file rendered from HTML+CSS
- Self-contained HTML with no external image dependencies
- Typography-driven design with CSS decorative elements
- Consistent branding placement
When to use this skill:
- Blog posts need an OG/social preview image
- Hugo front matter needs an
image:field - A series of posts need visually cohesive covers
- Existing covers need updating or redesigning
Detailed Workflow
Step 1: Read the source content
Read the blog post or article to extract the title, key concepts, and overall tone. The cover image must accurately represent the content. Identify:
- The exact title (or a shortened version if it exceeds 40 characters)
- The primary topic category (technical, tutorial, explanatory, announcement)
- Key visual metaphors or concepts from the content
- Whether the post is part of a series (affects series label placement)
- The desired output file path
If the user provides only a title without a file path, ask for the target output location before proceeding.
Step 2: Determine the visual direction
Select a design approach based on the post topic and tone:
- Technical posts (programming, infrastructure, security, blockchain): dark background with bold typography and accent gradients. Conveys depth and technical rigor.
- Tutorial/guide posts (how-to, step-by-step, beginner): light background with clean layout and structured visual hints. Conveys clarity and approachability.
- Conceptual/explanatory posts (architecture, design patterns, theory): gradient background with centered typography. Conveys breadth and sophistication.
- Announcement posts (new feature, series launch, milestone): bold accent colors with prominent typography. Conveys energy and importance.
Consult references/cover-design.md for the full color palette and typography specifications for each direction.
Step 3: Design the HTML+CSS
Create a complete, self-contained HTML file. All styles must be inline within a ` block. No external stylesheets, no tags (except Google Fonts via @import`), no external images, and no JavaScript.
Hard constraints:
- Canvas dimensions: exactly 1200x630px set on
body overflow: hiddenon body to prevent scroll artifacts- Max 2 fonts: one display font for titles, one sans-serif for metadata
- Google Fonts loaded via
@import url(...)inside the `` block - All decorative elements created with CSS (gradients, shapes, transforms)
- No `
tags, nobackground-image: url(...)` pointing to external files
See the HTML boilerplate section below for a complete starting template.
Step 4: Write to a temp file
Save the HTML to a temporary location. Use the project's tmp/ directory:
tmp/cover-.html
Derive the slug from the post title (lowercase, hyphens, max 30 characters). Create the tmp/ directory if it does not exist. Writing to tmp/ keeps generated HTML separate from source content and makes cleanup straightforward.
Step 5: Capture the screenshot
Run the screenshot script to render the HTML to PNG:
bash scripts/screenshot.sh tmp/cover-.html /cover.png
The script handles Chrome headless invocation with the correct flags (--headless=new, --disable-gpu, --no-sandbox, --hide-scrollbars). It outputs the PNG at the specified path.
Important: Run the script from the skill directory so that scripts/screenshot.sh resolves correctly, or use an absolute path to the script.
Step 6: Verify the output
Read the generated PNG file to visually verify it rendered correctly. Check for:
- Title text is fully visible and not clipped
- Text is readable at half-size (simulate by checking overall layout density)
- Decorative elements are positioned correctly (not overlapping critical text)
- Colors render as specified (Chrome may handle some CSS differently)
- No white/blank areas where content should be
- Safe margins are respected (no text too close to edges)
If the image does not look correct, adjust the HTML and re-run the screenshot. Common fixes are in the troubleshooting section below.
Step 7: Clean up
After confirming the PNG renders correctly, delete the temp HTML file:
rm tmp/cover-.html
Do not leave temp HTML files in the repository. If the tmp/ directory is now empty, remove it as well.
Step 8: Integrate with the blog post
Add the cover image to the blog post front matter:
---
title: "Post Title"
image: /images/category/cover.png
---
Copy or move the PNG to the appropriate static images directory for the blog. The exact path depends on the blog's static file structure.
HTML Boilerplate
Use this template as the starting point for every cover image. It includes the correct dimensions, font loading, layout zones, and branding placement.
Dark Variant Template
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&family=JetBrains+Mono:wght@400;700&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 1200px;
height: 630px;
overflow: hidden;
font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif;
background: #0f172a;
color: #f8fafc;
position: relative;
}
/* Background decoration */
.bg-circle {
position: absolute;
border-radius: 50%;
opacity: 0.06;
}
.bg-circle-1 {
width: 600px;
height: 600px;
background: linear-gradient(135deg, #6366f1, #8b5cf6);
top: -200px;
right: -100px;
}
.bg-circle-2 {
width: 400px;
height: 400px;
background: linear-gradient(135deg, #06b6d4, #3b82f6);
bottom: -150px;
left: -50px;
}
/* Layout */
.cover {
position: relative;
z-index: 1;
padding: 60px 80px;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
/* Series label */
.series {
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1.5px;
color: #818cf8;
margin-bottom: 20px;
}
/* Title */
.title {
font-size: 56px;
font-weight: 800;
line-height: 1.15;
max-width: 900px;
margin-bottom: 16px;
}
/* Subtitle */
.subtitle {
font-size: 22px;
font-weight: 400;
color: #94a3b8;
max-width: 700px;
line-height: 1.4;
}
/* Branding */
.branding {
position: absolute;
bottom: 24px;
right: 80px;
font-size: 14px;
color: #94a3b8;
font-weight: 500;
}
Series Label
Post Title Goes Here
Optional subtitle or tagline
widnyana.web.id
Light Variant Template
Replace the dark-specific styles:
body {
background: #ffffff;
color: #0f172a;
}
.bg-circle {
opacity: 0.04;
}
.series {
color: #3b82f6;
}
.subtitle {
color: #64748b;
}
.branding {
color: #64748b;
}
The structure remains identical. Only background, text, and accent colors change.
Design Rules
When to use dark vs light
| Topic Type | Background | Rationale | |------------|-----------|-----------| | Programming, Rust, Solidity | Dark (#0f172a) | Technical depth | | Infrastructure, DevOps, CI/CD | Dark (#0f172a) | Systems-level content | | Security, auditing | Dark (#0f172a) | Seriousness, gravity | | Blockchain, crypto, DeFi | Dark (#0f172a) | Industry convention | | Tutorials, guides, how-to | Light (#ffffff) | Approachable, clear | | Architecture, design patterns | Gradient | Breadth, sophistication | | Career, soft skills | Light (#ffffff) | Friendly, readable | | Announcements, launches | Bold gradient | Energy, prominence |
Font loading
Always load fonts via @import inside the ` block, not via in the head. This keeps the HTML truly self-contained and avoids rendering issues where Chrome headless may not wait for external ` resources.
Include only the weights actually used. Loading unused weights slows Chrome headless rendering:
/* Good: only needed weights */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700;800&display=swap');
/* Bad: loading all weights */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');
Dimensions and safe area
The full canvas is 1200x630px. Social platforms (Twitter, LinkedIn, Slack, Discord) may crop edges. Critical content (title text, series labels) must stay within the safe area:
- Safe area: 1040 x 510px centered within the canvas
- Left/right margin: minimum 80px
- Top/bottom margin: minimum 60px
- Branding: stays within safe area (bottom: 20-50px), uses solid muted colors with >= 5.5:1 contrast. Omit entirely when no branding is provided.
Visual element guidelines
Each cover must include at least one visual element beyond pure typography. Options:
- Gradient orbs: Large translucent circles positioned behind the text area. Use 2-3 orbs with low opacity (0.04-0.08) for depth.
- Accent bars: Thin horizontal or diagonal lines with gradient colors to add structure.
- Geometric shapes: Triangles, rotated squares, or hexagons as subtle background patterns.
- Code snippet visuals: For programming posts, a styled code block with syntax-colored text adds context.
- Grid/dot patterns: Repeating dot or line patterns using CSS
background-imagewithlinear-gradientfor technical posts.
All decorative elements must use position: absolute and sit behind text content via z-index. Never let decorations interfere with text legibility.
Common Issues and Troubleshooting
Chrome not found
Symptom: scripts/screenshot.sh exits with error: no Chrome/Chromium binary found in PATH.
Fix: Install Chrome or Chromium. The script searches for google-chrome-stable, google-chrome, chromium-browser, or chromium in that order. On Fedora: sudo dnf install chromium. On Ubuntu: sudo apt install chromium-browser. Verify with which google-chrome-stable.
Font not loading or rendering as fallback
Symptom: Title renders in Arial or Times New Roman instead of the specified Google Font.
Fixes:
- Verify the
@importURL is correct and the font name matches exactly (case-sensitive). - Ensure the
@importis the first rule inside `. CSS@import` must precede all other rules. - Add a small
font-display: swapparameter:&display=swapin the Google Fonts URL. - If the font still fails, fall back to a web-safe stack:
'Inter', 'Helvetica Neue', Arial, sans-serif.
Text clipped or overflowing
Symptom: Title or subtitle text is cut off at the bottom or right edge.
Fixes:
- Check that
overflow: hiddenis set onbody(this is intentional, but confirms clipping is happening). - Reduce font size if the title exceeds 2 lines at the current size.
- Increase
max-widthon the title element, but never exceed 1000px to preserve safe margins. - Shorten the title text for the cover. The cover title does not need to match the full post title exactly.
Image appears blank or white
Symptom: The output PNG is entirely white or appears empty.
Fixes:
- Verify the HTML file exists and is not empty before running the screenshot script.
- Check that
bodyhas an explicitbackgroundcolor set. Chrome headless defaults to white. - Ensure all content has
z-indexhigher than 0 if background elements are present. - Open the HTML file in a regular browser to confirm it renders correctly before blaming headless Chrome.
Colors look different from CSS values
Symptom: Gradient or background colors appear washed out or shifted compared to the CSS specification.
Fixes:
- Chrome headless renders in sRGB color space. If the display preview uses a wider gamut, colors may appear different.
- Avoid
color()orlab()CSS color functions. Use hex (#0f172a) orrgba()values only. - Verify the PNG is not being displayed at a different size than 1200x630 (scaling changes color perception).
Screenshot shows scrollbars or extra whitespace
Symptom: The PNG has a scrollbar or extra whitespace on the right or bottom.
Fixes:
- Confirm
overflow: hiddenis set onbody. - Add
margin: 0; padding: 0to bothhtmlandbodyvia the universal selector* { margin: 0; padding: 0; }. - The screenshot script passes
--hide-scrollbarsbut this may not suppress all scrollbar artifacts in all Chrome versions. The CSSoverflow: hiddenis the reliable fix.
Quick Reference
Cover Image Specifications
| Property | Value | |----------|-------| | Canvas size | 1200 x 630 px | | Safe area | 1040 x 510 px (centered) | | Format | PNG | | Min margins | 80px horizontal, 60px vertical | | Max fonts | 2 (display + body) | | External images | None (CSS only) | | JavaScript | None (static HTML+CSS) |
Output Locations
| Context | Typical Path | |---------|-------------| | Hugo blog | static/images//cover.png | | Temp HTML | tmp/cover-.html |
Color Palettes (Quick)
| Variant | Background | Primary Text | Secondary Text | Accent | |---------|-----------|-------------|---------------|--------| | Dark | #0f172a | #f8fafc | #94a3b8 | #6366f1 to #8b5cf6 | | Light | #ffffff | #0f172a | #64748b | #3b82f6 | | Gradient | #1e1b4b to #312e81 | #f8fafc | #a5b4fc | #818cf8 |
Workflow Checklist
- Read the post content
- Select dark/light/gradient direction
- Write self-contained HTML with inline CSS
- Save to
tmp/cover-.html - Run
bash scripts/screenshot.sh tmp/cover-.html .png - Read the PNG to verify rendering
- Delete temp HTML
- Add to blog front matter
Additional Resources
Local References
references/cover-design.md- Complete color palettes, typography scale, layout zones, and visual element specifications for cover imagesscripts/screenshot.sh- Chrome headless capture script that handles binary detection, viewport sizing, and output file management
Related Design Guides
For diagram and infographic styles used in other visual-gen skills, consult the architecture-diagram and process-infographic skill references.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: widnyana
- Source: widnyana/eyay-toolkits
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.