Description
Generate correctly-sized images for every social media platform. Add text with customizable font/size/color, background gradients or solid colors, logo overlays, and patterns. Solves the "what size is an OG image again?" problem — select a platform, customize, and download.
Features
- Platform presets with correct dimensions:
| Platform |
Preset |
Dimensions |
| Open Graph |
Link preview |
1200 × 630 |
| Twitter/X |
Summary Large Image |
1200 × 675 |
| Twitter/X |
Summary |
800 × 418 |
| Instagram |
Post (square) |
1080 × 1080 |
| Instagram |
Story / Reel |
1080 × 1920 |
| Instagram |
Landscape |
1080 × 566 |
| LinkedIn |
Post |
1200 × 627 |
| LinkedIn |
Cover |
1584 × 396 |
| Facebook |
Post |
1200 × 630 |
| Facebook |
Cover |
820 × 312 |
| YouTube |
Thumbnail |
1280 × 720 |
| YouTube |
Banner |
2560 × 1440 |
| Pinterest |
Pin |
1000 × 1500 |
| Discord |
Embed |
1200 × 675 |
| Twitch |
Offline Banner |
1920 × 1080 |
| Custom |
User-defined |
W × H |
- Text layers:
- Multiple text blocks, each independently positioned
- Font family: system-ui, serif, monospace, or Google Fonts (top 20 loaded on demand)
- Font size: auto-scale or manual (px)
- Font weight: light, regular, bold, black
- Color picker with opacity
- Text alignment: left, center, right
- Text shadow: color, blur, offset
- Letter spacing and line height
- Text transform: uppercase, lowercase, capitalize
- Max width with word wrap
- Background options:
- Solid color
- Linear gradient (angle + 2–4 stops)
- Radial gradient
- Mesh gradient (4-point gradient)
- Image upload (with fit/fill/cover modes, blur/darken overlay)
- Patterns: dots, grid, diagonal lines, noise, waves (SVG-based overlays)
- Logo/Image overlay:
- Drop a logo PNG/SVG, position anywhere
- Resize with aspect ratio lock
- Opacity control
- Corner presets: top-left, top-right, bottom-left, bottom-right, center
- Shape elements:
- Rectangles, circles, lines (decorative elements)
- Color, opacity, border
- Templates — Pre-designed layouts:
- Blog post header (title + subtitle + gradient)
- Product launch (centered text + badge)
- Quote card (large text + attribution)
- Event announcement (date + title + location)
- Minimalist (text + solid background)
- Safe zone guides — Show where text might get cropped on different platforms
- Export: PNG, JPEG (quality slider), WebP
Implementation
Dependencies
Zero — Canvas API for all rendering.
Core Logic
interface ImageConfig {
width: number;
height: number;
background: Background;
layers: Layer[];
}
type Background =
| { type: 'solid'; color: string }
| { type: 'linear-gradient'; angle: number; stops: { color: string; position: number }[] }
| { type: 'radial-gradient'; stops: { color: string; position: number }[] }
| { type: 'image'; src: string; fit: 'cover' | 'contain' | 'fill'; overlay?: string }
| { type: 'pattern'; pattern: 'dots' | 'grid' | 'lines' | 'noise'; color: string; opacity: number };
type Layer =
| { type: 'text'; text: string; x: number; y: number; font: FontConfig; maxWidth?: number; align: string }
| { type: 'image'; src: HTMLImageElement; x: number; y: number; width: number; height: number; opacity: number }
| { type: 'shape'; shape: 'rect' | 'circle' | 'line'; x: number; y: number; width: number; height: number; fill: string; opacity: number };
async function renderImage(config: ImageConfig): Promise<HTMLCanvasElement> {
const canvas = document.createElement('canvas');
canvas.width = config.width;
canvas.height = config.height;
const ctx = canvas.getContext('2d')!;
// 1. Background
drawBackground(ctx, config.width, config.height, config.background);
// 2. Pattern overlay (if applicable)
if (config.background.type === 'pattern') {
drawPattern(ctx, config.width, config.height, config.background);
}
// 3. Layers (ordered front-to-back)
for (const layer of config.layers) {
ctx.save();
switch (layer.type) {
case 'text':
drawTextLayer(ctx, layer);
break;
case 'image':
ctx.globalAlpha = layer.opacity;
ctx.drawImage(layer.src, layer.x, layer.y, layer.width, layer.height);
break;
case 'shape':
drawShape(ctx, layer);
break;
}
ctx.restore();
}
return canvas;
}
function drawTextLayer(ctx: CanvasRenderingContext2D, layer: TextLayer): void {
ctx.font = `${layer.font.weight} ${layer.font.size}px ${layer.font.family}`;
ctx.fillStyle = layer.font.color;
ctx.textAlign = layer.align as CanvasTextAlign;
ctx.letterSpacing = `${layer.font.letterSpacing ?? 0}px`;
if (layer.font.shadow) {
ctx.shadowColor = layer.font.shadow.color;
ctx.shadowBlur = layer.font.shadow.blur;
ctx.shadowOffsetX = layer.font.shadow.offsetX;
ctx.shadowOffsetY = layer.font.shadow.offsetY;
}
// Word wrap
if (layer.maxWidth) {
const lines = wrapText(ctx, layer.text, layer.maxWidth);
lines.forEach((line, i) => {
ctx.fillText(line, layer.x, layer.y + i * layer.font.size * (layer.font.lineHeight ?? 1.4));
});
} else {
ctx.fillText(layer.text, layer.x, layer.y);
}
}
function drawPattern(ctx: CanvasRenderingContext2D, w: number, h: number, bg: PatternBackground): void {
ctx.globalAlpha = bg.opacity;
ctx.fillStyle = bg.color;
switch (bg.pattern) {
case 'dots':
for (let x = 0; x < w; x += 20) for (let y = 0; y < h; y += 20) {
ctx.beginPath(); ctx.arc(x, y, 1.5, 0, Math.PI * 2); ctx.fill();
}
break;
case 'grid':
ctx.lineWidth = 0.5; ctx.strokeStyle = bg.color;
for (let x = 0; x < w; x += 30) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, h); ctx.stroke(); }
for (let y = 0; y < h; y += 30) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(w, y); ctx.stroke(); }
break;
case 'lines':
ctx.lineWidth = 0.5; ctx.strokeStyle = bg.color;
for (let i = -h; i < w + h; i += 15) { ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i + h, h); ctx.stroke(); }
break;
}
ctx.globalAlpha = 1;
}
Platform Presets
const PRESETS: Record<string, { name: string; width: number; height: number; category: string }> = {
'og': { name: 'Open Graph', width: 1200, height: 630, category: 'General' },
'twitter-large': { name: 'Twitter Large Image', width: 1200, height: 675, category: 'Twitter/X' },
'twitter-summary': { name: 'Twitter Summary', width: 800, height: 418, category: 'Twitter/X' },
'ig-post': { name: 'Instagram Post', width: 1080, height: 1080, category: 'Instagram' },
'ig-story': { name: 'Instagram Story', width: 1080, height: 1920, category: 'Instagram' },
'linkedin-post': { name: 'LinkedIn Post', width: 1200, height: 627, category: 'LinkedIn' },
'yt-thumb': { name: 'YouTube Thumbnail', width: 1280, height: 720, category: 'YouTube' },
// ... all presets
};
Privacy
All rendering via Canvas API. Images never leave the browser. Uploaded logos/backgrounds are processed locally only.
UI
- Preset bar (top): Platform buttons grouped by category, custom size input
- Canvas (center): Live preview at scaled size, click-to-select layers, drag to reposition
- Layer panel (right):
- Add Text / Add Image / Add Shape buttons
- Layer stack with reorder, visibility toggle, delete
- Selected layer properties (font, color, position, size, opacity)
- Background panel: Tabs for Solid / Gradient / Image / Pattern
- Templates drawer: Pre-designed template thumbnails, click to apply
- Export bar (bottom): PNG / JPEG (quality) / WebP buttons, dimensions displayed
- Safe zone toggle: Show/hide cropping guides
- Responsive — canvas scales down on mobile, panels become tabs
Files to Create/Modify
| File |
Purpose |
tools/social-image/package.json |
Workspace package |
tools/social-image/src/renderer.ts |
Canvas rendering engine, text wrapping, patterns |
tools/social-image/src/presets.ts |
Platform dimension presets |
tools/social-image/src/templates.ts |
Pre-designed template configs |
tools/social-image/src/tool.ts |
Public API: renderImage, export functions |
tools/social-image/src/page.ts |
Canvas editor, layer panel, preset bar |
tools/social-image/src/meta.ts |
ToolMeta |
tools/social-image/src/index.ts |
Exports |
tools/social-image/tests/renderer.unit.test.ts |
Dimension accuracy, text wrapping, pattern generation |
tools/social-image/tests/presets.unit.test.ts |
Preset dimension validation |
tools/social-image/tests/page.unit.test.ts |
DOM rendering tests |
src/index.ts |
Register route |
src/index.html |
Add to tool grid |
Description
Generate correctly-sized images for every social media platform. Add text with customizable font/size/color, background gradients or solid colors, logo overlays, and patterns. Solves the "what size is an OG image again?" problem — select a platform, customize, and download.
Features
Implementation
Dependencies
Zero — Canvas API for all rendering.
Core Logic
Platform Presets
Privacy
All rendering via Canvas API. Images never leave the browser. Uploaded logos/backgrounds are processed locally only.
UI
Files to Create/Modify
tools/social-image/package.jsontools/social-image/src/renderer.tstools/social-image/src/presets.tstools/social-image/src/templates.tstools/social-image/src/tool.tstools/social-image/src/page.tstools/social-image/src/meta.tstools/social-image/src/index.tstools/social-image/tests/renderer.unit.test.tstools/social-image/tests/presets.unit.test.tstools/social-image/tests/page.unit.test.tssrc/index.tssrc/index.html