Turn any screenshot into a beautiful, share-ready image in seconds. Free, open source, runs entirely in your browser.
See the codeShotcandy turns a plain screenshot into a share-ready image or video in seconds.
Free, open source, and it runs entirely in your browser. No account, no upload.
Every "after" below is a real export from Shotcandy's engine, one click from the plain screenshot on the left.
36 one-click styles in seven families (from your shot, fruity, pastel, paper, deep, wallpaper and device). Hover to preview, press G for the whole Candy Jar, or press S for Candy Shuffle, which re-rolls background, tilt and frame together. Styles that suit your screenshot come first, and "From your shot" builds a palette from the image itself. Save your own tweaks as presets.
Backgrounds cover solid colours, linear, radial and mesh gradients with an editor, 12 original wallpapers and your own images. Layout controls have named stops for padding, corners and shadow, plus borders, an inset plate, 3D tilt and position.
Turn a landscape screenshot into a tall post in one step. Pick a 9:16 story, a 4:5 portrait or any tall size and Shotcandy adds a headline and subhead above your screenshot, set in the brand's display type with ink or white picked to suit the background. Click the text on the canvas to edit it in place.
A macOS window, a browser (light or dark), and drawn phone, tablet and laptop frames. All vector, all drawn by us, no vendor artwork.
Text, arrows (straight or curved), highlight boxes and blur/pixelate for anything private. Annotations can stick to the screenshot or to the canvas, and every one is editable after the fact.
Eight motion presets (zoom in, focus, scroll, 3D sweep, float, drift, draw on, flip in) that loop seamlessly. Export MP4, WebM or GIF at up to 4K, rendered frame by frame by the same engine that draws your stills.
| ![]() |
Paste code, pick one of 8 themes with a matching background, highlight lines and set a filename. Syntax highlighting by Shiki across 27 languages, with auto-detect.
Type or paste a post or a quote and get a polished card: name, handle, avatar, stats or star rating, in light, cream, candy, dark or midnight. No third-party API involved.
Build a 3 to 10 slide set with headlines at Apple's exact sizes (iPhone 6.9", 6.5", 6.3", 5.5" and iPad), restyle every slide at once, and export the whole set as a ZIP.
Tell Shotcandy where the image is going (X, LinkedIn, Instagram, Product Hunt, a README, Slack and docs) and it picks the size, format and quality, then checks the file fits that platform's limit. Or choose any preset yourself: Open Graph 1200×630, X, LinkedIn, Instagram post and story, Product Hunt, App Store and free aspect ratios. PNG, JPEG or WebP at 1× to 4×, copy to the clipboard, or download with your own filename pattern.
Everything has a key. Press ? in the app for the full sheet.
| Action | Keys |
|---|---|
| Paste a screenshot | ⌘ V |
| Copy the image | ⌘ C |
| Download / export options | ⌘ S / ⌘ ⇧ S |
| Candy Shuffle | S |
| Candy Jar (all styles) | G |
| Previous / next style | [ ] |
| Cycle frames / padding | F / P |
| Text, arrow, highlight, blur | T A R B |
| Play or pause motion | M |
| Size menu | K |
Shotcandy is a static site. Your screenshots are decoded, rendered and encoded on your own device, in your browser, and are never uploaded anywhere. There are no accounts, no analytics and no server-side code. Recent designs, presets and uploaded backgrounds are kept in your browser's IndexedDB, and you can export any design as a .shotcandy project file to back it up or move it to another machine. After the page loads, the only network requests are for fonts.
You need Node 20.9 or newer and pnpm.
pnpm i && pnpm dev
Then open http://localhost:3000.
The production build is plain files. There is nothing to configure: no environment variables, no database, no API routes.
pnpm build # writes a fully static site to out/
pnpm serve # optional: preview out/ with the zero-dependency static server
Upload out/ to any static host: GitHub Pages, Netlify, Vercel, Cloudflare Pages, an S3 bucket or a plain nginx folder. URLs use trailing slashes, so no rewrite rules are needed.
The heart of Shotcandy is a small, deterministic rendering engine in src/engine, written in plain TypeScript with no React dependency. The same scene plus the same input always produces the same pixels, which is what makes previews, exports and animation frames agree exactly.
flowchart LR
A[Paste / drop / pick] --> B[Scene model<br>plain JSON]
P[Styles & presets] --> B
B --> C[Layout<br>sizes, fit, frames]
C --> D[Canvas renderer<br>layers to pixels]
D --> E[Live stage preview]
D --> F[Export worker<br>PNG · JPEG · WebP]
D --> G[Animation worker<br>frame by frame]
G --> H[MP4 · WebM · GIF]
B --> I[IndexedDB & .shotcandy files]
engine/scene): a JSON description of canvas, background, card, frame, annotations and optional animation. Undo, presets, project files and the UI all read and write it.engine/layout, engine/render, engine/frames): layers drawn onto an HTML canvas, including our own vector frames and shadows.engine/export): renders off the main thread in a worker, with size presets, scale factors and per-destination size limits.engine/animation): motion presets are functions of time over the same scene, encoded with WebCodecs plus mp4-muxer / webm-muxer, or gifenc for GIFs.engine/code, engine/post, engine/appstore): code images, post cards and App Store sets build ordinary scenes, so they get every style, frame and export for free.src/components, src/state): a Next.js static export with Tailwind. The editor store drives the engine; the engine never knows about React.pnpm test # Vitest: engine unit tests and headless render tests
pnpm test:e2e # Playwright: visual regression against committed baselines,
# export sizes, and app flows in Chromium, Firefox and WebKit
pnpm bench # export performance (budget: a 4K export in under 1.5 s)
pnpm typecheck && pnpm lint
To see every style on every sample screenshot at once, render the contact sheet:
CONTACT=1 pnpm vitest run tests/render/contact-sheet.test.ts
Issues and pull requests are welcome.
src/engine, and no clocks or unseeded randomness in anything that renders.pnpm test:e2e:update) and say so in the PR.brand/samples for demos and tests. Please don't add real product screenshots, logos or vendor device art.pnpm typecheck && pnpm lint && pnpm test before opening a PR.Shotcandy is free and always will be. If it saves you time, you can support the project with a one-off tip or a small monthly contribution.
MIT © 2026 Bilal Tahir
64 commits
TypeScript
79.2%
HTML
9.9%
CSS
9.2%
JavaScript
1.7%
Turn any screenshot into a beautiful, share-ready image in seconds. Free, open source, runs entirely in your browser.
See the codeShotcandy turns a plain screenshot into a share-ready image or video in seconds.
Free, open source, and it runs entirely in your browser. No account, no upload.
Every "after" below is a real export from Shotcandy's engine, one click from the plain screenshot on the left.
36 one-click styles in seven families (from your shot, fruity, pastel, paper, deep, wallpaper and device). Hover to preview, press G for the whole Candy Jar, or press S for Candy Shuffle, which re-rolls background, tilt and frame together. Styles that suit your screenshot come first, and "From your shot" builds a palette from the image itself. Save your own tweaks as presets.
Backgrounds cover solid colours, linear, radial and mesh gradients with an editor, 12 original wallpapers and your own images. Layout controls have named stops for padding, corners and shadow, plus borders, an inset plate, 3D tilt and position.
Turn a landscape screenshot into a tall post in one step. Pick a 9:16 story, a 4:5 portrait or any tall size and Shotcandy adds a headline and subhead above your screenshot, set in the brand's display type with ink or white picked to suit the background. Click the text on the canvas to edit it in place.
A macOS window, a browser (light or dark), and drawn phone, tablet and laptop frames. All vector, all drawn by us, no vendor artwork.
Text, arrows (straight or curved), highlight boxes and blur/pixelate for anything private. Annotations can stick to the screenshot or to the canvas, and every one is editable after the fact.
Eight motion presets (zoom in, focus, scroll, 3D sweep, float, drift, draw on, flip in) that loop seamlessly. Export MP4, WebM or GIF at up to 4K, rendered frame by frame by the same engine that draws your stills.
| ![]() |
Paste code, pick one of 8 themes with a matching background, highlight lines and set a filename. Syntax highlighting by Shiki across 27 languages, with auto-detect.
Type or paste a post or a quote and get a polished card: name, handle, avatar, stats or star rating, in light, cream, candy, dark or midnight. No third-party API involved.
Build a 3 to 10 slide set with headlines at Apple's exact sizes (iPhone 6.9", 6.5", 6.3", 5.5" and iPad), restyle every slide at once, and export the whole set as a ZIP.
Tell Shotcandy where the image is going (X, LinkedIn, Instagram, Product Hunt, a README, Slack and docs) and it picks the size, format and quality, then checks the file fits that platform's limit. Or choose any preset yourself: Open Graph 1200×630, X, LinkedIn, Instagram post and story, Product Hunt, App Store and free aspect ratios. PNG, JPEG or WebP at 1× to 4×, copy to the clipboard, or download with your own filename pattern.
Everything has a key. Press ? in the app for the full sheet.
| Action | Keys |
|---|---|
| Paste a screenshot | ⌘ V |
| Copy the image | ⌘ C |
| Download / export options | ⌘ S / ⌘ ⇧ S |
| Candy Shuffle | S |
| Candy Jar (all styles) | G |
| Previous / next style | [ ] |
| Cycle frames / padding | F / P |
| Text, arrow, highlight, blur | T A R B |
| Play or pause motion | M |
| Size menu | K |
Shotcandy is a static site. Your screenshots are decoded, rendered and encoded on your own device, in your browser, and are never uploaded anywhere. There are no accounts, no analytics and no server-side code. Recent designs, presets and uploaded backgrounds are kept in your browser's IndexedDB, and you can export any design as a .shotcandy project file to back it up or move it to another machine. After the page loads, the only network requests are for fonts.
You need Node 20.9 or newer and pnpm.
pnpm i && pnpm dev
Then open http://localhost:3000.
The production build is plain files. There is nothing to configure: no environment variables, no database, no API routes.
pnpm build # writes a fully static site to out/
pnpm serve # optional: preview out/ with the zero-dependency static server
Upload out/ to any static host: GitHub Pages, Netlify, Vercel, Cloudflare Pages, an S3 bucket or a plain nginx folder. URLs use trailing slashes, so no rewrite rules are needed.
The heart of Shotcandy is a small, deterministic rendering engine in src/engine, written in plain TypeScript with no React dependency. The same scene plus the same input always produces the same pixels, which is what makes previews, exports and animation frames agree exactly.
flowchart LR
A[Paste / drop / pick] --> B[Scene model<br>plain JSON]
P[Styles & presets] --> B
B --> C[Layout<br>sizes, fit, frames]
C --> D[Canvas renderer<br>layers to pixels]
D --> E[Live stage preview]
D --> F[Export worker<br>PNG · JPEG · WebP]
D --> G[Animation worker<br>frame by frame]
G --> H[MP4 · WebM · GIF]
B --> I[IndexedDB & .shotcandy files]
engine/scene): a JSON description of canvas, background, card, frame, annotations and optional animation. Undo, presets, project files and the UI all read and write it.engine/layout, engine/render, engine/frames): layers drawn onto an HTML canvas, including our own vector frames and shadows.engine/export): renders off the main thread in a worker, with size presets, scale factors and per-destination size limits.engine/animation): motion presets are functions of time over the same scene, encoded with WebCodecs plus mp4-muxer / webm-muxer, or gifenc for GIFs.engine/code, engine/post, engine/appstore): code images, post cards and App Store sets build ordinary scenes, so they get every style, frame and export for free.src/components, src/state): a Next.js static export with Tailwind. The editor store drives the engine; the engine never knows about React.pnpm test # Vitest: engine unit tests and headless render tests
pnpm test:e2e # Playwright: visual regression against committed baselines,
# export sizes, and app flows in Chromium, Firefox and WebKit
pnpm bench # export performance (budget: a 4K export in under 1.5 s)
pnpm typecheck && pnpm lint
To see every style on every sample screenshot at once, render the contact sheet:
CONTACT=1 pnpm vitest run tests/render/contact-sheet.test.ts
Issues and pull requests are welcome.
src/engine, and no clocks or unseeded randomness in anything that renders.pnpm test:e2e:update) and say so in the PR.brand/samples for demos and tests. Please don't add real product screenshots, logos or vendor device art.pnpm typecheck && pnpm lint && pnpm test before opening a PR.Shotcandy is free and always will be. If it saves you time, you can support the project with a one-off tip or a small monthly contribution.
MIT © 2026 Bilal Tahir
64 commits
TypeScript
79.2%
HTML
9.9%
CSS
9.2%
JavaScript
1.7%