Tired of uploading photos to shady servers? I built a privacy-first bulk watermarker. 🔒
It runs 100% in the browser (Next.js). Images never leave your device.
✅ Smart Contrast
✅ HEIC Support
✅ SEO Renaming
Free & no ads. Feedback welcome!👇
https://smartwatermarktool.com/
Hey everyone! Thanks again for the tough love on this. I just released a major update (v1.3) fixing the crash issues and adding the privacy features you asked for. I wrote a full update here: https://www.indiehackers.com/post/you-roasted-my-mvp-i-listened-here-is-v1-3-crash-proof-100-local-eaac757746. Would love to hear your thoughts on the fix!
actually love this tool. My art usually constantly gets pirated over and over again. This will be useful
I'm really glad to hear that! Art theft is incredibly frustrating, and it was definitely in the back of my mind when building this.
The best part for your use case is that since it's local-first, your high-res originals never leave your computer. You get the protection of the watermark without the risk of uploading your source files to a cloud server.
Hope it helps keep your work safe! 🎨
Is the watermarking done via canvas/WebAssembly, and how are you handling HEIC in-browser (convert locally or decode directly)?
Great technical questions!
Watermarking: I'm sticking to the standard HTML5 Canvas API (2D Context) for now. It's surprisingly fast for simple overlays and text manipulation, so WebAssembly felt like overkill for the MVP.
HEIC Handling: It's done via local conversion using heic2any. The browser takes the HEIC blob, converts it to a JPEG blob in memory, and then I draw that converted blob onto the Canvas. It adds a small processing delay compared to native JPGs, but it ensures compatibility since native browser support for HEIC is still inconsistent.
That's pretty cool, I like that you kept it simple, just do one thing right!
Thanks a lot! That was the main goal.
It's very tempting as a developer to add complex editors, filters, or AI features, but I wanted to keep the workflow strictly linear: Upload → Watermark → Download.
For sellers who just want to get their listing online, I figured speed and simplicity were the most important features. Glad it resonates!
Nice post! I just looked at your website and its pretty good. Though, I have small change you could add to make it even better:
Thanks for the feedback! You're totally right.
Sometimes users hesitate to upload their own files just to 'test' the tool. I'm thinking about adding a 'Try with a Sample Image' button or a clear Before/After visual right in the hero section to show exactly what the 'Smart Contrast' looks like without any effort. Adding this to my backlog!
The "100% in browser" approach is the right call for this use case. Nobody wants to upload their photos to some random server, even if the privacy policy says "we delete them." Client-side processing removes the trust question entirely.
Smart contrast is an underrated feature. Most watermarkers just slap white text regardless of image content, and it either disappears on light backgrounds or looks terrible on dark ones. Auto-adjusting to image content is exactly the kind of detail that separates a polished tool from a MVP.
HEIC support is a good call too - that format catches a lot of people off guard when they try to use iPhone photos in web tools that only handle JPEG/PNG.
Question: how does performance scale with large batches? Browser-based processing can get sluggish when you throw 50+ high-res images at it. Any thoughts on chunking or progressive processing to keep the UI responsive?
Thanks for the kind words! You nailed exactly why I built it—trust is the main issue with existing tools.
Regarding performance with large batches: That's the main challenge of client-side processing. currently, I handle images asynchronously to avoid completely blocking the UI, but 50+ high-res raw images can indeed get heavy on the main thread.
I'm planning to implement Web Workers in the next update to move the Canvas processing off the main thread, or use a queue system (processing chunks of 3-5 images at a time) to keep the interaction smooth. Great catch!
Web Workers are the right move here. The main thread shouldn't be doing heavy Canvas operations - that's exactly what Workers are designed for.
The chunking approach (3-5 images at a time) is smart UX too. Users can see progress happening, which psychologically feels faster than a spinner on a single batch. Progress bars that actually move beat estimated completion times every time.
One thought: if you're already tracking which images are processed, you could add a "resume" feature for when browsers crash mid-batch. Edge case, but photographers with 200+ images will love you for it.
Spot on about the progress bar psychology. Seeing images turn green one by one is much more satisfying (and reassuring) than a global spinner.
The 'resume' feature is a fantastic edge-case idea. Since we're dealing with heavy image data, I'd probably need to use IndexedDB to persist the batch state temporarily (localStorage would likely choke on the size), but it would be a lifesaver for power users processing 200+ items. Definitely adding that to the 'Advanced' roadmap. Thanks for the insight!
IndexedDB is absolutely the right call for heavy image data - localStorage's 5-10MB limit would choke on even a modest batch. Smart to think about that constraint early.
The "Advanced" roadmap placement makes sense, but I'd argue there's a quick win here: even just persisting the list of filenames and their processed/unprocessed status (tiny payload) would let users know where they left off, even if they have to re-load the actual files. That's 80% of the UX benefit with 10% of the implementation complexity.
The green-one-by-one pattern is satisfying because it maps to how our brains track progress on physical tasks. You're essentially giving users a digital "done pile" - powerful stuff for tools handling tedious work.
That is a brilliant 'Pareto principle' insight. 💡
You're absolutely right—persisting just the state metadata (filenames + status) is a lightweight solution that solves the cognitive load of "Wait, did I already process the blue shirt?" without the technical overhead of managing Blob storage in the browser.
I'm definitely stealing that 'digital done pile' analogy! It effectively gamifies a boring admin task. Thanks for the actionable advice, I'll prioritize this metadata-only persistence for the next patch.
Happy to help! The Pareto insight really is the unlock here - you get the cognitive benefit (knowing where you left off) without the storage headache.
The "gamification of boring admin" angle is worth leaning into more broadly. Resellers processing 50+ product photos don't think of it as fun work - but if your UI makes them feel productive (progress indicators, completion sounds, that satisfying green checkmark cascade), they'll actually enjoy using the tool. That emotional layer is what turns "utility I have to use" into "tool I want to use."
Looking forward to seeing the metadata persistence in action. Ship it and let us know how users respond!
You've articulated the design philosophy perfectly: turning a chore into a flow state.
I hadn't thought about completion sounds, but pairing that with the visual 'cascade' of green checks would definitely add that little dopamine hit to the workflow. It changes the vibe from 'data entry' to 'clearing the deck.'
I'm putting the metadata persistence at the top of my list for the next update. I'll definitely ping you here when the patch is live. Thanks again for the mentorship!
Happy to help! You're building something genuinely useful - the combination of privacy-first architecture and attention to UX details like the flow state is rare. Most tools pick one or the other.
Looking forward to seeing how users respond to the metadata persistence. Good luck with the launch!
Thank you! Hearing that the balance between privacy and UX shines through is incredibly validating—it was the hardest part to get right.
I really appreciate the encouragement and the specific feedback. I'll get to work on that update. Cheers! 🚀