Beautiful device mockups in seconds.
Free, open-source, and runs entirely in your browser.
Try it live • About • Features • Get Started • Tech Stack • License
Most mockup tools are either bloated desktop apps, locked behind subscriptions, or require uploading your screenshots to someone else's server. Monkr is different - it's a fast, privacy-first mockup generator that runs 100% in your browser. No accounts, no uploads, no watermarks.
Drop in a screenshot, pick a device, choose a background, and download a polished mockup in seconds. Need App Store screenshots? Animated previews? Multi-device compositions? Monkr handles it all.
Pixel-perfect frames for the devices people actually use:
| Category | Devices |
|---|---|
| iPhone | 18 Pro Max, 18 Pro & iPhone Duo — inner/outer, folded & unfolded — (official Apple bezels); 17 Pro Max, 17 Pro, 17 Air, 17, 16 Pro Max, 16 Pro, 16 Plus, 16, 15 series, 14 series |
| Android | Pixel 7 Pro, Nothing Phone |
| iPad | Pro (M5) 13" & 11" (official Apple bezels), Pro 13", Pro 11", Air, Mini |
| Mac | MacBook Pro 16", MacBook Air M2, MacBook Air 13" |
| Desktop | iMac M4 24" & MacBook Neo (official Apple bezels), iMac 24", iMac Pro, Pro Display XDR |
| Watch | Apple Watch Series 11 46mm, Apple Watch Ultra 3 49mm — official Apple product bezels (see docs/APPLE-BEZELS.md) |
| Misc | Apple Studio Display / Studio Display XDR 2026 (official Apple bezels, marketing frames only — no ASC screenshot type) |
| Other | Apple TV 4K, Flat Screen TV, Browser (Light & Dark) |
Each device includes multiple color variants and can be freely positioned, scaled, rotated, and tilted in 3D.
Official Apple product-bezel frames are kept in sync with
Apple Design Resources by
npm run sync-bezels — it discovers every published Bezel-*.dmg, diffs
against static/devices/manifest.json, measures the screen cutouts, and
generates registry entries + mask SVGs automatically. A new device class
shows up on its own — the run flags anything a human must decide (a frame
with more than one screen, a cutout no App Store screenshot size fits, a
folding device) instead of importing it silently. See
docs/APPLE-BEZELS.md for the workflow, flags, and
license notes.
- 30+ gradient presets - Cosmic, warm, cool, nature, pastel, neon, and mesh gradients
- 100+ curated images - Abstract, cosmic, earth, holographic, mystic, glass, radiant, vintage, and classic macOS wallpapers (Big Sur through Tahoe)
- Solid colors with full color picker
- Transparent backgrounds for compositing
- Trim transparent edges - crop a transparent PNG export to the visible mockup (shadows and antialiased edges kept). Saved with the project; applies to Download, Copy, and Export All Variations, never to App Store slides
- Custom uploads - drag & drop any image
- Unsplash integration - search millions of free photos
One-click layouts that look professional instantly:
- Single device - Hero shots, centered, tilted
- Duo layouts - Side by side, overlapping, responsive pairs
- Multi-device - Fan spreads, perspective rows, cascades
- Ecosystem - Full Apple lineup in one shot
- App Store - Pre-configured multi-slide layouts for iPhone and iPad
Built specifically for shipping apps:
- Toggle App Store mode and pick your platform (iPhone 6.7", 6.1", iPad 12.9", 11")
- Canvas automatically sizes to App Store guidelines
- Choose 1-10 sections that split the canvas into slides
- Design across all slides using the same tools
- Export slices each section into a separate screenshot
- Visual divider lines and section labels keep you oriented
- Multiple font families with weight control (100-900)
- Alignment, letter spacing, and line height
- Text shadow with color, blur, and offset
- Arc text for curved headlines
- Position above, below, or anywhere on canvas
- 3D tilt and rotation
Create animated mockups and export as video:
- 7 animation presets - Full Spin, Rock, Tilt Showcase, Float, Zoom Pulse, Slide In, Rise
- Adjustable duration and FPS
- Loop support
- Export as MP4 (H.264), MOV, or WebM (VP9)
- Powered by FFmpeg WASM - encoding happens entirely in your browser
| Format | Use Case |
|---|---|
| PNG | Lossless quality, transparency support |
| JPG | Smaller files, great for web — no alpha channel, so it's disabled while Background is "None" |
| MP4 | Animated mockups, social media |
| MOV | QuickTime-compatible video |
| WebM | Web-optimized video |
All image exports support 1x, 2x, and 3x scale for retina-quality output. One-click copy to clipboard for quick sharing.
Every device on the canvas can be individually tuned:
- Position - Drag or use precise X/Y controls
- Scale - Pinch or slider from tiny to oversized
- Rotation - Free rotation in degrees
- 3D Tilt - Perspective tilt on X and Y axes
- Shadow - Color, blur, spread, and offset
- Glow - Edge glow with customizable color and intensity
- Frame style - Full device frame, outline only, or frameless
20+ arrangement templates for multi-device compositions:
- Single Center, Tilted, Hero Left/Right
- Side by Side, Overlap, Stacked
- Fan, Cascade, Perspective Row
- Grid 2x2, Scattered, Isometric
- Phone+Tablet, Laptop+Phone, Floating Stack
- Showcase 5 and more
Pre-configured sizes for every platform:
- General - 16:9, 9:16, 1:1, Ultrawide
- Social - Dribbble, Twitter, Instagram (Post & Story), LinkedIn, Product Hunt, Open Graph
- App Store - All iPhone sizes, iPad, Mac, Apple TV, Apple Watch (46mm & Ultra 49mm)
- Google Play - Phone, Tablet 7" & 10", Feature Graphic
- Auto-save - Your project persists in localStorage automatically
- Import/Export - Save and load
.monkrproject files - Reset - One-click clean slate
- Mobile friendly - Responsive sidebar with swipe navigation
- Zero server dependency - Everything runs client-side
Head to wemiller.com/tools/monkr/app and start creating.
git clone https://github.com/blaineam/Monkr.git
cd Monkr
npm install
npm run devOpen http://localhost:5173 and you're in.
npm run build
npm run preview # preview the build locallyThe static build outputs to build/ and can be deployed anywhere - GitHub Pages, Netlify, Vercel, Cloudflare Pages, or your own server.
How the hosted copy is served. The app at wemiller.com/tools/monkr/app/ is a
small shell (~0.6 MB) built by scripts/build-portfolio.sh (base path
/tools/monkr/app, output build-portfolio/) and mirrored into the portfolio
site. The device frames and backgrounds (~145 MB) are not copied there: the shell
loads them from monkr.wemiller.com with CORS (VITE_MONKR_MEDIA_ORIGIN, see
src/lib/site.ts). This repo's Pages deploy keeps publishing them, but runs
scripts/legacy-site.mjs, which turns every page on monkr.wemiller.com into a
redirect to the new address (path, query and hash kept) and adds migrate.html,
which hands saved projects in that origin's localStorage to the new address in
the browser (src/lib/legacy-import.ts; nothing is uploaded).
Render .monkr projects to framed images from the command line — no clicking
through the UI. It drives Monkr's own renderer (headless Chromium + the
/headless route), so output is pixel-identical to the Export button.
npm install # installs Playwright (a devDependency)
npx playwright install chromium # one-time browser download
# render a project's embedded screenshots
npm run render -- shot.monkr --out out/
# or, if linked/installed: monkr render shot.monkr --out out/
# swap in fresh screenshots (a folder, in name order) and re-save the .monkr
monkr render App-iphone.monkr --out out/ --save --screenshots raw/iphone/One framed image is written per screenshot. Useful flags: --save (write the
updated .monkr), --format png|jpg, --scale 1|2|3, --trim / --no-trim
(crop a transparent PNG to its visible pixels), --build (force a
rebuild first), and --device/--color/--canvas to synthesize a default frame
when no .monkr exists yet. Run monkr render --help for the full list. The
CLI auto-builds the static site on first use and rebuilds automatically when
src/ has changed since the last build. Implemented in bin/monkr.mjs +
cli/render.mjs, backed by the headless route at src/routes/headless/.
monkr animate plays Monkr's animation presets over a project and writes a
video, using the same renderer frame by frame and the system ffmpeg
(brew install ffmpeg) for H.264 encoding. Presets can be chained, which
is what short social clips (YouTube Shorts, Reels) need: an entrance, then a
loop.
# rise in from below, then float for the rest of a 7-second 9:16 clip
monkr animate short.monkr --out short.mp4 --duration 7000 --relative \
--sequence "rise@0:1400,float@1400:7000"--sequence takes preset@start:end steps in milliseconds (a bare preset name
runs the whole clip). A step longer than its preset repeats whole cycles, and a
step that continues a property picks up where the previous one ended, so chains
never jump. --relative applies presets as offsets from each device's own
position and pose, instead of the editor's absolute values, so a composed layout
keeps its composition. Other flags: --fps, --silent-audio (adds a silent AAC
track), --build.
Add music with Tom, a seeded music machine:
--music synthwave (or --music "chip:#road-trip" for a specific,
shareable tune) scores the clip with a Tom jingle whose final hit lands at
--music-hit ms (default: 74% of the clip). Tom is optional. Monkr finds it via
TOM_BIN or tom on your PATH, and only needs it when you ask for music. Implemented in cli/animate.mjs; the chaining and relative
math live in src/lib/animation.ts (buildSequenceTracks, resolveTrackValue).
| Layer | Technology |
|---|---|
| Framework | SvelteKit 2 + Svelte 5 (runes) |
| Language | TypeScript 5.9 |
| Styling | Tailwind CSS 4 |
| Icons | Lucide |
| Image Export | html-to-image |
| Video Export | FFmpeg WASM |
| Build | Vite 7 |
| Deploy | Static adapter (GitHub Pages) |
src/
├── lib/
│ ├── components/ # Svelte components (Canvas, Sidebar, ExportButton, etc.)
│ ├── stores/ # State management with Svelte 5 runes
│ ├── animation.ts # Animation system + FFmpeg video export
│ ├── backgrounds.ts # Curated background image registry
│ ├── export.ts # Image export + App Store section slicing
│ ├── fonts.ts # Font loading and management
│ ├── gradients.ts # Gradient preset definitions
│ ├── mockups.ts # Perspective mockup scenes
│ ├── presets.ts # Canvas size presets
│ ├── scenes.ts # One-click scene presets
│ ├── templates.ts # Layout arrangement templates
│ ├── types.ts # TypeScript type definitions
│ └── unsplash.ts # Unsplash API integration
├── routes/
│ └── +page.svelte # Main app page
└── app.html # HTML shell
static/
├── backgrounds/ # 100+ curated background images
├── devices/ # Device frame PNGs (all sizes + colors)
│ └── manifest.json # Apple official-bezel sync state (sync-bezels)
└── ... # Favicons, OG image, manifest
tools/
├── sync-bezels.mjs # Sync frames with Apple's official Product Bezels
├── measure-bezel.mjs # PNG alpha-channel screen-cutout measurement
└── test/ # Unit + headless end-to-end tests (npm test)
Contributions are welcome! Feel free to open issues or submit pull requests.
- Fork the repo
- Create a feature branch (
git checkout -b feature/cool-thing) - Commit your changes
- Push to the branch (
git push origin feature/cool-thing) - Open a Pull Request
Before opening a PR:
npm test— unit + headless end-to-end tests. The e2e tests drive a real Chromium (npx playwright install chromiumonce); they skip when no browser is installed.npm run check—svelte-checkmust report no errors.
CI runs the same two commands on every pull request. For larger changes, open an issue first so the approach can be discussed before you build it.
MIT - do whatever you want with it.
Made by Blaine Miller
