DEV Community

Cover image for I Built a Free AI Background Remover with Next.js 16 & Cloudflare Workers — $0/mo
WobblyDev
WobblyDev

Posted on

I Built a Free AI Background Remover with Next.js 16 & Cloudflare Workers — $0/mo

Open-source repo and "boring" stack details

Let me start with some context: I have a graveyard of unfinished side projects. Probably 15+ repos that never saw the light of day. This time I told myself — ship it, no matter how ugly the first version is.

The idea was dead simple. Upload a photo, remove the background, download a transparent PNG. That's it.

I ended up building imagesbackgroundremover.com — and the whole thing runs on Cloudflare's free tier. Zero dollars a month in hosting costs. I've also open-sourced the entire codebase so you can see exactly how it's put together:

GitHub logo turnturn / bg-remover-nextjs-cloudflare

Free AI Background Remover built with Next.js 16, Tailwind CSS 4, and Cloudflare Workers. Zero infrastructure cost.

🖼️ BG Remover — AI Background Remover

Remove image backgrounds instantly with AI. Free, fast, and no signup required.

🌐 imagesbackgroundremover.com

✨ Features

  • 🎯 AI Background Removal — Powered by advanced AI that detects subjects and removes backgrounds in seconds
  • 📸 Drag & Drop Upload — Supports JPG, PNG, and WebP (up to 10 MB)
  • 🔍 Before/After Comparison — Interactive slider to compare original and processed images
  • ⬇️ One-Click Download — Download transparent PNG with a single click
  • 📱 Fully Responsive — Works flawlessly on mobile, tablet, and desktop
  • 🌍 Multi-language — English and Chinese (中文) support
  • 🔒 Privacy First — Images are processed in real-time and never stored
  • 🔍 SEO Optimized — JSON-LD, Open Graph, Twitter Cards, semantic HTML, blog

🚀 Live Demo

Try it now at imagesbackgroundremover.com

How It Works

  1. Upload your image (JPG, PNG, or WebP)
  2. AI processes and removes the background automatically
  3. Download the transparent PNG…

Here's the honest breakdown of how it went.


The architecture (kept it boring on purpose)

I'm a big believer in boring technology. The fewer moving parts, the fewer things that break at 2am.

The whole system is just a browser talking to Cloudflare Workers on the edge. No origin server, no Docker containers, no Kubernetes, no "microservice mesh." Workers handles routing, auth, and API calls. Data goes to D1 and KV. That's it.

Architecture diagram

The "boring" architecture: browser → Cloudflare Workers → D1/KV, with Google OAuth and PayPal as external services.

Here's the stack in plain terms:

  • Next.js 16 — App Router with Edge Runtime. The latest version, because why not live on the edge (pun intended).
  • TypeScript — I don't write JS without types anymore. Life's too short for undefined is not a function.
  • Tailwind CSS 4 — Say what you will, but I can prototype a decent-looking UI in hours instead of days.
  • Cloudflare Workers — The compute layer. Deployed via opennextjs-cloudflare (see the config).
  • D1 — Cloudflare's edge SQLite. Stores users, credits, transactions.
  • KV — Key-value store for sessions. Think Redis, but free and managed.
  • Google OAuth — Login. Hand-rolled, not NextAuth (more on this later).
  • PayPal — Payments. Subscriptions and one-time credit packs.

Monthly infrastructure cost: $0. Not "$0 for the first 3 months." Just $0.


Why I left Vercel

I know, I know. "Next.js + Vercel" is like peanut butter and jelly. And honestly, the developer experience on Vercel is excellent.

But here's what happened. I needed a database for users and credits. I needed session storage. On Vercel's free tier, that means bolting on external services — a hosted Postgres, maybe Upstash for Redis. Suddenly my "free" project had $15-20/month in dependencies.

Cloudflare gave me all of that for free:

  • D1 — A real SQL database at the edge. Not a toy. Actual SQLite with proper query support.
  • KV — Session storage without managing Redis.
  • No cold starts — Workers are always warm. Users in Tokyo and users in Berlin get the same fast response.

The catch? You need opennextjs-cloudflare to make Next.js work on Workers. It's an adapter, and it works — but don't expect the Vercel-level polish. Debugging runtime errors on Workers can feel like reading tea leaves sometimes.

For a solo project with zero budget, the math was obvious.


The deploy gotcha that cost me an afternoon

Let me save you some time: pushing to GitHub does NOT trigger a Cloudflare Workers build.

If you've used Cloudflare Pages, you're probably expecting Git-push deploys. Workers doesn't do that. You need two commands:

npx opennextjs-cloudflare build   # ~45 seconds
npx wrangler deploy               # ~45 seconds
Enter fullscreen mode Exit fullscreen mode

Deployment pipeline

The deploy flow: two commands, under 2 minutes from commit to live.

I spent a genuinely embarrassing amount of time refreshing my production URL and wondering why nothing changed. Don't be me.

Also, in your wrangler.toml, do not forget this line:

compatibility_flags = ["nodejs_compat"]
Enter fullscreen mode Exit fullscreen mode

Without it, Node.js APIs that Next.js depends on will fail silently at runtime. Not with a nice error message. Just weird, broken behavior that makes you question your life choices.


The UI: one rule

I gave myself one rule for the interface: if someone can't figure out what this tool does within 5 seconds, I failed.

So the design is deliberately simple. Upload area dead center. Three-step "how it works" below. FAQ at the bottom. No sidebar, no feature tour, no "watch our 2-minute intro video." Just the thing you came here to do.

Product screenshot

The live product — one page, one action, zero confusion.

The before/after slider

This is probably my favorite piece of UI in the whole project. It looks like it needs a fancy library, but it's actually embarrassingly simple:

Click to see the slider code (React + CSS clip-path)
<div className="relative overflow-hidden">
  <img src={originalUrl} alt="Original" />
  <img 
    src={processedUrl} 
    alt="Processed"
    style={{ clipPath: `inset(0 ${100 - position}% 0 0)` }} 
    className="absolute inset-0"
  />
  <input 
    type="range" min={0} max={100} 
    value={position}
    onChange={(e) => setPosition(Number(e.target.value))}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

That's it. CSS clip-path and a native range input. No npm package needed.

i18n for two languages

The site supports English and Chinese. I considered next-intl and react-i18next, then decided they were massive overkill for two languages. Instead I wrote a simple i18n.ts:

export type Locale = "en" | "zh";

export const messages: Record<Locale, Messages> = {
  en: {
    hero: { title: "Make your images clean, cut-out, and ready to use." },
  },
  zh: {
    hero: { title: "让图片更干净,更利落,更适合直接使用。" },
  },
};
Enter fullscreen mode Exit fullscreen mode

Language switching uses ?lang=zh URL params with localStorage persistence. An applySeo() function updates all meta tags dynamically.

Is this the "right" way to do internationalization? No. Does it work perfectly for my use case? Absolutely.


Auth: 200 lines vs. a framework

I hand-rolled Google OAuth instead of reaching for NextAuth. Here's why:

  1. I only need Google login. NextAuth is built for "sign in with 47 different providers." That's not my problem.
  2. Edge compatibility. Some NextAuth adapters don't play nice with Workers.
  3. It's three routes. That's it.
/api/auth/login           → redirect to Google consent screen
/api/auth/callback/google → exchange code for tokens, create user in D1
/api/auth/me              → look up session in KV, return user
Enter fullscreen mode Exit fullscreen mode

Sessions live in KV with a 7-day TTL. The entire auth system is ~200 lines. Sometimes the best abstraction is no abstraction.


Making money (the honest version)

I went with a credits model because it's the simplest thing that could work:

Plan Price What you get
Free $0 3 credits on signup
Starter $3.49/mo 10 credits/month
Pro $8.69/mo 25 credits/month
Credit Pack (5) $1.73 Never expire
Credit Pack (10) $3.46 Never expire

PayPal handles subscriptions and one-time purchases. The integration was fine until I hit webhook signature verification. PayPal's documentation for verifying webhooks on edge runtimes reads like it was written by someone who has never actually tried to verify a webhook on an edge runtime. I got it working eventually, but it was not fun.


SEO for a domain that Google has never heard of

A brand-new domain has zero authority. Zero. Google doesn't know you exist, and it doesn't care that your code is clean.

Here's what I did:

The basics (one afternoon of work):

  • Proper robots.txt and sitemap.xml
  • JSON-LD structured data (WebApplication schema)
  • Open Graph + Twitter Card tags
  • Canonical URLs and hreflang for both languages
  • Title < 70 chars, description < 155 chars

The real work (ongoing):

  • Built a /blog with three articles targeting long-tail keywords:
    • "How to Remove Image Background for Free in 2026"
    • "Best Background Remover Tools Compared"
    • "Transparent PNG for Ecommerce Product Photos"
  • Each post has its own SEO metadata, JSON-LD Article schema, canonical URL, and a CTA back to the main tool

Technical SEO is table stakes. Everyone has it. Content and backlinks are what actually move the needle — and that's a game measured in months, not days.


Five things I'd tell past-me

1. Ship the smallest version first. My v1 had no login, no payments, no blog. Just: upload → remove → download. One page, one button. I added everything else after confirming people actually used it.

2. Cloudflare's free tier is a cheat code. D1 + KV + Workers replaces $20-30/month of managed services. For indie devs and side projects, this changes the economics completely.

3. Don't fight the deployment. I wasted time trying to get Git-push deploys working with Workers. Just accept the two-command flow and move on.

4. Resist every feature idea. I almost added batch upload, color backgrounds, AI enhancement filters. Glad I didn't. The product is better because it does one thing well.

5. SEO is a slow burn. The technical foundation matters, but don't expect Google to notice you for weeks. Write content, build links, be patient.


Try it

If you need to remove a background from an image — give it a spin. Free, instant, no signup required, works on mobile.

Try the Background Remover for Free

The full source code is open:

GitHub logo turnturn / bg-remover-nextjs-cloudflare

Free AI Background Remover built with Next.js 16, Tailwind CSS 4, and Cloudflare Workers. Zero infrastructure cost.

🖼️ BG Remover — AI Background Remover

Remove image backgrounds instantly with AI. Free, fast, and no signup required.

🌐 imagesbackgroundremover.com

✨ Features

  • 🎯 AI Background Removal — Powered by advanced AI that detects subjects and removes backgrounds in seconds
  • 📸 Drag & Drop Upload — Supports JPG, PNG, and WebP (up to 10 MB)
  • 🔍 Before/After Comparison — Interactive slider to compare original and processed images
  • ⬇️ One-Click Download — Download transparent PNG with a single click
  • 📱 Fully Responsive — Works flawlessly on mobile, tablet, and desktop
  • 🌍 Multi-language — English and Chinese (中文) support
  • 🔒 Privacy First — Images are processed in real-time and never stored
  • 🔍 SEO Optimized — JSON-LD, Open Graph, Twitter Cards, semantic HTML, blog

🚀 Live Demo

Try it now at imagesbackgroundremover.com

How It Works

  1. Upload your image (JPG, PNG, or WebP)
  2. AI processes and removes the background automatically
  3. Download the transparent PNG…




Got questions about the edge deployment, the OAuth flow, or anything else? Happy to go deeper in the comments.

Top comments (11)

Collapse
 
mjoycemilburn profile image
MartinJ • Edited

Great post, thank you. As a side comment, I couldn't agree more with your doubts about PayPal's professionalism. I've been a big fan of this company from day 1, when I first discovered the joys of a PayPal account. But it's been a downhill experience ever since. What is **wrong **with this company's management????

As evidence, I give you the company's number 1 product - the payment window. This is a breeze if you have a Paypal a/c. If not, it requires the IQ of an Einstein. Reason? Some bright marketing type has decided to use the situation as an opportunity to push people towards **creating **a Paypal account. Result? Total confusion. I've had to deal with customers literally in tears over this ghastly apology for a payment interface. And it's been like this for years? The worst of it is I'm a Paypal shareholder. I still believe in them, but can you hear the sound of my teeth grinding?

Collapse
 
_51c72dc747ba876dd3294 profile image
WobblyDev

Man, the guest checkout rant hit home. I've had users email me completely lost trying to pay without creating an account. Years of this and they still won't fix it. As a fellow PayPal integrator... I feel your pain 😅 Thanks for reading!

Collapse
 
germanviscuso profile image
German Viscuso

"I needed a database for users and credits. I needed session storage. On Vercel's free tier, that means bolting on external services — a hosted Postgres, maybe Upstash for Redis. Suddenly my "free" project had $15-20/month in dependencies." -> Vercel + Supabase

Collapse
 
_51c72dc747ba876dd3294 profile image
WobblyDev

Yeah that's exactly the trap. Supabase is solid on its own, but once you're stitching together Vercel + Supabase + maybe Upstash for KV, you're managing three dashboards and three billing pages for a "free" stack. Cloudflare having D1 and KV built in just cuts all that out.

Collapse
 
leob profile image
leob

Really cool write-up! I'm hearing lots of good things about Cloudflare as an application platform these days - eager to look at how you did this and to try something myself!

Collapse
 
_51c72dc747ba876dd3294 profile image
WobblyDev

Thanks! Definitely give it a shot. The repo's public if you want to poke around: github.com/turnturn/bg-remover-nextjs-cloudflare.

Collapse
 
leob profile image
leob

Yeah I definitely want to check it out - interesting also that you did not target Vercel (the 'standard' choice), but Cloudflare, via OpenNext ...

Collapse
 
meir_meir_ba97d0e4663bddc profile image
Meir Meir

Hi. Thanks for sharing. What about the dedicated domain name? Is it also free?

Collapse
 
_51c72dc747ba876dd3294 profile image
WobblyDev

Not if you mean a custom domain — you still have to pay for that yourself. But Cloudflare does give you a free *.workers.dev subdomain, so you can get a project online without buying a domain first.

Collapse
 
mecloud profile image
mecloud

👍️

Collapse
 
_51c72dc747ba876dd3294 profile image
WobblyDev

🙏