<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jasper Smith</title>
    <description>The latest articles on DEV Community by Jasper Smith (@jaspersmith).</description>
    <link>https://dev.to/jaspersmith</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3865893%2Fce10e334-179a-4681-9b3a-56ed2d8f1fe3.jpg</url>
      <title>DEV Community: Jasper Smith</title>
      <link>https://dev.to/jaspersmith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jaspersmith"/>
    <language>en</language>
    <item>
      <title>I built an AI people remover that never downscales your photo (Next.js + Cloudflare Workers)</title>
      <dc:creator>Jasper Smith</dc:creator>
      <pubDate>Tue, 29 Sep 2026 13:32:35 +0000</pubDate>
      <link>https://dev.to/jaspersmith/i-built-an-ai-people-remover-that-never-downscales-your-photo-nextjs-cloudflare-workers-48ok</link>
      <guid>https://dev.to/jaspersmith/i-built-an-ai-people-remover-that-never-downscales-your-photo-nextjs-cloudflare-workers-48ok</guid>
      <description>&lt;p&gt;Most "AI photo cleanup" tools have a dirty secret: you upload a 24-megapixel photo, and you get back something closer to 1–2 megapixels. The model works at a fixed resolution, so the whole image gets resized, regenerated and quietly degraded — even the parts you never touched.&lt;/p&gt;

&lt;p&gt;I wanted a tool to &lt;a href="https://www.peopleremover.com/" rel="noopener noreferrer"&gt;remove people from photo online&lt;/a&gt; without that trade-off, so I built one: &lt;a href="https://www.peopleremover.com/" rel="noopener noreferrer"&gt;People Remover&lt;/a&gt;. You brush over a tourist, a photobomber or an ex, the AI fills the area, and you download a PNG that is exactly the same width and height as your original.&lt;/p&gt;

&lt;p&gt;This post covers the architecture and the one trick that makes it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core idea: generate small, composite big
&lt;/h2&gt;

&lt;p&gt;Inpainting models are good at inventing plausible background. They are not good at preserving 6000×4000 pixels of detail they didn't need to touch. So I split the job in two:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The model&lt;/strong&gt; gets the full frame plus a black-and-white mask (white = edit, black = keep) and generates at 1K (Standard) or 2K (HD Repair).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The browser&lt;/strong&gt; keeps the original decoded pixels, scales the model output back up to the original dimensions, and copies in &lt;em&gt;only&lt;/em&gt; the masked pixels.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything outside the brush stays identical to what the browser decoded from your file. Only the area you painted changes.&lt;/p&gt;

&lt;p&gt;Here's a simplified version of the compositing step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;composite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageBitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// full-resolution source&lt;/span&gt;
  &lt;span class="nx"&gt;generated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageBitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// model output at 1K/2K&lt;/span&gt;
  &lt;span class="nx"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageBitmap&lt;/span&gt;        &lt;span class="c1"&gt;// white = replace, black = keep&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OffscreenCanvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Start from the untouched original.&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. Build a layer that is "generated pixels, clipped to the mask".&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OffscreenCanvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;lctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// upscale to original size&lt;/span&gt;
  &lt;span class="nx"&gt;lctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;globalCompositeOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;destination-in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;lctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// keep only masked area&lt;/span&gt;

  &lt;span class="c1"&gt;// 3. Paint that layer over the original.&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convertToBlob&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real version handles a few more things: the mask needs an alpha channel (not just luminance) for &lt;code&gt;destination-in&lt;/code&gt;, antialiased edges give a narrow transition so you don't see a hard seam, and repeated edits build on the last full-size composite rather than the original.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why HD Repair is not "AI upscaling"
&lt;/h3&gt;

&lt;p&gt;A common question: if the output is full size anyway, what does the 2K mode buy you? The answer is detail &lt;em&gt;inside the brushed area&lt;/em&gt;. At 1K, a person you removed from a 6000px-wide photo is regenerated at roughly a sixth of the native resolution, then stretched. At 2K you get twice the detail in each direction. On small photos (under ~1000px on the long side) Standard already matches the source, so HD makes no difference. It's never a whole-image upscale — untouched pixels are never regenerated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 15&lt;/strong&gt; deployed to &lt;strong&gt;Cloudflare Workers&lt;/strong&gt; via &lt;code&gt;@opennextjs/cloudflare&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D1&lt;/strong&gt; (SQLite at the edge) for accounts, jobs and a credit ledger&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R2&lt;/strong&gt; for uploads, masks and results, accessed through the S3 SDK&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; for one-time credit packs and monthly plans&lt;/li&gt;
&lt;li&gt;Google OAuth as the only sign-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No image processing happens on the server. The Worker validates uploads, creates a job with the model provider, polls it, and copies the result into R2. The heavy pixel work runs in the user's browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that bit me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Idempotency matters more than you think.&lt;/strong&gt; Mobile networks drop requests all the time. Every removal carries a client-generated UUID &lt;code&gt;requestId&lt;/code&gt;. If the same ID arrives twice, the server returns the existing job instead of charging again or creating a second model task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refunds need to be transactional.&lt;/strong&gt; A generation can fail at the provider after the credits are deducted. Confirmed failures refund the exact charge once, recorded in the ledger. Temporary polling or download errors, on the other hand, stay retryable and &lt;em&gt;don't&lt;/em&gt; refund — otherwise a flaky connection turns into free credits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Save the final composite separately.&lt;/strong&gt; The browser uploads the merged, original-size PNG back to the server after compositing. If that upload fails, the browser keeps the composite in memory and offers a save-only retry that never charges another edit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Canvas has memory limits, especially on phones.&lt;/strong&gt; A 25-megapixel photo decoded into RGBA is 100 MB of raw pixels, and iOS Safari will happily refuse a canvas that big. I cap input at 25 MP / 20 MB and show an explicit error instead of silently producing a broken file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metadata is gone.&lt;/strong&gt; Output is PNG, and EXIF/ICC data isn't kept. Some people see that as a privacy bonus; photographers who care about color profiles should know it up front.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can use it for
&lt;/h2&gt;

&lt;p&gt;The same brush-and-fill pipeline works for more than people:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing strangers from travel shots — I wrote a step-by-step guide on &lt;a href="https://www.peopleremover.com/how-to-remove-people-from-photos" rel="noopener noreferrer"&gt;how to remove people from photos&lt;/a&gt; with real before/after masks, including why you should always brush the shadow too.&lt;/li&gt;
&lt;li&gt;Cleaning up clutter: bins, cables, signs, cars. That's the dedicated tool to &lt;a href="https://www.peopleremover.com/remove-object-from-photo" rel="noopener noreferrer"&gt;remove object from photo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Date stamps, watermark-free captions on your own images, screenshot text: &lt;a href="https://www.peopleremover.com/remove-text-from-image" rel="noopener noreferrer"&gt;remove text from image&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you mostly edit on your phone, I also compared the built-in options (iPhone Clean Up, Google Photos Magic Eraser, Samsung Galaxy AI) in this roundup of free &lt;a href="https://www.peopleremover.com/remove-people-from-photo-app" rel="noopener noreferrer"&gt;remove people from photo apps&lt;/a&gt;. The short version: the built-in tools are great if your phone supports them; a browser tool helps when it doesn't, or when you need the full-resolution file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it / tell me what breaks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.peopleremover.com/" rel="noopener noreferrer"&gt;People Remover&lt;/a&gt; gives you 2 free credits without signing in (one Standard edit), and 4 more on your first Google sign-in. No watermark, no app install, full-resolution download.&lt;/p&gt;

&lt;p&gt;I'd genuinely like feedback from other devs, especially on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mask edge blending — any better approaches than an antialiased brush + alpha clip?&lt;/li&gt;
&lt;li&gt;Handling very large images on mobile without hitting canvas limits (tiling? &lt;code&gt;createImageBitmap&lt;/code&gt; with resize options?)&lt;/li&gt;
&lt;li&gt;Anyone running similar async job flows on Workers + D1 — how are you handling polling after the user closes the tab?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment. Happy to go deeper on any part of this.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>cloudflarechallenge</category>
    </item>
    <item>
      <title>I Built an AI Video Generator with Next.js and Got My First Paid User in 3 Months</title>
      <dc:creator>Jasper Smith</dc:creator>
      <pubDate>Sat, 25 Jul 2026 16:56:57 +0000</pubDate>
      <link>https://dev.to/jaspersmith/i-built-an-ai-video-generator-with-nextjs-and-got-my-first-paid-user-in-3-months-23kd</link>
      <guid>https://dev.to/jaspersmith/i-built-an-ai-video-generator-with-nextjs-and-got-my-first-paid-user-in-3-months-23kd</guid>
      <description>&lt;h1&gt;
  
  
  I Built an AI Video Generator with Next.js and Got My First Paid User in 3 Months
&lt;/h1&gt;

&lt;p&gt;I'm a frontend developer working at a bank in Shenzhen. By day I write React components. By night, I've been building &lt;a href="https://www.froging.ai" rel="noopener noreferrer"&gt;Froging AI&lt;/a&gt; — an AI video generator that turns images and text into videos in minutes.&lt;/p&gt;

&lt;p&gt;Three months ago I knew nothing about AI video APIs. Last week, I got my first paid order. Here’s how it happened.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;I wanted to ship fast and keep costs low. My stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14&lt;/strong&gt; (App Router) — frontend + API routes in one repo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase&lt;/strong&gt; — Auth, PostgreSQL, and storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — deployment, zero DevOps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creem&lt;/strong&gt; — payments (one-time + subscriptions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replicate / Minimax / 海螺AI&lt;/strong&gt; — video generation APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why not Python? I'm a frontend dev. Next.js API routes handle async queueing just fine. I didn't want to learn a new deployment pipeline. Ship fast, iterate faster.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;Froging AI has two core features:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image to Video&lt;/strong&gt;&lt;br&gt;
Upload a photo, add a prompt, and the AI animates it into a short video clip. Good for product demos, social content, and creative experiments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text to Video&lt;/strong&gt;&lt;br&gt;
Describe a scene in plain English and get a generated video back in minutes. No camera, no editing software.&lt;/p&gt;

&lt;p&gt;Under the hood, I'm routing requests to different providers based on model availability and cost. Replicate's open-source models (Wan-2.1, etc.) for cheap experiments. Minimax and 海螺AI for higher-quality outputs. The user doesn’t pick the model — the system optimizes for speed and quality automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Dollar
&lt;/h2&gt;

&lt;p&gt;On July 13th, I woke up to an email from Creem: &lt;em&gt;"You received a payment."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It was $4.99. One user bought the Starter plan.&lt;/p&gt;

&lt;p&gt;That small amount changed everything. Before that, I was optimizing SEO, tweaking landing page colors, and watching Google Analytics like a hawk. After that, I realized: &lt;strong&gt;the only metric that matters is whether someone is willing to pay.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The user came from organic search. I had spent weeks writing blog posts, submitting to AI directories, and building backlinks. No ads. Just content and patience.&lt;/p&gt;




&lt;h2&gt;
  
  
  3 Things I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start with one feature, not ten
&lt;/h3&gt;

&lt;p&gt;My original plan was an "all-in-one AI creative suite" — image generation, video generation, editing tools, the works. I stripped it down to video only. If I had waited for the full vision, I'd still be coding instead of charging.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. SEO is a patience game
&lt;/h3&gt;

&lt;p&gt;I stopped Google Ads after burning through budget with zero conversions. Switched to long-tail SEO: "image to video AI free", "text to video generator no signup". Slow traffic, but free and compounding.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Payment integration is part of the product
&lt;/h3&gt;

&lt;p&gt;I spent too much time perfecting the UI before integrating Creem. The moment payments went live, my mindset shifted from "hobby project" to "business." Do it early. Even if nobody pays, the infrastructure being ready changes how you build.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Image generation is on the roadmap (finally expanding beyond video)&lt;/li&gt;
&lt;li&gt;Better mobile experience (most traffic is mobile)&lt;/li&gt;
&lt;li&gt;More video models — I'm watching Kling 2.6 and Veo-3 closely&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you're curious, &lt;a href="https://www.froging.ai" rel="noopener noreferrer"&gt;Froging AI&lt;/a&gt; is live. You can generate a few videos for free without signing up.&lt;/p&gt;

&lt;p&gt;If you're also building a side project, drop a comment. I read every one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tags: #ai #webdev #nextjs #saas #sideproject #startup #indiedev&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>nextjs</category>
      <category>saas</category>
    </item>
    <item>
      <title>Building an AI Image Detector with Next.js: Lessons from Shipping Fast</title>
      <dc:creator>Jasper Smith</dc:creator>
      <pubDate>Tue, 30 Jun 2026 16:13:44 +0000</pubDate>
      <link>https://dev.to/jaspersmith/building-an-ai-image-detector-with-nextjs-lessons-from-shipping-fast-4f7j</link>
      <guid>https://dev.to/jaspersmith/building-an-ai-image-detector-with-nextjs-lessons-from-shipping-fast-4f7j</guid>
      <description>&lt;p&gt;I recently shipped &lt;a href="https://www.aipicturechecker.com" rel="noopener noreferrer"&gt;&lt;strong&gt;AI Picture Checker&lt;/strong&gt;&lt;/a&gt; — a free online &lt;strong&gt;AI Image Detector&lt;/strong&gt; that identifies whether a photo was generated by AI and, more importantly, &lt;em&gt;which&lt;/em&gt; model created it (Midjourney, DALL·E, Gemini, Flux, etc.).&lt;/p&gt;

&lt;p&gt;Here is what I learned from building and launching it in under two weeks.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most &lt;strong&gt;AI image detectors&lt;/strong&gt; give you a vague "AI vs Real" percentage. That is fine for curiosity, but useless when you are moderating user uploads or verifying a news photo. You need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this actually synthetic?&lt;/li&gt;
&lt;li&gt;Which generator was used?&lt;/li&gt;
&lt;li&gt;Is it a deepfake or a fully generated image?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Existing tools either hide results behind paywalls or require accounts before you can even test them.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14&lt;/strong&gt; (App Router) + TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase&lt;/strong&gt; — Auth, Postgres, and file storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — Edge functions and global CDN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection models&lt;/strong&gt; — Ensemble of Hive AI API + custom CLIP-based classifier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharp&lt;/strong&gt; — Client-side image preprocessing before upload&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  One Technical Lesson
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do not trust a single model.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During testing, one commercial API scored 96% accuracy on Midjourney v6 images but dropped to 62% on Gemini-generated photos. Inpainted images (real photo + AI-edited regions) fooled it completely.&lt;/p&gt;

&lt;p&gt;The fix was an ensemble approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run multiple detectors in parallel&lt;/li&gt;
&lt;li&gt;Weight scores by model confidence&lt;/li&gt;
&lt;li&gt;Fall back to metadata checks (C2PA signatures) when available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pushed the blended accuracy above 90% across the board, though it increased the per-request cost to roughly $0.005–$0.008.&lt;/p&gt;




&lt;h2&gt;
  
  
  The SEO Play
&lt;/h2&gt;

&lt;p&gt;I launched the landing page before the detection API was fully integrated. Why? To start indexing immediately.&lt;/p&gt;

&lt;p&gt;I published a dozen blog posts targeting long-tail keywords — &lt;code&gt;AI Image Detector&lt;/code&gt;, &lt;code&gt;AI Picture Checker&lt;/code&gt;, &lt;code&gt;check if image is AI generated&lt;/code&gt;, &lt;code&gt;deepfake detection online&lt;/code&gt; — and pointed internal links to the main tool.&lt;/p&gt;

&lt;p&gt;Three months later, organic traffic is the primary growth channel. For solo developers, &lt;strong&gt;content-first, feature-second&lt;/strong&gt; is a viable launch strategy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;You can &lt;a href="https://www.aipicturechecker.com" rel="noopener noreferrer"&gt;&lt;strong&gt;check if an image is AI-generated&lt;/strong&gt;&lt;/a&gt; at &lt;strong&gt;aipicturechecker.com&lt;/strong&gt;. No signup is required for the first few checks. Upload a JPG, PNG, or WebP (up to 10MB) and get results in seconds.&lt;/p&gt;

&lt;p&gt;If you find an image that fools the detector, drop a link in the comments — I use edge cases like that to retrain the model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.aipicturechecker.com" rel="noopener noreferrer"&gt;&lt;strong&gt;AI Picture Checker&lt;/strong&gt;&lt;/a&gt; — Free &lt;strong&gt;AI Image Detector&lt;/strong&gt; with source attribution&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hivemoderation.com/" rel="noopener noreferrer"&gt;Hive Moderation&lt;/a&gt; — Enterprise detection API&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://c2pa.org/" rel="noopener noreferrer"&gt;C2PA&lt;/a&gt; — Content authenticity standards&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Building AI tools at LuTa Tech. Follow for more write-ups on shipping fast, Next.js architecture, and generative media.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Gemini Omni Video Generator: Create Cinematic AI Videos with Veo</title>
      <dc:creator>Jasper Smith</dc:creator>
      <pubDate>Sat, 23 May 2026 16:40:27 +0000</pubDate>
      <link>https://dev.to/jaspersmith/gemini-omni-video-generator-create-cinematic-ai-videos-with-veo-1ahf</link>
      <guid>https://dev.to/jaspersmith/gemini-omni-video-generator-create-cinematic-ai-videos-with-veo-1ahf</guid>
      <description>&lt;h2&gt;
  
  
  Introducing Gemini Omni Video Generator
&lt;/h2&gt;

&lt;p&gt;AI video creation has just taken a massive leap forward. &lt;a href="https://www.geminiomnivideo.io/" rel="noopener noreferrer"&gt;Gemini Omni Video Generator&lt;/a&gt; is a powerful AI-powered platform that lets you create stunning cinematic videos from simple text prompts and images — powered by Google's Veo models.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can You Create?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cinematic Videos&lt;/strong&gt; — Generate high-quality, movie-like scenes from text descriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image-to-Video Animations&lt;/strong&gt; — Bring your static images to life with fluid motion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short-Form Social Content&lt;/strong&gt; — Create engaging clips for Instagram, TikTok, and YouTube Shorts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marketing Videos&lt;/strong&gt; — Produce professional promotional content in seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creative Storytelling&lt;/strong&gt; — Visualize narratives with AI-generated scenes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Gemini Omni?
&lt;/h2&gt;

&lt;p&gt;Built on top of Google's &lt;strong&gt;Gemini Omni&lt;/strong&gt; and &lt;strong&gt;Veo&lt;/strong&gt; AI models, this platform delivers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast, professional AI video production&lt;/li&gt;
&lt;li&gt;Simple, intuitive workflows&lt;/li&gt;
&lt;li&gt;High-quality output with realistic motion&lt;/li&gt;
&lt;li&gt;No complex editing skills required&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who Is It For?
&lt;/h2&gt;

&lt;p&gt;Whether you're a &lt;strong&gt;content creator&lt;/strong&gt;, &lt;strong&gt;marketer&lt;/strong&gt;, or part of a &lt;strong&gt;content team&lt;/strong&gt;, Gemini Omni Video Generator streamlines your video production pipeline. No more spending hours on animation — describe what you want, and let AI bring your vision to life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;Ready to create your first AI video? Visit &lt;a href="https://www.geminiomnivideo.io/" rel="noopener noreferrer"&gt;geminiomnivideo.io&lt;/a&gt; and start generating cinematic content in seconds.&lt;/p&gt;

</description>
      <category>veo</category>
    </item>
    <item>
      <title>We Built an AI Image-to-Video Generator in 2026: Architecture, Challenges, and Lessons Learned</title>
      <dc:creator>Jasper Smith</dc:creator>
      <pubDate>Tue, 07 Apr 2026 13:05:46 +0000</pubDate>
      <link>https://dev.to/jaspersmith/we-built-an-ai-image-to-video-generator-in-2026-architecture-challenges-and-lessons-learned-4jpk</link>
      <guid>https://dev.to/jaspersmith/we-built-an-ai-image-to-video-generator-in-2026-architecture-challenges-and-lessons-learned-4jpk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmran0u0v0gor5kykmq9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmran0u0v0gor5kykmq9c.png" alt=" " width="799" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We just launched &lt;strong&gt;&lt;a href="https://www.aiimagetovideo.video/" rel="noopener noreferrer"&gt;AI Image to Video&lt;/a&gt;&lt;/strong&gt;, a free tool that transforms static images into professional videos using AI. Built by &lt;a href="https://www.luta-tech.com/" rel="noopener noreferrer"&gt;LuTa Tech&lt;/a&gt;, it's designed for developers and creators who need quick, high-quality video content without complex editing workflows.&lt;/p&gt;

&lt;p&gt;Try it here 👉 &lt;a href="https://www.aiimagetovideo.video/" rel="noopener noreferrer"&gt;https://www.aiimagetovideo.video/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;As developers building content tools, we kept hitting the same wall: &lt;strong&gt;video creation is hard&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Whether you're building a landing page, creating social media content, or prototyping an app, you need video assets. But traditional video editing requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expensive software (After Effects, Premiere Pro)&lt;/li&gt;
&lt;li&gt;Steep learning curves&lt;/li&gt;
&lt;li&gt;Hours of manual work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We wanted something as simple as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload an image&lt;/li&gt;
&lt;li&gt;Write a prompt ("make the ocean waves move")&lt;/li&gt;
&lt;li&gt;Get a video in seconds&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So we built it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Frontend Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React + TypeScript&lt;/strong&gt; - Type safety for complex canvas operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebGL/Canvas API&lt;/strong&gt; - Real-time preview and image processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; - Rapid UI development&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AI/Backend
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python FastAPI&lt;/strong&gt; - High-performance async video processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diffusion Models&lt;/strong&gt; - Custom fine-tuned models for motion generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FFmpeg&lt;/strong&gt; - Video encoding and optimization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS S3 + CloudFront&lt;/strong&gt; - Asset storage and global CDN delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Tricky Parts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Browser-side Image Processing&lt;/strong&gt;&lt;br&gt;
Handling large images (4K+) in the browser without crashing tabs was challenging. We implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web Workers for off-main-thread processing&lt;/li&gt;
&lt;li&gt;Progressive image loading&lt;/li&gt;
&lt;li&gt;Canvas tiling for memory efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Prompt Engineering for Motion&lt;/strong&gt;&lt;br&gt;
Getting AI to understand "how things should move" requires careful prompt structuring. We built a prompt enhancement layer that translates user inputs into model-optimized instructions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Video Encoding in the Cloud&lt;/strong&gt;&lt;br&gt;
Balancing quality vs. processing time vs. cost. We ended up with a tiered system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast preview (480p, 5s generation)&lt;/li&gt;
&lt;li&gt;High quality (1080p, 30s generation)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.aiimagetovideo.video/" rel="noopener noreferrer"&gt;AI Image to Video&lt;/a&gt; lets you:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Upload any image&lt;/strong&gt; (JPG, PNG, WebP)&lt;br&gt;
✅ &lt;strong&gt;Describe motion with natural language&lt;/strong&gt; ("gentle waves", "falling leaves")&lt;br&gt;
✅ &lt;strong&gt;Get MP4 output&lt;/strong&gt; in seconds&lt;br&gt;
✅ &lt;strong&gt;Use it for free&lt;/strong&gt; (with reasonable limits for server costs)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases we've seen:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;E-commerce product demos&lt;/li&gt;
&lt;li&gt;Social media content creation&lt;/li&gt;
&lt;li&gt;Game asset generation&lt;/li&gt;
&lt;li&gt;Prototyping video concepts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About LuTa Tech
&lt;/h2&gt;

&lt;p&gt;This project is built by &lt;a href="https://www.luta-tech.com/" rel="noopener noreferrer"&gt;LuTa Tech&lt;/a&gt;, a small team focused on making AI creative tools accessible to developers and creators.&lt;/p&gt;

&lt;p&gt;We're not trying to replace professional video editors. Instead, we're building the &lt;strong&gt;"quick prototype to video"&lt;/strong&gt; layer that every developer needs in their toolkit.&lt;/p&gt;

&lt;p&gt;Check out our other projects at &lt;a href="https://www.luta-tech.com/" rel="noopener noreferrer"&gt;luta-tech.com&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It &amp;amp; Give Feedback
&lt;/h2&gt;

&lt;p&gt;The tool is live and free to try: &lt;strong&gt;&lt;a href="https://www.aiimagetovideo.video/" rel="noopener noreferrer"&gt;https://www.aiimagetovideo.video/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have an API coming soon (join the waitlist on the site)&lt;/li&gt;
&lt;li&gt;If you're building something similar, happy to share more technical details in the comments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's next?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Video-to-video translation&lt;/li&gt;
&lt;li&gt;Batch processing API&lt;/li&gt;
&lt;li&gt;Open-source some of our preprocessing tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop your thoughts in the comments! What would you use this for?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post is not sponsored. Just sharing a tool we built that might help fellow developers.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>machinelearning</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
