Image editor SDK · Rust core, one binary everywhere
Edit small. Render big. Identical.
Your users edit a preview in the browser. Your server applies the same edit log to the 80-megapixel original and produces the same pixels. Verified by hash.
The same component lays itself out for a phone on its own. No second UI to build, no mobile flag to set. Try it in the frame.
One component, two layouts
Below 768 px of container width the toolbar moves to the bottom and the tool panel sits above it. It reacts to its container, not the viewport, so a narrow sidebar gets the phone layout too.
Touch first
Pinch to zoom, drag to pan, one finger for crop handles, redaction boxes and annotations. Wheel and trackpad do the same on a desktop.
Only the preview travels
The phone loads and edits a small preview. The edit log goes to your server, which applies it to the full-resolution original. Same pixels, a fraction of the data.
Notches and home bars
Safe-area insets are respected. show-history="buttons" drops the timeline and show-export="never" hides Export, so the essentials fit on a small screen.
9:41
Loading the editor…
The editor could not load here. Open the demo instead.
Live editor in a phone frame. Drag, pinch, tap.
The edit log is the image
One log, one core
Every crop, filter and annotation is an operation in a JSON log. A Rust core compiled to WebAssembly executes it in a Web Worker, on Node, Deno, Bun or AWS Lambda. Same bytes in, same bytes out.
Byte-identical, hash-verified
Render the same source with the same log anywhere and the SHA-256 matches. Large uploads edit a proxy on the phone; the server renders the original from the same log.
Resume from JSON
Store the original once and the log next to it. Reopen any state, on any device, without generation loss. The log can travel inside the exported PNG, JPEG or WebP.
Every tool your users expect
Ten plugins ship in the box. Each one is a package you can drop, replace or extend.
Crop
Rotate by any angle, flip, aspect presets, handles that stay 7 px on every screen.
@sealpixel/plugin-crop
Finetune
Brightness, contrast, saturation, exposure, gamma, clarity and vignette.
@sealpixel/plugin-finetune
Filter
Grayscale, sepia, vintage, cool, warm and any 4×5 colour matrix, with strength.
@sealpixel/plugin-filter
Redact
Pixelate or blur rectangles and freeform regions. Cells snap to the source grid so proxy and original match.
@sealpixel/plugin-redact
Annotate
Rectangles, ellipses, lines, arrows, freehand paths and text. Fonts are hashed assets: identical glyphs everywhere.
@sealpixel/plugin-annotate
Sticker
Place logos and image assets with rotation, flips and opacity.
@sealpixel/plugin-sticker
Frame
Solid, inset and polaroid frames.
@sealpixel/plugin-frame
Watermark
Image or text, anchored or tiled, applied identically on the server.
@sealpixel/plugin-watermark
Resize
Contain, cover and fill to a target size. Lanczos3 down, Catmull-Rom up.
@sealpixel/plugin-resize
Fill
Background colour for areas a rotation or crop exposes.
@sealpixel/plugin-fill
A component for every stack
A Web Component underneath, thin typed wrappers on top. Controlled and uncontrolled edit logs everywhere.
Send the original and the edit log to one fetch handler. It validates the log, renders with the same WebAssembly binary and returns bytes, a hash and a job key. Repeat the request and it returns the cached result.
Zod-validated request, SSRF allowlist, size limits before decode
Idempotent job keys: same source, log and options, same object
S3 or URL sources, S3 or inline destinations, proxy mode for large uploads
Memory sizing table from 12 to 80 megapixels
POST /render
{
"source": { "kind": "s3", "bucket": "uploads", "key": "IMG_4821.jpg" },
"editLog": { "version": 1, "source": { "id": "IMG_4821", "width": 8192, "height": 5461 }, "ops": [ … ] },
"output": { "format": "image/jpeg", "quality": 0.92 },
"destination": { "kind": "s3", "bucket": "renders" }
}
200 OK
{
"key": "renders/3f9a…c1.jpg",
"hash": "3f9a4e…b7c1", ← equals the browser's hash for the same input
"width": 6144, "height": 4096,
"cached": false, ← true on the second identical request
"timings": { "decode": 412, "render": 1730, "encode": 388 }
}
Extend it without forking
A plugin is an npm package: operations with zod schemas, a reducer, a kernel in JavaScript or in Rust compiled to its own WebAssembly module, and an optional tool with panel and gizmo. It runs on the client and on the server without rebuilding the core.
Scaffold one
npm create sealpixel-plugin acme-spotlight --kernel wasm-rustcd acme-spotlight && npm test # parity: Node vs Chromium, WebKit, Firefox
Business Source License 1.1, Apache 2.0 after four years. No runtime license check: the software never phones home. Read the license
Questions
Who uses Sealpixel free of charge?
Anyone under EUR 1,000,000 of gross annual revenue: individuals, and organizations below that threshold. Production and commercial products are included. Revenue counts across the whole group, so a subsidiary of a large company is not free. For client work the client’s revenue decides, so a freelancer building for a small startup pays nothing and the same freelancer building for a large customer is covered by that customer’s seats.
I am an agency. What do I pay?
One seat per developer who works on codebases that include Sealpixel, regardless of how many clients or products those codebases serve. A seat held by your developer covers all their client work, so your clients need no seats of their own, and none to run the finished application.
How do volume tiers work?
Pick the number of seats at checkout. From 5 seats every seat costs 10 percent less, from 10 seats 20 percent less. Seats you add later are billed at the tier your total reaches and prorated to your renewal date. Above 25 seats we quote individually.
Can an open-source project use Sealpixel?
Yes. Contributors below the revenue threshold need no seats; a company that develops the project needs seats for its developers. Copies and forks stay under the Business Source License, and every release becomes Apache 2.0 four years after it was published.
Is Sealpixel open source?
Not yet, by design. Sealpixel uses the Business Source License 1.1: the source is public, you may read, modify, fork and redistribute it, and production use is free below the revenue threshold. Four years after a version is published it converts to the Apache License 2.0. Until then, larger organizations buy developer seats.
What is a developer seat exactly?
A seat belongs to a named person who writes, reviews, tests or integrates code in a project that includes Sealpixel. It can be reassigned when that person leaves. Designers in the codebase and QA engineers count; end users of your application do not.
Can I build a SaaS on Sealpixel?
Yes. The only limit is a service whose primary value is the image editor itself, such as a hosted "edit your image" product or an image editing API sold to third parties. A photo-book shop, a CMS, a real-estate portal or a support tool with editing built in are all fine.
How does the refund work?
Cancel within 30 days of your first purchase and the merchant of record refunds the full amount to the original payment method. No questions asked.
What exactly is byte-identical?
The same source bytes plus the same edit log rendered through the same core version produce the same output bytes and SHA-256, in every browser, on Node, Deno, Bun and Lambda. When a phone edits a downscaled proxy and the server renders the original, the composition is identical (same normalized geometry) but the bytes differ, because the inputs differ. The docs spell this out.
How big is the download?
The WebAssembly core is about 1.3 MB raw and 390 KB with Brotli, loaded lazily when the editor mounts. The Lit UI and the render worker add a few tens of kilobytes. There is a budget check in CI.
Which browsers are supported?
Current Chrome, Edge, Safari and Firefox on desktop and mobile. Every commit runs the parity suite in Chromium, WebKit and Firefox, and the UI suite in Chromium and WebKit. On iOS Safari the download falls back to the share sheet.
Can I write my own tool?
Yes. npm create sealpixel-plugin scaffolds a package with operations, a reducer, a JavaScript or Rust kernel and a tool panel. The testing kit renders your plugin in Node and three browsers and asserts equal hashes. Two example plugins ship in the repository.