Build Shots.so
YESreplaces $5/mosaves $60/yrback to the verdict
A screenshot beautifier as one static page: drop, paste or pick a screenshot, adjust padding, corners, shadow, background and canvas ratio with live preview, export a crisp PNG at 1x or 2x or copy it to the clipboard. Everything happens in the browser; nothing is uploaded; it works offline after the first load.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Every step below is a command you type or a file you edit.
Get it VS Code (code.visualstudio.com), Cursor or Zed. Open a folder for the project and use the editor's built-in terminal. open ↗
Verify
You can open a folder and run a command in its terminal - installfree
Why Clipboard image copying behaves differently in Safari; Phase 5 must be tested in both.
Get it Chrome or Edge, plus Safari if you have a Mac. Without Safari, note the clipboard code path is untested there.
- have readyfree
Why Including one very tall one and one wider than 4000px, to exercise ratios and performance.
Get it Take three: a normal window, a full-page tall capture, a large retina one.
- accountfree
Why To share it with others. Locally, opening the file is enough.
Get it Cloudflare Pages, Netlify or GitHub Pages: connect the repo, done. open ↗
- installfree
Why History for your code, and the way most hosts deploy.
Get it Install from git-scm.com or with your package manager, then run git init in the project folder once it exists. open ↗
Verify
git --version prints a version
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
A single `state` object drives every render: `{ image, padding, radius, shadow,
background, ratio, scale }`. Every control writes to `state` and calls one
`render()`. There is exactly one render function and one source of truth · the
moment two code paths draw to the canvas, the controls start disagreeing with
the export, which is the classic bug in this tool.The build, in order
Image input and render loop
Three ways in, one render function, correct on HiDPI from the start.
state = { image, padding, radius, shadow, background, ratio, scale }. Every control writes to state and calls render(). Exactly one render function; two code paths drawing to the canvas is the classic bug here.
Files
index.htmlpaste: read clipboardData.items for an image type. All three create an Image from a Blob URL and set state.image.
Backing store = css size times devicePixelRatio; ctx.scale once. Retrofitting this later means re-tuning every offset.
done when · tick each as it passesGeometry controls
Padding, radius and shadow as live sliders whose export matches the preview.
Range inputs bound to state; render on input.
ctx.roundRect and clip, not a CSS overlay, or the export will not match the preview. Draw the shadow with canvas shadow properties on the clipped shape.
done when · tick each as it passesBackgrounds
Ten presets that look premium before anyone touches anything.
Plus a custom colour input and a transparent option.
Most users never change it.
done when · tick each as it passesCanvas ratios
Fit without cropping or distortion.
Store it in state; a change triggers one render().
Compute the scale as the minimum of available width over image width and available height over image height. Never crop, never distort.
done when · tick each as it passesExport
Sharp PNG at 1x and 2x, and clipboard that works in both engines.
Never upscale the preview bitmap.
Pass a Promise resolving to a Blob into ClipboardItem; Safari requires the promise form and Chromium accepts it. Call navigator.clipboard.write synchronously inside the click handler.
done when · tick each as it passesPolish
Shortcuts, an empty state, memory, offline.
Open DevTools > Network, reload with Offline checked.
done when · tick each as it passesShip it as an appproduct builder
Only for the product path: installable, offline-first, with a privacy statement.
Files
manifest.webmanifestsw.jsNothing is uploaded; there is no analytics.
done when · tick each as it passes
That is the whole plan for Shots.so. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- A template and device-frame library. Keeping frames current is real ongoing work and a real reason to pay.
- Batch processing and automatic text redaction.
- Cloud sync of presets. There is no cloud here.
- their template/mockup library
- device frames kept up to date
- batch processing
- Device frames as SVG overlays you maintain yourself
- A share-target so phones can send screenshots straight in
Need the files? The project pack on the verdict page hands your agent the whole brief · more screenshots.