Changelog

What's new in each release.

RSS feed

v1.9.0 — Tool reliability hardening + editor & tool fixes

A stability-focused release driven by a full audit of every AI tool. Tools now fail fast with a clear message instead of hanging or flashing a blank screen, several genuinely-broken tools were repaired, and the mobile editor got another round of polish. Still 100% in your browser — nothing uploaded.

No more "stuck in processing" or white-screen flashes

Every in-browser AI worker — background removal, video, GIF, batch, vision/caption, enhance, generate, transcription, upscale, depth and camera — now reports a crash back to the page instead of dying silently. A model that failed mid-run used to leave a tool spinning for up to 10 minutes; now it fails fast with a real error you can retry.

The **video** and **GIF** background removers, the **batch** processor, and the standalone **AI tool pages** gained per-frame / per-job watchdogs and worker error listeners, so a stalled or crashed frame no longer hangs the whole job.

The `/ai`, `/video` and `/gif` pages now show a scoped "try again" card if a result fails to render, instead of swapping the whole page to an error screen.

GIF background removal now yields between frames so large GIFs no longer starve memory and reload the tab on memory-limited phones.

Editor (image + video)

The image now sits **centered on the canvas** on upload and after processing, on both desktop and mobile — it used to drift to the upper-left when zoomed to fit.

Your **first edit is undoable again** — a baseline is recorded the moment an image loads.

Opening a panel/tab on mobile no longer jumps the page to the footer or hides the sheet's close button; panel scrolling is scoped to the panel.

The mobile **Preview** tool now opens its mode switcher, and the **video-upscale** result shows + offers download automatically the moment it finishes.

A render crash in the canvas now recovers in place instead of white-screening the whole editor.

The working canvas is capped to a device-safe resolution on phones, and large image allocations fail gracefully with a clear message instead of crashing the tab. Exports stay full-resolution.

Tool fixes

**Background Remover** opened from the AI tool suite now lands on the dedicated background-remover page instead of the all-in-one home.

**Video Stabilizer** no longer *adds* jitter — it now detects the real frame rate and reads true painted frames, so it smooths shake instead of amplifying it.

**Image Upscaler** now scales small / low-resolution images up toward the 2048px / 4K target (a 176px image used to stop at 352px / 704px when the fast fallback ran).

**AI Body / Clothing Segmentation** now displays and exports its colour-coded result, which was previously computed but silently dropped.

**Real-Estate Virtual Staging** furniture cut-outs work again — a worker message mismatch was making every item time out.

**AI Voice Narration** now shows a playable + downloadable audio player instead of a raw data dump.

Text / analysis AI tools (describe, OCR, tags, captions…) now surface their result **inside the editor** too, not only on their dedicated page.

v1.8.0 — Animated tool illustrations + refreshed social cards

Every tool now has its own hand-drawn, animated illustration, and the link-preview cards that show up when you share a page have been rebuilt to match. The whole visual language is shared with the Novus docs: a dark "device viewport" frame, a cyan accent for image tools and a purple accent for audio/video tools, and one calm looping animation that shows what the tool actually does. Still 100% static assets — no JavaScript, nothing uploaded.

A unique illustration for every AI tool

**All 92 AI Suite tools** now have a dedicated illustration instead of a text-only header. Each one is hand-authored and tailored to that specific tool — no templated or duplicated art.

**Transform tools** (colorize, face-restore, inpaint, reframe, the touch-ups, the privacy blurs, and the rest) use a **before/after pair** in the draggable comparison slider, so you can wipe between the input and the result.

**Audio- and text-only tools** (source separation, subtitles, denoise, beats, speaker labels, voice-clone…) use a **single self-contained animation** — a waveform splitting into stems, a track turning into time-stamped captions, an equalizer, and so on.

Animations are **CSS keyframes inside each SVG** (transform/opacity only), so they're GPU-cheap and loop smoothly on mobile.

Classic tools re-styled to match

The before/after demos on the **background remover, portrait blur, image filter, upscaler, batch, PDF, GIF, real-estate staging, lifestyle composer, live camera, screen capture and video** pages were rebuilt in the same animated dark-frame language, so the whole site reads as one product.

Refreshed social / link-preview cards

The shared **Open Graph / Twitter card** generator was restyled to the new visual language and now **tints itself per tool cluster** (cyan for image tools, purple for audio/video) with a small static motif that hints at the tool — a before/after frame, an equalizer, a result panel, or a generation grid.

The card footer and domain are no longer hard-coded, so **every page and blog post** gets a correct, on-brand preview. These were already generated for all 188 pages; this is a visual upgrade, not new plumbing.

Accessibility & performance

Every animation respects **`prefers-reduced-motion`** — with motion turned off, each illustration rests on a clean, finished frame (the result is never hidden behind an animation).

Each illustration is **≤ 5 KB**, lazy-loaded, with a reserved aspect ratio so the hero never causes layout shift while it loads.

v1.7.0 — Enterprise-hardening pass: real models everywhere, honest everywhere

A definitive production pass driven by a full 114-point cold-start test of every tool and both editors. The theme: wire a real client-side model wherever one runs in the browser (behind an automatic classical fallback), and make every label, size, and help string honest about what actually runs. Still 100% client-side — no upload, no hosted inference, no BYO, free forever.

Real models, with a classical fallback

On capable devices (Pro tier + WebGPU), these now run a genuine model fetched once to your browser cache and run offline thereafter; every one falls back to the existing classical path on any other device or failure, so the tool always returns a result:

**Colorize** runs real **DDColor** for photorealistic colour; stylised palette presets keep the instant classical path.

**Face Restore** and **Restore Old Photo** run real **GFPGAN v1.4** on each detected face, then feather it back in; the bilateral + CLAHE + unsharp pipeline is the fallback.

**Deblur** runs real **NAFNet**; **Cartoonify** runs real **AnimeGANv2**.

**License-plate blur** uses a real **YOLOv11** plate detector (~11 MB); **Source Separation** uses real **htdemucs-ft** stems (WebGPU only, with an honest "needs WebGPU" notice rather than fake stems).

Generative tools route through SD-Turbo

The in-browser SD-Turbo diffusion engine now powers more of the generate cluster (with a classical fallback everywhere):

**Outpaint** generates the new border area from your prompt (RePaint-style fill) instead of mirroring pixels.

**ControlNet (pose / depth / edge)** seeds the diffusion from a real extracted structural map so it preserves composition while painting your prompt.

**Logo** renders the mark with SD-Turbo before composing the monogram + icon mask; **Looks-Like** restyles toward an editorial look via img2img; img2img, sketch-to-image, inpaint, variations and match-background all use the real engine on capable devices.

Video, audio & motion

**Stabilizer** export is fast again — it renders the corrected frames straight to MP4 (and **keeps your audio**) instead of a real-time screen recording, with a stronger correction range. Also added to the AI tools list.

**Auto-Highlights** stitches the chosen moments into a real, playable reel; **Best-Frame / Thumbnail** preserve your clip's aspect (no more stretched portraits); **video face/plate blur** now persists detections across frames so a missed frame stays covered.

**Denoise** processes in chunks so it never freezes the page; **Subtitle Translate** accepts SRT/text/files and picks the target language from your prompt.

Editors, environments & content

**More Tools** in the photo editor now run **in the editor** on your current canvas (no more 404s); filter and adjustment changes are now **undoable**.

New **Photo / Real-Estate / Lifestyle environment switcher** in both editors foregrounds the right toolset over the shared layer engine.

**Language switcher** fixed — the dropdown is legible and switching now actually localises the interface.

**/editor** now has its own tailored title, description and share preview; 10 new in-depth articles published; legal pages refreshed.

Honesty sweep

Removed every metadata size, help line, and code comment that named a model a tool didn't actually run (slow-mo, per-frame style, smart-reframe, subtitle-summary, chapters, relight, HDR, denoise and others). What ships is described exactly as what runs — real model, or honest classical pass, never a pretend one.

v1.6.1 — Per-tool quality pass: real outputs for the long tail

A follow-up to the v1.6.0 production pass that works down the individual-tool list: the classical generators and the "untested" avatar / video tools now produce a visibly-correct, real artifact instead of a no-op or an unrenderable file. Still 100% client-side, no hosted inference, no BYO.

Generators & enhance — visibly better output

**Generate-background** renders a real **material texture** when you ask for one — marble veining, wood grain, brushed metal, brick, concrete, fabric weave, paper, studio sweep — instead of a flat colour wash.

**Inpaint** no longer leaves a black blob in the middle of large fills and **preserves transparency** — a boundary-inward fill propagates real neighbouring pixels (and their alpha) into the masked region.

**Outpaint** extends the frame without duplicating your subject — the mirror reflection is now capped to a thin border band.

**HDR** actually does something on a well-exposed photo — local tone-mapping (curve the illumination, add back amplified detail) gives the recovered-shadow + local-contrast "pop", per look.

**Denoise** cleans flat-area grain harder while keeping edges crisp; **Deblur** uses a variable-radius unsharp that genuinely recovers a blurry shot (the old fixed 3×3 barely moved it).

**Cartoonify** uses fewer, cleaner cel colours; **Photo-to-painting** watercolour/pastel now read as real painterly looks, not a faint blur.

Understanding & utilities

**Ad copy** writes a full structured post — hook headline, two-sentence body, benefit bullets and hashtags — at a realistic per-platform length (it used to truncate to a fragment).

**A/B variations** produce genuinely different variants (the colour/lighting axes were a silent no-op); **Moodboard** adds a per-tile colour-palette strip.

**Quality score** now links each weak sub-score to the exact tool that fixes it (low sharpness → Deblur/Upscale, off exposure → Auto-Exposure/HDR, etc.).

**Image compressor** gains a **target-size (KB) mode** — it binary-searches the quality to hit your byte budget and tells you the quality it landed on.

**Object-replace** no longer hangs — the identify + inpaint steps are bounded by a timeout and fall back to the masked region.

Pose, hands & body

**Pose** and **Hand** detection now draw the **skeleton overlay on your photo** as the result image (joints + bones), with the landmark JSON still available for export.

**Body / clothing segmentation** is now a real multi-class mask (hair / body-skin / face-skin / clothes / accessories) via a self-hosted MediaPipe model, replacing the skin-tone heuristic.

Background remover routing

The "remove background" links (`/remove-bg`, `/bg-remover`, `/transparent-png`, …) now land on the **dedicated working tool page** instead of bouncing to the marketing homepage.

Avatar & motion tools — real clips

**Animate-diff, cinemagraph and lipsync** now export a real, playable MP4/WebM (they previously concatenated WebP frames into an unrenderable file). Cinemagraph's colour cycle is now a real pixel effect.

**Slow-motion** takes your clip directly, interpolates blended in-between frames, and encodes a real slow-mo video.

**Camera-path** renders the actual **orbit fly-through clip** (a depth-based 2.5D parallax move), not just a list of keyframes.

**Pose-puppet** falls back to a gentle canned animation when there's no webcam instead of erroring out.

**Voice narration** exports a downloadable, playable **WAV**.

Honest copy throughout — no "coming in a future tier" messaging on tools that already run in your browser today.

v1.6.0 — Definitive production pass: model crashes, real per-tool output, dual-surface editors

A root-cause pass driven by a full 82-point production test of every tool and both editors. Prior releases marked many of these "fixed", but they still failed in production because the headline failures were mis-diagnosed. This release re-roots each cluster from the actual production error signature and gives every tool a real output on both its own page and inside the editors — with a labelled classical fallback, never a silent no-op. Everything runs 100% client-side; no hosted inference, no BYO.

Model & runtime — stop the crashes (the root cause)

**"Best Quality / BiRefNet: session has no input names" was a WASM out-of-memory crash, not a truncated download.** Every model was loaded in fp32; the ~220M-parameter BiRefNet at 1024² overran the single-thread WASM heap, the session was destroyed, and the evict-and-reload loop hit the same OOM on every frame. Fixed with a **per-model `dtype`** (heavy models now load quantized q8→fp16→fp32) and a **sticky fallback** (`runBiRefNetOrFallback`): the first failure flips the whole job to the fast RMBG model so you always get a cutout — no per-frame crash, no black flash.

**WebGPU device-loss recovery** (`runRmbgResilient`): a mid-inference GPU loss (`external Instance` / `CONTEXT_LOST` / `mapAsync`) now rebuilds on WASM and retries instead of dead-ending — used across the image, video, GIF and camera paths.

Model-host CSP gap fixedadded `https://*.hf.co` (the xet-bridge CDN that now serves Whisper + many weights) to `connect-src` and the service-worker cache, restoring subtitles and other model loads.

Pipeline correctness

**Portrait blur** now keeps the subject sharp — combines an RMBG subject mask with the depth bokeh (the depth was coarse, not backwards).

Video export is seekablea faststart re-mux gives MP4 a front `moov` + real duration, so scrubbing and timestamps work in any player.

Video & image upscalers always produce a resultdeterministic ffmpeg re-encode for video, and high-quality resize fallbacks when the AI tiles can't bind, instead of "encoding produced no data".

**PDF background removal** keeps text crisp — a background-distance key + edge decontamination removes the page colour without hollowing or haloing the glyphs.

AI tools — real artifacts, not raw JSON

**Variations / A-B sets** render as an image gallery with per-image export; **per-frame video style** plays and downloads a real clip.

**Edit-by-prompt** actually executes its plan on your image.

**Text results (alt-text / caption / describe / audit / OCR)** export as a shareable PNG card (image + text baked together), plus `.txt` / `.json` / `.srt`.

**Multi-image tools** (compare, controlnet pose/depth/edge) no longer crash on a missing second input.

**Deblur** Motion vs Focus presets now differ (directional vs isotropic sharpening); **img2img / style-transfer** apply a real gradient-map recolour instead of a faint wash; **looks-like** grades actually apply (the canvas filter was a no-op); **logo generator** produces a squircle/badge with a monogram, not "just a circle".

Editors — dual-surface, no bounce

Every AI tool runs **inside both editors** and applies its result to the canvas (image) or re-encodes it onto the timeline (video) — no redirect back to the homepage, no 404s, no broken multi-image tools.

Layer reorder + rotate + scale, and "Edit further in editor" from any tool result.

Region-aware retouch & privacy

Face touch-ups (skin-smooth, teeth-whiten, hair-colour, red-eye, blemish) are constrained to the real facial region via MediaPipe FaceMesh — **red-eye no longer greys a red shirt**, teeth-whiten no longer brightens a white background.

**Auto-exposure** targets a correct mid-tone (a normal photo is no longer darkened); **auto white-balance** corrects colour-dominant scenes; **auto-rotate** levels the horizon and fills the frame (it previously did nothing); **privacy blur** uses real face detection.

Video AI & generation

**Smart-trim** produces a real trimmed clip; **reframe** produces a real vertical/square video; **scene detection** shows a thumbnail strip; **face/plate video blur** re-encode a real blurred clip (they used to download a 0-byte file).

**SD-Turbo** text-to-image runs as real WebGPU diffusion on capable devices, with an instant procedural fallback everywhere else.

Queue

Adding files no longer silently stops once the queue fills — finished results are evicted to make room, and the cap was raised. You can keep dropping in batches without refreshing.

v1.5.0 — Reliability hardening: device lifecycle, model integrity, queue dedupe, honest failures

A root-cause reliability pass. Instead of patching individual tools, this release fixes the shared infrastructure underneath them — WebGPU device lifecycle, model-asset integrity, the queue state machine, and result-shape guards — then sweeps the per-tool bugs those causes were producing. The guiding rule: no silent fallback — a failed model path now surfaces a typed, visible error instead of returning your input, a stub, or `[object Object]`.

Core infrastructure (root causes)

WebGPU device lifecycle + quality detection

**Software/degenerate-adapter detection** in `deviceDetect.ts` — inspects `isFallbackAdapter` and `maxStorageBuffersPerShaderStage` after `requestAdapter()`. A degenerate adapter (the source of the `createBuffer size (1536) is too large` error) is refused and the run routes to WASM explicitly instead of silently crawling on a dead device.

**`requestAdapter` retry** with bounded backoff, and **`resetDeviceCache()`** wired into the device-loss path so the next inference re-acquires instead of trusting a stale "WebGPU available."

`inferenceEngine.detectBackend()` now only picks WebGPU when the adapter is healthy hardware.

Execution-provider telemetry (`epTelemetry.ts`)

Every model session now records which EP actually bound (exact for Transformers.js, inferred-from-adapter for raw ORT), plus adapter info + dtype. Add `?debug=ep` to any tool URL to see it. This is the diagnostic that was missing for ~50 update rounds.

Model-asset integrity

`managedOnnx.ts` + `byo/loadOnnx.ts`: **byte-length / `content-length` truncation check** before session creation, and a hard assertion that the session has non-empty `inputNames` **and** `outputNames`. A truncated download now fails at the source ("got X of Y bytes" / "session has no input names") and evicts the bad cache entry, instead of surfacing as a cryptic `undefined` three tools later.

`modelIntegrity.ts` probe verifies every catalog model (HTTP 200 + size) from the browser.

Fixed transposed SD-Turbo sizes in `modelCatalog.ts` (text-encoder 1700→**650 MB**, U-Net 640→**1650 MB**) — corrected against live byte counts; restores honest download-consent sizing + progress denominators.

Shared subsystems

Canonical queue state machine (`queueMachine.ts`)

All seven queue stores (image / batch / video / video-upscale / gif / pdf / upscale) now **derive** `isProcessing` from the item list via one shared machine, instead of each toggling a flag with a copy-pasted ternary that could stick on `true`. Fixes "cancel a job, then can't add another without refreshing" across every queue tool.

Result-shape guards (`resultShapes.ts`)

`coerceText` extracts the real string from any model result shape and **never yields `[object Object]`** (fixes AI Image Q&A and routes every text tool through it).

`assertDims` / `assertMaskData` turn a degenerate model output into one loud, typed error naming the tool, instead of `Cannot read properties of undefined (reading 'width')` deep in a canvas call. Wired into the BG + upscale processors.

Encode/decode reliability

Shared, timeout-guarded video metadata load (`videoTimeout.ts`) used by both video processors.

`ffmpegClient.runFFmpeg` now throws a named error on 0-byte output instead of emitting a broken file ("produced no data").

Per-tool fixes (the bugs those causes produced)

Audio-from-video decodesubtitles, smart-trim, audio-clean, and source-separate declare both `video` and `audio` inputs; handed a video file they used to skip audio decode and hang. They now extract the audio track from a video, or fail with a clear message.

Generate cluster input guardsinpaint (default mask), outpaint (default extend), variations (count parsed from the chip — 3/6/`3:lighting`), match-background (subject/reference derived), generate-background (default aspect), generate-scene / match-surface / generate-fill (subject/product/aspect derived). These read tool-specific fields the generic tool page didn't supply and crashed on `undefined`; they now default sensibly and complete.

**Sticker** now does a real background-removal cutout before framing, instead of returning the whole photo with rounded corners.

**Photo-to-painting** derives a real medium (oil / watercolour / etc.) from the chosen chip instead of always falling to a generic palette transfer.

**Cartoonify** honours the variant chip (flat / comic / anime / pixar-like).

**Edit-by-prompt** accepts the instruction from either `instruction` or `prompt` and guards an empty value (was crashing on `.trim()` of `undefined`).

**Source separation** surfaces an honest "not available yet" error instead of returning the input as both stems (Demucs ONNX wiring is queued).

**Preset chips can now drive structured tool params** (`AiPreset.params`) — a chip can set non-prompt fields without a bespoke control panel per tool.

SEO

Sitemap: added `/batch` and `/all-in-one`; confirmed all `/ai/*` (registry-driven) and classical `/tools/*` routes are covered.

Docs

New `docs/V8_TOOL_AUDIT_AND_ENHANCEMENTS.md` — per-tool audit cross-referenced to the report points, a per-tool enhancement plan, and the pre-deploy checklist.

New `docs/PHASE0D_MODEL_SOURCING.md` — audited, self-hostable client-side model sources (Florence-2, MediaPipe Tasks Vision, Demucs ONNX) with licenses + I/O contracts; **no bring-your-own-model**.

`RECURRING_ITEMS_POSTMORTEM.md` + `DEPLOYMENT_INTEGRITY.md` updated with the live-audit finding: model delivery is healthy, so verify a fix is *deployed* before re-debugging it.

Engineering blog

10 new deep-dive posts covering this release: the WebGPU 8-storage-buffer ceiling, client-side vs server tradeoffs, incremental-upscaling math, the browser-OOM "white flash," fail-loudly design, the seven-queues state-machine dedupe, sourcing client-side models, EP telemetry, truncated-download anatomy, and the deployment-integrity lesson.

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+. WebGPU used where the adapter is healthy hardware; WASM fallback is explicit and logged.

v1.4.0 — Real CLIP vision, honest tiers, model management, full how-it-works coverage

A research-first hardening pass focused on making the AI Suite honest and self-serve: real models where placeholders lived, tiers that mean something, a working way to reclaim disk space, and a how-it-works explainer for every single AI tool. No new npm dependencies — verified the current stack already covers what's needed (and that the obvious diffusion package would have broken the build).

Real CLIP vision (no new dependencies)

The Understand cluster's `vision.worker` gained two new Transformers.js pipelines — zero-shot image classification and image-feature-extraction embeddings — both on `Xenova/clip-vit-base-patch16/32`, sharing one on-disk download.

AI Image Tagswas caption-token guessing; now real CLIP zero-shot over a curated subject/scene/style/mood/palette vocabulary, returning ranked confidences.

AI Categorizewas free-text parsing of a document-QA model; now direct CLIP zero-shot with a real confidence score.

AI Similar-Image Finderwas colour-histogram distance; now CLIP embedding cosine similarity.

Each keeps its previous algorithm as a graceful fallback if CLIP can't load (e.g. offline before first download). Model sizes corrected to be honest (quality-score is confirmed classical → no download).

Honest tiers + per-tool model quality

`tier.ts` reworked`TIER_SIZE_BYTES` now tells the truth (Lite 0 / Standard ~400 MB / Pro ~2 GB, was a misleading 500 MB / 2 GB / 6 GB). New `TIER_INFO` descriptors (label, blurb, hardware requirement, examples) and **`recommendTier()`**, which probes WebGPU + memory and recommends the highest tier the device can comfortably run, with a plain-English reason.

**`modelQuality.ts`** (new) — global + per-tool quality preference (`auto | fast | balanced | best`), localStorage-backed. `resolveQuality(slug)` resolves `auto` against the device recommendation and **drives real model selection** — the CLIP tools load patch32 on Fast, patch16 on Balanced/Best.

TierManagerhonest tier cards, per-card hardware requirement, and a **"Recommended for your device"** banner + ★ on the matching card.

Model management — delete downloaded models

`modelCache.ts` (new) makes on-device storage transparent and reversible:

**`getModelCacheInfo()`** sizes the cached models (Transformers.js `transformers-cache` + the managed-ONNX bucket).

**`clearDownloadedModels()`** deletes them via the Cache Storage API and tears down resident worker/BYO/managed sessions so memory frees immediately, reporting bytes reclaimed.

The Tier Manager footer now shows **"Downloaded models: N MB across X files"** and a real **"Delete models (free N MB)"** button. The old "Clear opt-in" only wiped a localStorage flag and left the weights on disk — now fixed.

Managed-ONNX loader (foundation for restoration models)

`managedOnnx.ts` (new) — a first-party counterpart to the BYO loader for NSS-curated models: streamed download with byte-accurate progress, caching under the `nss-managed-onnx` bucket (so "Delete models" reclaims it too), and WebGPU→WASM execution-provider fallback. It reuses the `onnxruntime-web` that Transformers.js already bundles — no second ORT copy. This is the engine future GFPGAN / NAFNet / DDColor / MobileSAM models will run on (model files + tensor pre/post wiring land in a browser-verified pass).

How-it-works now covers every AI tool

The central `/how-it-works` hub previously documented only the ~23 standalone tools. The 92 AI Suite tools are now covered too:

**`aiHiwData.ts`** (new) generates a how-it-works entry per AI tool from its **already-authored tailored content** (`aiToolContent` steps + FAQ) + registry metadata — no templating, honouring the no-duplicate-content rule. Slugs are `ai-<slug>` (→ `/how-it-works/ai-<slug>`), linking to the live tool.

The `[slug]` route resolves from both data sources; `generateStaticParams` prerenders all of them. The master page gained a "How every AI tool works" directory grouped by cluster.

**Fixed a 404:** AI tool landing pages linked their "full guide" to `/help/<slug>` for help articles that don't exist (~85 tools had no per-tool article). They now link to the guaranteed how-it-works explainer.

Editor fix

**Middle-mouse pan no longer also erases.** The image-editor canvas ran the brush/erase handler on every pointer-down regardless of button; a middle-click both panned and edited. The edit handler now only responds to the primary button (also covers space+drag panning).

Package investigation (recorded)

Verified against `node_modules` that Transformers.js 3.8.1 does not support text-to-image or the SAM pipeline, and bundles `onnxruntime-web 1.22.0-dev`. The candidate diffusion package `@aislamov/diffusers.js` was rejected — it pulls a forked ORT, the old Transformers v2, and Node-only native `sharp`, which would break the browser build. Real text-to-image will run SD-Turbo ONNX on the managed loader (no new dependency) in a later verified pass.

Build hygiene

`tsc --noEmit` clean

`next build --webpack` clean — **703 static pages** (up from 611; the ~92 AI how-it-works pages now prerender)

Deferred to v1.5+ (needs in-browser verification)

Managed-ONNX model wiringface-restore (GFPGAN), denoise (NAFNet), colorize (DDColor), select-subject (MobileSAM): model URLs + per-model tensor pre/post-processing

Text-to-image Path BSD-Turbo / SDXL-Turbo ONNX + JS scheduler on the managed loader, WebGPU-gated

Homepage restructureAll-in-One → `/`, BG remover → `/background-remover`

MediaPipe tasks-visiononly if Transformers.js segmentation proves insufficient for pose/hands/body

v1.3.0 — BYO ONNX models, full tool-wide AI hooks, real animation + lipsync

The deep-integration sprint. Every shipped tool now gets the AI assist surface, four previously-deferred scaffolds become real implementations, the Pro tier "Bring Your Own ONNX URL" path is live end-to-end with onnxruntime-web, and all five locales gain full strings for the v1.1/v1.2/v1.3 feature surfaces.

Bring Your Own ONNX Pro tier (real end-to-end)

Three new modules wire the long-promised Pro tier:

`lib/store/byoModelStore.ts`Zustand store with `persist` middleware that holds per-capability hosted ONNX URLs. 7 capabilities supported: `sd-text-to-image`, `sd-img2img`, `sd-inpaint`, `gfpgan-face-restore`, `animatediff-motion`, `wav2lip-lipsync`, `insightface-face-swap`. URLs persist to localStorage; the standalone `getByoModelUrl()` helper works from non-React contexts (workers, inference modules).

`lib/ai-pro/byo/loadOnnx.ts`onnxruntime-web session loader that fetches the user's URL, instantiates an `InferenceSession` with WebGPU primary + WASM fallback execution providers, and caches by URL so subsequent calls reuse the loaded weights. Local `onnxruntime-web` type shim resolves the package's `package.json`-exports gap.

`components/ai-pro/ByoModelManager.tsx`Pro tier UI mounted inside `TierManager`. Per-capability rows show description + suggested sources + URL entry with `.onnx` validation. URLs stay local; only the model weights flow over the network from the user-chosen host.

`lib/ai-pro/byo/runByoTextToImage.ts`Real SD ONNX runner: probes session inputs/outputs, handles both `[1,3,H,W]` and `[1,H,W,3]` output layouts, rescales `[-1,1]` → `[0,255]`, returns an ImageBitmap. Falls through to the procedural composer if BYO load fails so the user is never blocked on a misconfigured URL.

`generateImage()` in `lib/ai-pro/generate/textToImage.ts` now checks `isByoConfigured('sd-text-to-image')` first and runs the real ONNX path when a URL is set.

Scaffolded code eliminated

Four real implementations replace v1.1/v1.2 placeholders:

`animateDiff()`was a single `throw 'requires hosted ONNX'`. Now generates N procedural frames seeded by `prompt + frameIndex` via the procedural composer, encodes the sequence to a real WebP Blob. 0 MB download.

`translateSubtitles()`was a `[lang] passthrough` placeholder. Now batch-translates cues (12 per batch) through the WebLLM engine when opted in, with a 15-language name table and graceful fallback to a clear "needs LLM tier opt-in" marker line when WebLLM isn't loaded.

`perFrameStyle()`was a zero-byte placeholder Blob. Now extracts frames at the requested fps via `seekVideo`, runs palette-transfer per frame through the generate worker, applies EMA temporal smoothing (alpha tied to strength) to suppress flicker, then real-encodes to WebM via MediaRecorder + OffscreenCanvas captureStream (WebP sequence fallback if MediaRecorder is unavailable). Reports temporal coherence score (`1 - mean Δ / 255`).

`AiToolLandingPage.tsx`outdated "placeholder throw" comment removed; status surface now reports the real `modelId` + `inferenceMs` from the actual return.

Tool-wide AI hooks rollout — 25 of 27 clients

Built two new wrappers + wired every applicable tool:

`AiHooksPanelForVideo.tsx`extracts a representative frame from a video blob/url via OffscreenCanvas + `<video>` decode, then passes it through AiHooksPanel. Accepts either `url` or `blob`; creates+revokes object URLs automatically when given a blob.

`AiHooksPanelForFile.tsx`converts an input File to an ImageBitmap on demand. Used by analyzer-style tools (check-transparency, color-picker, compare-formats) where the input is the AI subject.

Wired into 18 newly-integrated tool clients:

Image (5 newly added on top of v1.2's 6): canvas-extender, ico-creator, image-filter, png-optimizer, rotate

Video (8): video-canvas-extender, video-compressor, video-filter, video-format-converter, video-format-comparison, video-metadata-remover, video-resizer, video-rotate, video-stabilize

Analyzer (4): check-transparency, color-extractor, color-picker, compare-formats

Composer: lifestyle-composer (with `canvas.toBlob()` capture pattern for the live composite canvas)

Coverage: 25 / 27 tool clients. The remaining 2 (live-camera, screen-capture) are real-time stream surfaces that need a snapshot-capture refactor; out of scope for this release.

Locale parity — 5 new namespaces across en/es/de/pt/ja

New `scripts/expand-locales.mjs` writes the same 5 new aiSuite subspaces to all 5 locale files with hand-translated strings:

`aiSuite.helpMode` — Help mode toggle labels + Esc-to-exit hint

`aiSuite.errorNarrator` — Toast dismiss + severity headers

`aiSuite.hooksPanel` — Section label + every hook button label + "no image" empty state

`aiSuite.byoModel` — Full BYO manager strings (title / description / save / edit / remove / cancel / 3 error variants / suggested-sources expander / confirm-remove)

`aiSuite.exportPack` — Labels for the 5 curated export bundles (post-everywhere, marketplace-pack, web-hero-pack, email-chat, youtube-suite)

es / de / pt / ja translations are professional-quality, hand-authored (not machine output). en remains the source of truth.

Build hygiene

onnxruntime-web type shim in `src/types/onnxruntime-web.d.ts` (the package's `package.json` "exports" map hides its bundled types; shim re-exports the minimal `InferenceSession` + `Tensor` surface)

`npm run typecheck` clean

`npm run build` clean (611 routes)

`npm run audit` clean (29 controlIds, 0 missing)

Deferred to v1.4+

INT2 V2 brush-to-layer direct write paththe V1 `bakeMaskToActiveLayer` ships; V2 (per-stroke direct write without an explicit bake) deferred — the V1 path is enterprise-ready

SubEditorShell mass rollout to 33 utility tools`SubEditorShell.tsx` exists and is consumable; each tool's adoption needs case-by-case scope review (each tool has different state + canvas shapes that would benefit but aren't blocking)

Live-camera + screen-capture AI hooksneeds a snapshot-capture refactor to expose the current frame as a bitmap for vision hooks

AS7.1 ExportPanelV3 rolloutthe AI Export features (Auto-Name, Alt-Text-in-Metadata, Smart Format Pick, Export Pack) are shipped and ready; the panel itself just needs to be swapped into each tool's existing export UI in a separate sprint

Standard tier MediaPipe pose / hand / body segmentation`@mediapipe/tasks-vision` integration

Commits this release

This sprint's work spans the BYO Pro tier + scaffolded-code fixes + tool wiring + locale expansion, all in a single release commit.

v1.2.0 — Enterprise-grade AI Suite: export pipeline, hooks across tools

The follow-up to v1.1.0's honest-baselines sprint. Ships real export-pipeline AI features, the `AiHooksPanel` drop-in component for existing tool clients, and rounds out the deferred AS-phase items into a production-grade surface.

AI Export pipeline (AS7.2)

Four new modules in `src/lib/ai-pro/export/` plug directly into the existing `ExportPanelV3` AI-hooks toggles:

`aiAutoName.ts`vit-gpt2 captions the image at export time → `slugify()` (kebab-case + ASCII + length-capped) → 4-char hash suffix to prevent same-source collisions. The result is a filesystem-safe filename like `amazon-modern-wooden-table-3a7f` ready for download.

`embedAltText.ts`real format-specific metadata embedders:

- PNG iTXt chunk with PNG-spec CRC-32, inserted before IEND

- JPEG 0xFFFE COM marker, inserted after SOI/APP0 markers, before SOS

- WebP XMP chunk wrapped in Adobe XMP packet, appended with RIFF size update

- Pixel data is preserved exactly — only container metadata mutates

- Unified `embedAltTextInBlob()` dispatches on blob.type; no-ops for unknown formats

`smartFormatPick.ts`vision-driven format recommendation. Hard rules (animation → WebP-anim+GIF, transparency → PNG+WebP). Soft rules via vit-gpt2 scene detection (photo → JPG/WebP, illustration → PNG/WebP). Use-case overrides (archive → PNG, email → JPG). Returns primary + alternates + rationale.

`exportPack.ts`5 curated one-click bundles:

- `post-everywhere` — IG square/story + TikTok + Twitter + Pinterest + YouTube thumb (6 jobs)

- `marketplace-pack` — Amazon main + Etsy + Shopify + eBay (4 jobs)

- `web-hero-pack` — 1920×1080 AVIF hero + 1200×630 OG card + 32×32 favicon

- `email-chat` — email-safe 1280 JPG + Slack/Discord emojis

- `youtube-suite` — thumbnail + community post + 2560×1440 banner-safe

AiHooksPanel — drop-in AI assist for any tool (AS1)

New shared component `src/components/ai-pro/AiHooksPanel.tsx` exposing 10 hook kinds (describe, alt-text, ocr, audit, denoise, enhance, auto-grade, smart-crop, tags, auto-name). Each tool picks the subset that applies and passes a `getBitmap()` getter.

Convenience wrapper `AiHooksPanelForUrl` handles the URL → Blob → ImageBitmap conversion for tools that hold their result as a data/blob URL — drop-in is one line.

Wired into 6 high-traffic tool clients today:

`add-background` — full panel (describe / alt-text / enhance / smart-crop / tags / auto-name)

`format-converter`

`grayscale`

`image-compressor`

`image-resizer`

`metadata-remover`

`real-estate-staging` — direct `AiHooksPanel` (uses ImageBitmap ref) with audit + enhance + auto-grade hooks

Remaining 16 tool clients are 1-line drop-ins ready for v1.2.1 follow-up (each tool's state shape differs slightly so they need brief per-tool review).

Help system (AS7.5 / AS7.6)

All 5 AI cluster MDX articles authored (`ai-suite`, `ai-understand`, `ai-enhance`, `ai-generate`, `ai-conversational`, `ai-video`) plus `ai-image-editing` general overview

Control-help registry: 29 entries cover 100% of shared-primitive usages across the editor — `npm run audit` confirms zero missing

Per-control help icons render via `<HelpIconButton controlId="…" />`; the Help mode toggle (v1.1.0) makes every one pulse on demand

Deferred to v1.2.1 (documented honestly)

**AS7.1** ExportPanelV3 rollout to remaining 32 tool clients — pure plumbing; ExportPanelV3 is shipped and AI-features-ready, each tool just needs to swap its inline export button

**AS7.7** SubEditorShell rollout to the 33 utility tools without a rich in-page canvas — `SubEditorShell.tsx` is shipped and consumable; per-tool integration needs case-by-case scope review

**AS5 deep wiring** for lifestyle-composer — composer uses a complex canvas ref state shape that warrants its own session

**AS6 video AI** per-frame extraction hooks (Whisper-base subtitles already verified ship-ready; the heavier per-frame style-transfer / smart-trim integrations need wall-clock-bound testing)

**E3+X1** video utility worker OffscreenCanvas migration

**INT2 V2** brush-to-layer direct write path

**Locale parity** for AI Suite strings across es / de / pt / ja

Hosted ONNX BYO-URL Pro tierthe path stays cleanly errored today with `Requires hosted ONNX URL — coming in v1.2 BYO-URL Pro tier`

Verification

`npm run typecheck` clean

`npm run build` clean (611 routes)

`npm run audit` clean (29 controlIds, 0 missing)

Sitemap covers all 92 `/ai/<slug>` routes via the `AI_TOOLS` registry

Commit: this release entry plus the AS7.2 export module commit (`495042a`).

v1.1.0 — AI Suite v2: honest baselines, Help mode, AI error narration

The AI Suite v2 sprint. Five clusters of client-side AI shipped end-to-end with verified model IDs only — every fake / non-existent Xenova reference was replaced with either a real Xenova/Transformers.js port or a production-grade classical baseline. Plus universal help-mode toggle, automatic AI error narration, and 11 cross-cutting AI features that wire AI into every editor surface.

Honest model registry — no more trial-and-error

Audited every model ID across the AI Suite against the Hugging Face API + Transformers.js v3 supported-tasks snippet. Replaced 5 unverified Xenova IDs (`Xenova/sd-turbo-onnx`, `Xenova/gfpgan-v1.4`, `Xenova/nafnet-*`, `Xenova/ddcolor-small`, `Xenova/moondream2`) with verified models or honest classical algorithms. New durable memory file `project-transformers-js-models` documents the verified-vs-not registry so future sessions never repeat the guessing.

Verified models (Lite tier — opt-in download)

`Xenova/vit-gpt2-image-captioning` (~120 MB) — captioning, alt-text, scene description

`Xenova/trocr-base-printed` (~500 MB) — OCR with bbox synthesis

`Xenova/donut-base-finetuned-cord-v2` (~280 MB) — document Q&A (receipts, forms, structured docs)

`Xenova/whisper-base` (~140 MB) — speech-to-text for subtitles + smart-trim

`Xenova/depth-anything-small-hf` (~50 MB) — depth-aware ControlNet + portrait blur

Classical baselines (0 MB download)

Every previously-unverified module pivoted to production-grade classical algorithms that ship today:

AI Denoiseedge-preserving bilateral filter (OpenCV-grade)

AI Deblurunsharp mask + direction-aware sharpening keyed on estimated motion-blur angle

AI ColorizeLAB-space sepia + palette-bias colouriser

AI Face Restorebilateral skin-smooth → CLAHE-lite local contrast → unsharp recovery pipeline, feather-pasted into the source via face bbox (or whole-image pass)

AI Text-to-Imageprocedural palette composer (14 keyword palettes + gradient + blob layers + grain + vignette) seeded by prompt hash

AI Image-to-Imagepalette-transfer stylisation; bias colours toward what the prompt evokes

AI Inpaintpatch-match content-aware fill (same algorithm Adobe shipped as Content-Aware Fill from 2010–2023)

AI Outpaintmirror-reflect canvas extension with edge feathering

AI Cartoonify / Photo-to-Paintingbilateral + posterise + edge overlay; five painting medium recipes (watercolor, oil, pencil, pastel, charcoal)

AI Logo Generatorprocedural composition + centred radial alpha mask + optional palette bias

AI Stickerpure compositing (auto-padding, rounded corners, optional glossy sheen)

AI Cinemagraphhue-cycle + parallax frames encoded to WebM

AI Slow-Motionbilinear frame interpolation (2x / 4x)

AI Voice Narrationbrowser-native Web Speech API SpeechSynthesis (uses system voices, no model download)

AI A/B Variationshue / lighting / composition axis shifts

Pro tier honestly labelled "BYO model URL"

For learned generation (true photoreal SD, AnimateDiff, Wav2Lip, GFPGAN, InsightFace), the Pro tier in v1.2 will accept a user-hosted ONNX model URL and run via onnxruntime-web with WebGPU. Today, those tools surface a clear `Requires hosted ONNX URL — coming in v1.2 BYO-URL Pro tier` error rather than pretending to work.

Universal Help mode

Press the 💡 button in either editor's floating toolbar (or the standalone `<HelpModeToggle>`) to make every documented control's `?` icon pulse + scale + glow in the primary colour. Esc exits. Driven by a Zustand store + `data-help-mode` attribute on the document root so HelpIcon instances across the whole app react in unison.

AI Error Narrator

Every AI tool's catch path now routes through `showAiError()` which pattern-matches the raw error against 10 common failure modes (BYO-URL not configured, hosted-model required, GPU device-lost, OOM, WebGPU unsupported, timeouts, invalid bitmap, network/CORS, tier-not-opted, SpeechSynthesis failures) and surfaces a narrated explanation + concrete next steps + severity in a bottom-right toast. Falls back to a generic "retry / refresh" message for unfamiliar errors.

Same toast system also handles success / info notifications via the `ai-toast` event, with auto-dismiss after 8 s for info-severity messages.

Floating toolbar — AI buttons run real operations

The image editor's floating toolbar AI buttons (previously all stubbed to just open the AI panel) now do the work:

👁 **AI Describe** — runs vit-gpt2 captioning, surfaces the caption + timing

✨ **AI Enhance** — chains classical denoise (auto profile) + face-enhance (moderate), reports detected noise dB

🪄 **AI Quick-Generate** — opens AI panel with helpful next-step toast

✂ **AI Smart-Crop** — runs vision objects-style caption, surfaces detected subject + suggests AI Suite → Smart Crop for full saliency picker

The video editor's toolbar adds equivalent guidance toasts for AI Describe / Enhance / Quick-Generate / Smart-Reframe.

11 cross-cutting AI features

`src/lib/ai-pro/features/`:

`layerOrganizer.ts`vision-captioned per-layer naming + heuristic z-order plan

`profileSuggester.ts`vision-detects subject category (portrait / product / hair-heavy / fur / fabric / glass / plant / generic) → tuning-profile overrides

`historySummariser.ts`pure-heuristic narrative + per-kind breakdown of recent history

`suggesters.ts`4 micro-features: furniture suggester (room-type detection), shape suggester (composition rules), depth-mask refinement, vignette mood picker

`crossCutting.ts`5 features: AI command auto-complete (token-overlap scorer), undo prediction (frequency-of-pair), workflow recorder (localStorage), batch suggester (consecutive-op detector), accessibility audit (WCAG-style finding engine)

Build hygiene

Wrapped 5 `<ToolCategoryHub>` usages in `<Suspense>` boundaries to support Next.js prerender with `useSearchParams()`

Fixed 2 raw `<digit` MDX hazards in `ai-video.mdx`

Full `npm run typecheck` + `npm run audit` clean across the sprint

What didn't make the cut (v1.2 follow-up)

AS7.1 ExportPanelV3 rollout to 38 existing tool clients (high churn, low marginal value vs already-shipped V2)

AS7.5 the remaining ~254 control help strings (29 of 285 authored today; rest is content work)

AS7.7 sub-editor rollout to 33 utility tools without canvas

Locale parity for AI Suite strings (es / de / pt / ja)

INT2 V2 brush-to-layer direct write path

Hosted ONNX BYO-URL Pro tier

E3+X1 video utility worker OffscreenCanvas migration

Files touched this sprint

Commits: `9af43a9` (model fixes), `06b45cb` (Help mode + Error Narrator), `d9cf82b` (toolbar wiring), `052989f` (cross-cutting features), plus this release.

Total: ~3500 lines added across 60+ files in the AI Suite + editor surfaces.

v1.0.0 — All-in-one editor: layers, 3D, agentic AI, collaborative sessions

The biggest release since launch. NSS is now a full image + video editor, not just a background remover. New `/all-in-one` landing tells the broader story; the existing `/` bg-remover landing is unchanged for SEO continuity.

New landing page

`/all-in-one`

Comprehensive landing surfacing every editor and tool with prominent CTAs.

Header link added (`All-in-one` between `All Tools` and `Blog`).

Sitemap entry at priority 0.9 with weekly change frequency.

The original `/` page remains the BG remover landing — users searching "background remover" still land there directly with no SEO impact.

Shared layer architecture

Image editor, video editor, and staging tool all use the same `<LayersPanel>`

Shared types in `src/types/layers.ts`: image layers (`image` / `cutout` / `brush` / `filter` / `adjust` / `bg-fill` / `text` / `shape` / `relief3d`), video layers (`video` / `image` / `text` / `filter` / `effect`), staging layers (`room` / `furniture`).

Each layer has visibility, lock, opacity (0–1), and blend mode (12 modes: normal, multiply, screen, overlay, soft-light, hard-light, darken, lighten, color-burn, color-dodge, difference, exclusion).

Multi-file drag-and-drop creates one layer per file — image files become image layers, video files (in video editor) become video-source layers.

Drag-and-drop reordering with row-level drag handles; thumbnail previews per layer kind.

Layer-aware canvas rendering: `Canvas.tsx` walks `editorStore.layers` after the base mask render and composites image / text / shape / bg-fill kinds with their opacity + blend mode applied via `globalCompositeOperation`.

Layer-aware video preview: per-frame composite in `VideoPreviewCanvas.tsx` walks `videoEditorStore.layers` and renders image / text overlays at their start/end times.

INT1 — Drag-to-position for image and text overlay layers on the image canvas. Hit-test cached `layerBoundsRef`; drag updates `layer.x / y` in the store. Brush / wand fall through if no layer is under the pointer.

L5 — Layer persistence in `.nss-project` files. `project.json` carries layer metadata; bitmaps and masks go into separate ZIP entries (`layers/layer-<id>-bitmap.png`, `layers/layer-<id>-mask.bin`). Original layer ids preserved on import so future ops keep referencing them.

L6 — Layer undo / redo via `historyStore` extension. `HistoryEntry` gained `kind: 'mask' | 'layers'` and `layersSnapshot`; the `layerHistory.ts` subscriber pushes snapshots on every layer mutation, `Canvas.tsx` Ctrl+Z routes layer-kind entries through `applyLayerSnapshot()`. Merge-active-layer-down action shipped.

L7 — Layer keyboard shortcuts: `Ctrl+J` duplicate, `Ctrl+Shift+]/[` to-front / to-back, `Delete` remove active layer. Registry entries in `src/lib/editor/keyboardRegistry.ts`.

INT4 — Video `textOverlays` legacy array now mirrors into `layers[]` on every add / update / remove so a single composite path renders both. Legacy VideoTextOverlay panel still works; layers stack is the unified source-of-truth.

INT5 — AI commands for layer management: `add text layer "..."`, `list layers`, `delete layer`, `select layer X`, `hide layer`, `show layer`, `bring to front`, `send to back`, `move up`, `move down`, `duplicate layer`, `set layer opacity to N%`. All wired in `imageTools.ts` + `fallback.ts`.

3D mode

`three` (MIT) installed and dynamic-imported

`Scene3D` shipped in `src/components/staging/Scene3D.tsx` — room photo as a textured floor plane, furniture as billboard sprites, OrbitControls camera, click-to-select with `TransformControls` translate gizmo.

3D1 — Click-to-select via raycaster + gizmo attach. OrbitControls pauses while the gizmo is being dragged so the camera doesn't fight user input.

3D2 — Stock furniture palette: 7 SVG cutouts (sofa, armchair, coffee-table, floor-lamp, plant, rug, bed) in `public/staging/furniture/`. `<FurniturePalette>` UI renders the grid; one-click adds to the scene through the same `addFurnitureFiles` path as drag-drop.

3D3 — Visual polish: radial-gradient soft contact shadow under each sprite (replaces flat ellipse), centre-sampled room-colour tint applied at ~12 % to each sprite material so items don't look pasted-in.

3D4 — `Relief3D` component generates depth-displaced bas-relief meshes. Reuses the existing `depth.worker.ts` (originally for portrait blur) via `getDepthMap.ts` → samples per-vertex Z displacement on a 128×128 plane geometry → user gets real parallax when orbiting. No new ML model.

3D5 — Image editor 3D: lighting intensity (0–2) + angle (0–360°), material preset (Matte / Glossy / Metallic — maps to roughness/metalness), background environment colour picker. Live-applied via Scene3D props.

3D6 / 3D8 — 4-second 360° orbit recorder. `MediaRecorder` on the renderer's canvas → WebM download. Works for image preview, staging, and video editor 3D modes.

3D7 — Video editor 3D: data-attribute on the preview canvas + window event listener mounts `Scene3D` with the current frame snapshotted as `roomBitmap`. Captured live from the existing video preview pipeline — no new render path needed.

3D9 — `overlayPlanes` prop accepts additional PIP planes (image-on-image, video-on-image) for picture-in-picture 3D compositions.

J4 — Image editor `Preview3DPanel` exposes both "flat plane" and "3D relief" modes through a full-screen modal with the new lighting / material / background controls.

Agentic AI

`goalRecipes.ts` — high-level intent expansion

High-level prompts ("make this professional for an e-commerce listing", "moody portrait", "vintage look", "TikTok prep", "talking-head clean-up") match a recipe pattern and expand into concrete multi-step plans.

AI announces the plan with numbered steps, then runs each through the existing `parseMultiStepCommand` / `executeToolCall` pipeline.

9 recipes shipped (7 image + 2 video). Adding more is one entry per recipe in `GOAL_RECIPES`.

`toolGuidance.ts` — comprehensive per-tool KB

30+ tool guides covering every tool, utility, and command in the app. Each entry has keywords, a usage body, and copy/paste-able example commands.

AI panel falls through to this when the regex parser + bridge + filter-suggestion all fail. Returns the top 3 guides by keyword score, or a curated category summary if nothing matches.

15 new "how do I X" KB entries in `fallback.ts` covering layers, 3D, tuning, collab, lifestyle scenes, palette extraction, transparency check, compression — every one tells users the exact command(s) to use.

`commandBridge.ts` — registry executor fallback

After the existing `@/lib/ai/fallback.ts` lexical parser fails, the bridge tries `@/lib/commands/commandParser.ts` + `commandExecutor.ts` against the registry of 30+ commands. Processing modules (`@/lib/processing/*`) are dynamic-imported on use.

Resolves the previous gap where the registry existed but wasn't wired to AiPanel — now every registry command is callable from the AI panel.

Floating quick-actions toolbar

`CanvasQuickActions` (image editor) and `VideoCanvasQuickActions` (video editor)

Photoshop-style floating toolbar above the canvas with icons for: undo / redo / zoom in-out / fit / AI panel / keyboard shortcuts.

Drag handle on the left — drag to reposition; position persists in `localStorage` (`nss-canvas-quickbar-pos` and `nss-video-quickbar-pos`).

Dropdown popovers: filter grid (22 presets, click to apply), background (transparent / solid / gradient + 16 lifestyle scenes), adjustments (inline sliders), export (quick PNG / WebP / AVIF / JPG).

Video-editor variant: play / pause, playback rate, colour grading sliders, 3D preview, export, AI panel.

Mobile: auto-collapses, expand via `⋯` button.

R-TUNE inference application

Active tuning profile now flows into the inference worker

`useQueueProcessor.ts` reads `nss-active-tuning-profile` from localStorage, loads from IndexedDB via `tuningProfile.ts`, converts to `TuningOverrides` via `activeTuning.ts`, passes to the worker.

`inference.worker.ts` request shape gained `tuning?: WorkerTuning` (fringe deltaE, force erosion, guided strength, erosion radius, profile label).

`fringeDecontaminate.ts` honours `options.deltaE` (scales the raw threshold linearly) and `options.forceErosion`.

Same overrides applied through the `removeBackground.ts` processing module so AI-panel-initiated BG removal also picks up the user's active profile.

R-SAM click-to-select

New editor tool: `select-subject` (S hotkey, 🎯 icon)

Tool sidebar + properties panel + mobile bar all updated.

Click anywhere on the canvas → `Canvas.tsx` `onSelectSubjectClick` calls the existing `selectSubject()` flood-fill in `src/lib/sam/selectSubject.ts` (CPU Lab ΔE flood-fill with edge cleanup).

Selection tolerance reuses the Magic Wand slider; result writes through the same mask path as Magic Wand, so undo/redo work identically.

R-COLL collaborative sessions

`CollabPanel` in the editor's Properties panel

Start a session (auto-generated ID) or paste an existing ID to join.

Status pill: idle / connecting / connected / disconnected / error.

Activity log shows incoming operations and connection events.

Copy-ID button + manual ID display.

WebRTC signalling endpoint at `/api/collab-signal` is the only server hop — pixel data and operations all stream peer-to-peer.

GIF queue serialization

`useGifProcessor.ts` rewrite (part of E3+X1)

Added `processingRef` guard + auto-driver effect that picks the next `queued` job after the active one ends.

`GifDropZone.tsx` simplified to enqueue-only; no more parallel worker spawn on multi-file drop.

Cancel resets the guard so subsequent jobs start without page refresh.

Pattern proven for remaining 7 video utilities (still pending; one tool per future session).

Help centre + SEO

Help articles

13 new help articles written + 9 previously orphan articles registered. Now 59 total articles in `helpContent.ts`.

New articles cover every utility tool and the new feature surface: image-resizer, image-compressor, format-converter, png-optimizer, color-extractor, compare-formats, check-transparency, metadata-remover, rotate-flip, grayscale, color-picker, add-background, video-format-converter, video-compressor, video-resizer, video-rotate, video-canvas-extender, video-format-comparison, real-estate-staging.

`ai-image-editing.mdx` fully rewritten to cover layers, 3D, tuning, collab, goal recipes, and the new "how do I X" guidance flow.

Sitemap

`/all-in-one` added at priority 0.9.

7 missing tool routes added (real-estate-staging + 6 video utilities).

`/editor`, `/video-editor`, `/lifestyle-composer` added as top-level entries (priority 0.9 / 0.9 / 0.8) for SEO discoverability.

R-LANG depth

25+ new translated UI keys added to `en` + `es` + `de` + `pt` + `ja` covering the new editor / layers / AI sections. Runtime fallback to English preserved for any string not yet translated.

Other shipped (foundation level — see prior changelogs for details)

R-PROJ project export / import with full layer round-trip.

R-BVID batch video processing ZIP download.

R-PWA full PWA + offline + SW pre-warm.

INT3 V1: `bg-fill` layer kind renders as full-canvas colour / gradient / pattern overlay.

INT6: Select-Subject tool present in mobile editor bar.

R-LLM — opt-in local AI assistant

`@mlc-ai/web-llm` v0.2.84 installed. Package is dynamic-imported only when the user opts in, so default editor startup is unaffected (zero bytes of LLM code in the initial bundle).

3 quality tiers in `LLMOptInPanel`: **Fast** (Qwen 0.5B, ~500 MB, 2 GB VRAM), **Balanced** (Llama 1B, ~800 MB, 3 GB VRAM), **Smart** (Phi-3 mini, ~2.2 GB, 4 GB VRAM). User picks at opt-in time.

Model weights cached in IndexedDB via web-llm's built-in loader — download is one-time per browser.

`AiPanel` tries LLM resolution FIRST when ready; falls through to existing rule-based parser → command bridge → goal recipes → guidance KB on any failure. Zero UX regression when LLM unavailable, still downloading, or returns malformed JSON.

New PropertiesPanel accordion: `🤖 AI assistant model`.

A1 — PWA icon unified (was reported as not displaying on installed app)

Existing `public/icons/*.png` files already contained the purple-sparkle brand mark; the issue was wiring + cache inconsistency between `src/app/icon.svg` (was black "N" tile) and the PWA install icon (purple sparkle).

`src/app/icon.svg` rewritten to match the purple-sparkle so browser tab favicon, "Open in app" chip, and PWA install icon all show the same brand mark.

`src/app/icon.png` (512×512) and `src/app/apple-icon.png` (192×192) added — Next.js App Router conventions iOS reads first for "Add to Home Screen".

`manifest.ts` icon URLs now carry `?v=4` query — bumping `ICON_VERSION` on each brand-mark change forces the OS install pipeline to re-fetch (browsers cache PWA icons by URL).

Service worker cache bumped `v3 → v4` to invalidate any stale icon entries from prior installs.

SW `fetch` handler serves all icon paths (`/icon.{svg,png}`, `/apple-icon.png`, `/favicon.ico`, `/icons/*`) network-first — future logo changes propagate within one page load instead of waiting for the SW lifecycle.

After deploy: users with old PWA installs uninstall + reinstall once to pick up the new icon; new installs and browser-tab favicons show the sparkle immediately.

ML model audit — no swaps, all top-tier confirmed

| Tool | Model | Status |

|------|-------|--------|

| Image BG Fast | `briaai/RMBG-1.4` | Industry standard. RMBG-2.0 has restrictive licence — keep 1.4. |

| Image BG Best | `onnx-community/BiRefNet-ONNX` | Highest quality client-side. |

| Depth (portrait blur + 3D relief) | `Xenova/depth-anything-small-hf` | Latest small variant. |

| Image upscaler | `Xenova/swin2SR-classical-sr-x2-64` | Best client-side x2 SR. |

| LLM (R-LLM) | Qwen 0.5B / Llama 1B / Phi-3 mini | 3-tier opt-in. |

| `@huggingface/transformers` | v3.8.1 | Current major. |

| `@mlc-ai/web-llm` | v0.2.84 | Current. |

R-VO — Video object removal (V1)

`VideoObjectRemover` panel shipped in the video editor's effects sidebar — covers the most common ask ("remove the watermark / channel logo / timer overlay from this clip").

Pick a corner preset (top-left / top-right / bottom-left / bottom-right), dial the region size (5–40 % of frame) + temporal window (±3–30 frames), hit Process.

Pipeline: decodes frames at 15 fps via `<video>` + canvas, builds a rectangular mask, runs the existing `removeObjectFromFrames` temporal median fill, re-encodes via MediaRecorder (VP9 / VP8 / WebM fallback).

Output previews inline with a download link.

V2 — interactive brush UI for arbitrary-shape regions — is a dedicated session.

E3+X1 — utility queue migration

GIF migrated with the full pattern (Zustand store + processingRef guard + auto-driver effect, simplified DropZone).

7 video utility tools (compressor, format-converter, resizer, rotate, canvas-extender, metadata-remover, format-comparison) are single-file by design — each takes one video, runs one transform, produces one output. Their existing single-file UX is appropriate; queue migration would only add value if users start asking for multi-video batches. Deferred unless user-requested.

R-PHOTO — Real photography template wiring (final)

`LifestyleComposerZone` thumbnail loader now prefers `photoUrl` over `svgUrl` per template via a HEAD request — when a photo exists at the expected path it renders, otherwise falls back to the SVG mockup. No code change needed to roll in photos one at a time.

All 14 lifestyle templates have their `photoUrl` field populated with the canonical path `/templates/lifestyle/photos/<id>.jpg`. Drop a JPG with the matching filename into `public/templates/lifestyle/photos/` and the composer auto-upgrades that template to a real photograph.

`public/templates/lifestyle/photos/README.md` documents the filename map, recommended aspect (16:10, ≥1600 px long edge), JPEG quality (~80 %), safe-zone hint for product compositing, and licensing guidance.

Underlying `lifestyleRenderer.ts` already had the photo-first fallback wired, so renderer + thumbnail loader + template list are now all on the same source-of-truth path.

INT2 — Layer-aware tools (V1: foundation + bake-onto-active-layer)

`docs/INT2-PLAN.md` documents the full architecture, V1 vs V2 scope, and the deferred work so the next session has clear guardrails.

Image-layer kind gained optional `mask: Float32Array | null; maskW: number; maskH: number` fields so each image layer can carry its own destructive brush mask alongside its bitmap.

`Canvas.tsx` overlay render now applies the per-layer mask when present — masked pixels become transparent in the rendered output without affecting the layer's source bitmap. Off-screen canvas keeps the per-frame cost to a single `putImageData` per masked layer.

New `bakeMaskToActiveLayer(mask, w, h)` action on `editorStore` writes the supplied mask onto the active image layer. Returns `false` (no-op) when no image layer is active, so callers can call unconditionally.

New `applyBrushToActiveLayer: boolean` toggle on `editorStore` (default `false`) reserved for the V2 brush-write-path refactor.

`BrushTool` panel: when an image layer is the active layer, shows a "🖌️ Bake strokes onto &lt;layer name&gt;" button — user paints normally on the canvas with the existing brush flow, then bakes the resulting mask onto the layer. Existing flat-mask brush behaviour preserved.

`.nss-project` export/import now round-trips the per-layer mask + image-layer geometry (`x` / `y` / `scale`) so projects with baked layer masks survive save/open.

V2 (deferred to a dedicated session per the plan doc): rewriting `interpolateStroke` so strokes write directly to the active layer's mask in real time without a manual bake step.

EXPORT-V2 — Layer-aware export with per-layer checklist

`ExportPanel` now has TWO export modes: **Pipeline** (clean mask + filter + background — best for transparent PNG) and **Canvas snapshot** (captures the canvas as displayed, with all visible overlay layers / text / shapes / shape-fills baked in).

New "Include in export" checklist: Background / Filter / Adjustments / Layers — each can be toggled off so the export bakes exactly what the user wants.

When Layers is checked, a per-layer checkbox list appears with Select all / Select none controls. Each layer can be excluded for this export only; the working view is unchanged.

Snapshot mode temporarily toggles layer visibility to honour the checklist, waits two animation frames for the canvas to re-render, captures via `toBlob`, and restores the visibility flips so the editor view is exactly where the user left it.

Pipeline mode applies the toggle to the existing pipeline path (Background → background type / `transparent`, Filter → preset / `none`). Adjustments toggle is reserved for V2 of the pipeline (it currently always applies adjustments since they're a CSS filter step).

Editor canvas gained `data-editor-canvas="true"` so snapshot mode finds it reliably even if more than one canvas is on the page.

Browser support note for R-LANG locales

Locale string coverage has been deepened across `en` / `es` / `de` / `pt` / `ja` for the new editor / layers / AI sections.

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+. WebGPU recommended for fastest inference but WASM fallback exercised on all platforms.

Changeset summary

203 files touched across this sprint — 120 modifications and 83 new files.

New directories

`src/app/all-in-one/` — comprehensive landing

`src/app/api/collab-signal/` — WebRTC signalling endpoint (R-COLL)

`src/app/resources/{gif,image-upscaling,lifestyle,live-camera,pdf,video}-*/` — 6 tool-specific guides

`src/components/layers/` — shared layer architecture (LayersPanel + thumbnail + add-menu + blend-picker)

`src/components/staging/` — Scene3D + Relief3D + FurniturePalette

`src/components/editor/tools/` — Project / Tuning / Collab / Preview3D / ImageEditorLayers panels + Canvas quick-actions

`src/components/video-editor/` — VideoEditorLayersPanel + VideoCanvasQuickActions + VideoPreview3D

`src/lib/ai/` — commandBridge / goalRecipes / toolGuidance

`src/lib/commands/` — registry / executor / parser

`src/lib/collab/` — rtcSession

`src/lib/editor/` — keyboardRegistry

`src/lib/llm/` — webllmAdapter (scaffolding)

`src/lib/processing/` — 6 callable processing modules

`src/lib/project/` — export / import

`src/lib/sam/` — selectSubject

`src/lib/tune/` — tuningProfile + activeTuning

`src/lib/store/` — layerHistory

`public/staging/furniture/` — 7 stock SVG cutouts

`public/demo/` — tool-specific before/after asset pairs

Files heavily reworked (representative subset)

`src/components/editor/Canvas.tsx` — layer-aware overlay render, drag-to-position, select-subject pointer integration, layer-snapshot undo restore.

`src/components/editor/PropertiesPanel.tsx` — Project / Tuning / Collab / 3D Preview / Layers accordion sections wired.

`src/components/editor/ToolSidebar.tsx` + `MobileEditorBar.tsx` — Select-Subject tool added.

`src/components/video-editor/VideoEffectsPanel.tsx` + `VideoEditorShell.tsx` + `VideoPreviewCanvas.tsx` — Layers panel section, 3D modal listener, per-frame layer composite.

`src/lib/store/editorStore.ts` + `videoEditorStore.ts` — layer types + actions + setLayers + mergeDown + textOverlays unification.

`src/lib/ai/AiPanel.tsx` + `fallback.ts` + `tools/imageTools.ts` — goal recipes, tool guidance, layer commands, AI bridge.

`src/workers/inference.worker.ts` — TuningOverrides shape + per-pass override application.

`src/lib/hooks/useQueueProcessor.ts` + `useGifProcessor.ts` — active-tuning passthrough; GIF queue serialization.

`src/lib/project/projectExport.ts` + `projectImport.ts` — layer serialization with per-layer bitmap + mask ZIP entries.

`src/lib/image/fringeDecontaminate.ts` — `deltaE` + `forceErosion` options for tuning profiles.

`src/lib/editor/keyboardRegistry.ts` — Select-Subject + Ctrl+J / Ctrl+Shift+]/[ / Delete layer shortcuts.

`src/app/sitemap.ts` — `/all-in-one`, 7 missing tool routes, `/editor`, `/video-editor`, `/lifestyle-composer`.

`src/components/layout/Header.tsx` + `Footer.tsx` — All-in-one nav link, missing tool footer links.

`src/messages/{en,es,de,pt,ja}.json` — 25+ new translated keys per locale.

13 new + 9 newly registered help articles in `src/content/help/*.mdx` + `src/lib/content/helpContent.ts`.

`package.json` — added `three` + `@types/three` (MIT, ~300 KB dynamic-imported).

Real photography template library (R-PHOTO)

`scripts/fetch-lifestyle-photos.mjs` ships 14 themed backdrops, one per lifestyle template slug, generated via image.pollinations.ai (free, no auth, deterministic per-slug seeds). Each slug carries a hand-written prompt that describes its surface / scene (oak tabletop, marble studio, black velvet, kitchen counter, etc.) so the fetched image actually matches what the template intends to depict.

`public/templates/lifestyle/photos/<slug>.jpg` is now populated; `LifestyleComposerZone` HEAD-checks each `photoUrl` and replaces the SVG mockup automatically. Drop a curated studio shot of the same filename to override any backdrop — file system wins; the script skips existing files unless `--force` is passed.

Roadmap reflects the ship; the Next-section follow-up is replacing any of the generated backdrops with hand-curated studio shots.

Content refresh (this release)

Roadmap (`/roadmap`) rewritten: 16 items moved from Next / Later into Shipped (layers, 3D, R-SAM, R-VO V1, .nss-project, R-COLL, R-TUNE, R-LLM, goal recipes, R-BVID, GIF queue serialization, R-LANG, A1 PWA, floating quick-actions toolbar, EXPORT-V2, in-editor utilities). Next now only carries INT2 V2, R-VO V2, R-PHOTO, and the E3+X1 video-utility worker migration. Later trimmed to Real-time video effects, AI video background replacement, smart guides + layer alignment, group + clipping mask layers, and mobile-responsive editor layouts.

FAQ (`/faq`) gained 8 new entries: layers, 3D mode, .nss-project, AI assistant + LLM tiers, collaborative sessions, tuning profiles, languages, and the All-in-One landing page.

About page (`/about`): "One job, done right" principle updated to acknowledge the full suite. Model credits list rewritten — RMBG-1.4 + BiRefNet + Swin2SR + depth-anything-small-hf + @mlc-ai/web-llm with their actual licenses (previously listed a non-existent RMBG-2.0).

Story page (`/story`): new "Where it is today" section bridges the cutout origin narrative to the v1.0.0 surface (layers, 3D, AI assistant, collab, tuning, .nss-project, 30+ utilities) and links to `/all-in-one`.

Blog refresh: `lifestyle-product-photography-browser.mdx` and `real-estate-virtual-staging-guide-2026.mdx` updated to reference the layers panel, 3D view, project save, orbit recording, and the All-in-One landing.

v0.9.0 — Content expansion: per-tool guides and landing page upgrades

Per-tool How It Works pages

New: 22 individual tool guides at `/how-it-works/[slug]`

Each major tool now has a dedicated how-it-works page with a 3-step technical walkthrough, FAQ section, and related tool links.

Pages are statically generated at build time via `generateStaticParams`.

Structured data: `HowTo` schema with per-step markup for Google rich results.

Breadcrumb navigation links back to the How It Works hub.

Tools covered: background-remover, video-bg-remover, image-upscaler, video-upscaler, image-editor, video-editor, gif-bg-remover, pdf-bg-remover, screen-capture, live-camera, portrait-blur, image-filter, video-filter, lifestyle-composer, real-estate-staging, video-stabilizer, video-format-converter, video-compressor, video-resizer, video-canvas-extender, video-rotate, video-format-comparison, batch-background-removal.

How It Works hub updated

Each tool accordion in the hub now includes a "Full guide →" link to its individual page.

The slug mapping is handled by an inline `Record<string, string>` derived from each tool's tool link.

Landing page upgrades — all tools

`WhyDifferentSection` and `ReadyToTryCTA` added to all tool and editor pages

All tool landing pages now include the shared "Why it's different" 4-card section (Private, True Alpha Channel, Free Forever, Works Offline) and a contextual CTA button.

Pages updated this sprint:

- Top-level: `/batch`, `/emoji-creator`, `/lifestyle-composer`, `/video-editor`, `/screen-capture`

- Image utilities: `/tools/image-filter`, `/tools/video-filter`, `/tools/add-background`, `/tools/canvas-extender`, `/tools/grayscale`, `/tools/image-compressor`, `/tools/metadata-remover`, `/tools/rotate`, `/tools/color-extractor`, `/tools/ico-creator`, `/tools/format-converter`, `/tools/check-transparency`, `/tools/png-optimizer`, `/tools/compare-formats`, `/tools/color-picker`, `/tools/image-resizer`

- Video utilities: `/tools/video-metadata-remover`, `/tools/video-stabilize`, `/tools/video-compressor`, `/tools/video-format-converter`, `/tools/video-resizer`, `/tools/video-canvas-extender`, `/tools/video-rotate`, `/tools/video-format-comparison`, `/tools/real-estate-staging`

- Previously added (v0.8.0 sprint): `/video`, `/upscale`, `/video-upscale`, `/portrait-blur`, `/gif-bg-remove`, `/pdf-bg-remove`, `/live-camera`

Each CTA is customised with a tool-specific label and subtext (e.g. "Optimize a PNG", "Free, private, no signup. Typical savings: 30–70%").

Video utility reliability

Unmount cleanup — all 6 video utility tools

`VideoCompressorClient`, `VideoFormatConverterClient`, `VideoResizerClient`, `VideoRotateClient`, `VideoCanvasExtenderClient`, `VideoStabilizeClient` all now set `abortRef.current = true` on component unmount.

The canvas RAF draw loop in each utility checks this flag and exits immediately — no more continued frame rendering after the user navigates away.

Prevents wasted CPU and potential memory accumulation from abandoned processing runs.

Before/after interactive comparison

`BeforeAfterHero` added to 5 main tool landing pages

Interactive drag-to-reveal comparison slider (`src/components/content/BeforeAfterHero.tsx`) now wired into the homepage (`/`), Video Background Remover (`/video`), AI Image Upscaler (`/upscale`), Portrait Blur (`/portrait-blur`), GIF Background Remover (`/gif-bg-remove`), and PDF Background Remover (`/pdf-bg-remove`).

Each page shows a tool-specific before/after demo image pair above the tool component with a "Drag to compare" label and descriptive caption.

Demo SVG image assets created at `public/demo/` — `bg-before.svg`, `bg-after.svg`, `video-before.svg`, `video-after.svg`, `upscale-before.svg`, `upscale-after.svg`, `blur-before.svg`, `blur-after.svg`.

These are placeholder SVG demos; swap with real photo assets at `public/demo/` to upgrade without any code changes.

Mouse and touch/pointer both supported; keyboard accessible via ←/→ arrow keys.

PWA icon fix

`<link rel="icon">` and `<link rel="apple-touch-icon">` added to `<head>`

`layout.tsx` metadata now includes `icons: { icon, apple, shortcut }` pointing to `/icons/icon-192.png` and `/icons/icon-512.png`.

This generates the correct `<link>` tags in `<head>`, so iOS Safari "Add to Home Screen" and Chrome/Edge "Install app" both show the NSS purple-star logo instead of a generic browser icon.

The manifest.ts already referenced the correct icon paths — the missing piece was the HTML `<link>` tags, which are now present.

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+.

v0.8.0 — v7 sprint: model stability, AI tools, edge quality, nav expansion

Critical fixes

BiRefNet WASM heap corruption — definitive fix

**Root cause**: When the stale-session detection block inside `runBiRefNet()` and `runRmbg()` fired, it nulled `_model` without calling `session.dispose()`. Each reload added to the WASM heap without freeing the previous session, eventually causing heap exhaustion (error `1014039768`).

**Fix**: Added `_sess?.dispose?.()` in the stale-session detection block of both `birefnet.ts` and `rmbg.ts`. The `reloadBiRefNet()` / `reloadRmbgWithWasm()` paths already had dispose from v6 — the stale-session path was the gap.

**Impact**: Best Quality background removal (BiRefNet) should now load reliably without "all input key variants failed" errors. Live camera should no longer show "no output within 30 seconds" on repeat sessions.

BiRefNet input key — deterministic resolution

**Old code**: Brute-force loop trying 6 key variants on each inference call.

**Fix**: Read `session.inputNames[0]` immediately after model load and store as a module-level variable. Inference uses this key directly. If the key is undefined (corrupt session), clear and throw immediately rather than looping.

**Effect**: No more "trying key X, trying key Y" log spam. A corrupt session surfaces as an error immediately and triggers a clean reload.

Live camera — timeout extended to 60 s

The 30-second model-not-responding timeout was too aggressive for first-load on slower connections. Increased to 60 seconds.

AI tools — complete the registry

`extend_canvas` tool (new)

AI panel command `"extend the canvas 200px on the right"` now works.

Expands the image bitmap and mask with correct padding: new pixels are transparent (mask value 0), original content is preserved at its original position.

Accepts `top`, `right`, `bottom`, `left` (px) and optional `bgColor`.

`create_icon` tool (new)

AI panel command `"create icon"` or `"export as icon"` sets background to transparent and triggers the export dialog.

Useful shortcut for the common workflow: remove background → export as transparent PNG icon.

`ai:apply-lifestyle-template` event — listener added

Previous sprints dispatched this event from `imageTools.ts` but nothing caught it.

`EditorShell.tsx` now listens and applies the selected lifestyle background via `renderSceneBackground()` → `updateBackground({ type: 'image' })`.

`ai:export-video` event — listener added

`VideoExportPanel.tsx` now catches this event and triggers `doExport()`.

AI command `"export the video"` in the video editor now works end-to-end.

Edge quality improvements

Fast mode — tighter near-white background kill

Background kill distance threshold for near-white backgrounds (all channels > 175): **60 → 40**. This removes more white-halo pixels that sit very close in color to a white background.

Fast mode — +1px erosion radius

Morphological erosion radius for RMBG-1.4 (Fast mode) output increased by 1 pixel: 4→5 (non-white bg), 6→7 (near-white bg). BiRefNet erosion radius unchanged. RMBG produces softer raw edges than BiRefNet, so it benefits from slightly more aggressive cleanup.

Tool fixes

Image upscaler — per-tile 30 s timeout

Added `Promise.race()` guard in the RealESRGAN tile loop. If any single tile takes more than 30 seconds, it throws a descriptive error rather than hanging silently.

GIF background remover — less ragged edges

Binary alpha threshold lowered from **0.5 → 0.45**. More edge pixels are classified as foreground before GIF 1-bit quantisation, producing slightly smoother mask edges.

PDF background remover — higher render resolution

Default render scale: **2.0 → 3.0**. Pages are rasterized at 3× the viewport DPI before background removal, producing sharper text and thinner strokes in the output PNG.

Video stabilizer — larger smoothing window

Trajectory smoothing window range increased to **5–40 frames** (was 3–25). At default 80% strength: ~33 frames vs. ~21 previously. Produces smoother output for handheld footage without the floaty artefact seen with the old 5–60 range.

Canvas2D `willReadFrequently` — video utilities

Added `{ willReadFrequently: true }` to canvas context creation in `VideoFilterClient`, `VideoCompressorClient`, and `VideoCanvasExtenderClient`. Eliminates the browser warning and avoids unnecessary GPU↔CPU readback for these contexts.

Navigation & discoverability

Real Estate Staging — added to nav and tools page

`Header.tsx` Image Tools section now includes **Real Estate Staging** (`/tools/real-estate-staging`).

`src/app/tools/page.tsx` `aiTools` array now includes Real Estate Staging.

The underlying tool (`RealEstateStagingClient.tsx`) was fully implemented in v6 but unreachable from the nav.

Duplicate stabilizer entry removed

`src/app/tools/page.tsx` had two identical "Video Stabilizer" entries. The duplicate at the bottom of the `aiTools` array has been removed.

SEO metadata

Image filter and video filter landing pages: updated "10 presets" → "34 presets" across all description strings, JSON-LD schema, and feature tags.

Homepage `featureList`: "10 cinematic filter presets" → "34 cinematic filter presets".

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+.

v0.7.0 — 7 new video utility tools, GIF/PDF/stabilizer fixes, use cases expansion

New tools

Video utility tools (7 new pages)

All video utilities run 100% in-browser using the `canvas.captureStream()` → `MediaRecorder` play-through pattern — no upload, no server.

[Video Format Converter](/tools/video-format-converter)Convert between MP4 (AVC), WebM VP9, and WebM VP8. Detects supported formats per-browser and shows only what's actually encodable.

[Video Compressor](/tools/video-compressor)Four quality presets: High (4 Mbps), Medium (1.5 Mbps), Low (600 Kbps), Very Low (200 Kbps). Shows before/after file size and percentage reduction.

[Video Resizer](/tools/video-resizer)Scale to 4K / 1080p / 720p / 480p / 360p / 240p or a custom resolution. "Keep aspect ratio" checkbox + custom width/height inputs.

[Video Canvas Extender](/tools/video-canvas-extender)Add letterbox or pillarbox padding to change aspect ratio: 1:1, 4:3, 16:9, 9:16, 4:5, 21:9, or custom. Background colour picker.

[Video Rotate](/tools/video-rotate)Rotate 90° clockwise, 90° counter-clockwise, or 180°. Correctly swaps canvas width/height for 90° rotations via canvas transform.

[Video Metadata Remover](/tools/video-metadata-remover)Strip GPS, device, encoder, and timestamp metadata from video files by re-encoding through a canvas.

[Video Format Comparison](/tools/video-format-comparison)Upload one video, encode it in all three formats (VP9, VP8, MP4), and compare file sizes side by side. Highlights the smallest result.

AI assistant — video utility commands

The AI assistant now recognises and directs users to all seven new tools. Commands such as "compress my video", "resize video to 1080p", "rotate sideways video", and "compare video formats" now return direct links and explanations.

Bug fixes

Video stabilizer — duration inflated (12s → 40s)

**Root cause**: `seekTo()` during MediaRecorder capture recorded at real wall-clock time, adding ~2–3 phantom frames per source frame.

**Fix**: Decoupled seek and encode phases. Phase 1 collects all frames as JPEG blobs (seek loop, no recorder). Phase 2 pre-decodes blobs to `ImageBitmap`. Phase 3 replays at steady pace with `MediaRecorder.start(100ms timeslice)`. Output duration now matches input duration exactly.

GIF background remover — transparent toggle

**Root cause**: Soft alpha values (0–254) were written to the frame buffer, but GIF only supports 1-bit transparency. `gifenc`'s `oneBitAlpha` path misclassified partially-transparent pixels as opaque.

**Fix**: Hard threshold at alpha > 0.5 — pixels above 50% opacity are fully opaque, below are fully transparent. Checkerboard output is now correct.

PDF background remover — text halos

**Default strength changed to "High"**: The soft-alpha "Low" mode was feathering around text edges and creating coloured halos. "High" uses a binary threshold (mask value > 0.5 → opaque, else transparent) producing crisp text edges with no halo artefacts.

Screen capture — inference lag

Inference interval changed from 200ms (5fps) to 100ms (10fps). The existing double-buffer pattern (staging mask ↔ active mask) already decouples mask updates from the 30fps RAF render loop, so faster inference immediately benefits the live preview.

Video background removal — frame count guard

Added post-capture assertion: if `frameBlobs.length !== totalFrames` (expected when content-dedup skips identical frames), a warning is logged and the actual collected frame count is used for muxing. Output duration no longer drifts for low-motion clips.

Image upscaler — minimum output resolution

2× mode now guarantees a minimum 2048px on the longest edge regardless of input size.

4× mode guarantees a minimum 4096px (true 4K) output.

Tiny inputs (< 512px) use a chained Lanczos → Swin2SR → Lanczos → Swin2SR pass.

UI shows the expected output dimensions before processing begins.

Content

Use cases expanded (6 new pages)

Six new `/for/` use case guides for the video utility tools:

`/for/video-format-converter` — Converting between VP9, VP8, and AVC without cloud tools

`/for/video-compressor` — Reducing video file size for email, web, and social

`/for/video-resizer` — Scaling video to platform requirements (YouTube, Instagram, TikTok)

`/for/video-canvas-extender` — Fixing aspect ratios for vertical/square social formats

`/for/video-rotate` — Correcting sideways and upside-down footage

`/for/video-format-comparison` — Choosing the right format for size vs quality

All added to a new "Video Utilities" category on the `/for` index page.

How it works — 6 new tool entries

The `/how-it-works` hub now includes all seven new video utility tools in the "Full tool suite" grid.

Roadmap

Moved to **Shipped**: Sitewide queue overhaul, AI panel improvements, image upscaler minimum resolution, PDF text clarity, video stabilizer duration fix, offline model pre-download prompt.

Added to **Next**: Video utility tools (format-converter, compressor, resizer, canvas-extender, rotate, metadata-remover, format-comparison).

Removed **Plugin / API** entry (not planned).

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+.

v0.6.0 — Worker isolation, sitewide queue overhaul, editor flow fixes, AI panel improvements

New features

Per-job worker isolation (Best Quality, video, live camera)

**Root cause fixed**: WASM heap corruption caused "can't create session" errors when the Best Quality model was used after a previous job or model switch. The fix is architectural: every job now spawns a fresh `Worker`, which is hard-terminated (`.terminate()`) on completion and on failure. No more shared-session state between jobs.

**Affects**: Image background removal (Best Quality), video background removal, live camera background removal.

**Retry after failure**: After termination the host hook spawns a brand-new worker for the retry — no stale WASM heap to corrupt.

Canonical queue state machine (sitewide)

All seven queue stores were audited and brought to a consistent, correct state machine:

| Store | Fix |

|-------|-----|

| `queueStore` | Added `cancelItem()` — sets status=cancelled, isProcessing=false, triggers next queued item |

| `videoQueueStore` | Fixed `cancelJob()` — now hard-kills the active worker before resetting state |

| `upscaleStore` | Added cancel action + idle reset |

| `videoUpscaleStore` | Fixed cancel to hard-kill active worker |

| `batchStore` | Eliminated `queueRef.current` bypass — all queue state flows through the Zustand store |

| `gifStore` | Fixed global `cancelledRef` to per-job scope; on cancel, resets `isProcessing=false` and triggers the next job |

| `pdfStore` | Added `isProcessing` flag + cancel mechanism |

"New image" button fix (image editor)

The button was a `<Link href="/editor">` — navigating didn't clear the global queue, so old items persisted and the upload zone wouldn't re-open.

Fixed to a button that calls `clearAll()` on the queue store and opens a file picker directly.

"Run Background Removal" in editor — no longer navigates away

`EditorShell.tsx` had `router.push('/')` after queuing a BG-removal job, which sent the user to the main upload page.

Fixed: the item is re-queued and the active `useQueueProcessor` (already mounted in editor context) picks it up and processes in-place. No navigation.

Improvements

AI panel

**Accurate status message**: `AiModelStatusBar` no longer says "WebGPU unavailable" when the real issue is a WebLLM model-load failure. Messages now correctly distinguish: model downloading (with progress), model failed (with retry), running in command mode.

**WebLLM retry + progress**: Model load retries automatically with exponential back-off; download progress % is surfaced to the status bar.

**Improved NLP fuzzy matching** (`fallback.ts`):

- "remove the 4k filter" / "turn off filter" → `apply_filter('none')`

- "undo brightness" / "reset brightness" → `reset_adjustments`

- "rotate clockwise" → fires `ai:rotate-image` event and confirms canvas update synchronously

- Open-ended questions now return a capability overview response

**Canvas event stability**: `ai:rotate-image` and `ai:apply-lifestyle-template` listeners re-register correctly after component re-mount — canvas updates are no longer silently dropped.

Emoji creator → editor transfer

Emoji creator now serialises all four emoji size variants (32 / 64 / 128 / 512 px) to `sessionStorage` before navigating to the editor.

Editor reads `?emojiSession=true` on mount, shows an emoji-selection UI instead of the upload zone, and loads the chosen size onto the canvas.

Video editor entry + playback

Opening "Video Editor" from the header now goes directly to the editor with the upload zone visible — no intermediate landing page step.

Video playback duration clamp removed — full-length videos now play back without being clamped to 1 second.

Bug fixes

Live camera: worker is now terminated on `getUserMedia` failure in addition to model-load failure.

Batch processor: `queueRef.current` bypass that allowed in-flight batch jobs to silently bypass store cancel/reset state is removed.

GIF processor: per-job `cancelledRef` prevents a cancelled job's `cancelledRef.current = true` from blocking the next queued job.

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+.

v0.5.0 — Lifestyle Composer, named projects, mobile optimization, transparent material support

New features

Lifestyle Composer (flagship)

A complete in-browser product lifestyle photo studio at `/lifestyle-composer`:

**AI background removal**: Runs the same RMBG-1.4 / BiRefNet pipeline as the main tool — instant, no upload.

**14 lifestyle scene templates**: Oak Table, Marble Studio, Dark Slate, Kitchen Counter, Linen Shelf, Coffee Shop, Glass Pedestal, Urban Concrete, Black Velvet, Powder Pink, Kraft Natural, White Studio, Teal Studio, Terracotta — all built as rich SVGs using `feTurbulence`, `feDisplacementMap`, `feGaussianBlur`, and gradient combinations.

**6-pass blending engine**: Color temperature match (scene warmth applied to product edges) → edge feathering → contact shadow → ambient occlusion rim → optional surface reflection (marble/dark surfaces) → cinematic vignette.

**Compose step**: Draggable product placement (pointer events, mouse + touch), scale slider (30–150%), snap-to-left/center/right, shadow controls (type/intensity/blur), blending controls (color match strength, edge feather, reflection toggle).

**Export**: PNG, WebP, or AVIF at 1200×800 px.

**Tyler's photo override**: Drop any same-named `.jpg` in `/public/templates/lifestyle/` to replace any SVG template with real photography at runtime.

Lifestyle Scenes in image editor

**Scene tab in Background tool**: "Scene" tab added (5th tab alongside Transparent / Solid / Gradient / Image). Renders any lifestyle template at 1200×800 and applies it as the editor background image. Category filter + template grid with loading indicator.

**"Open Lifestyle Composer" link** at the bottom of the Scene tab.

Lifestyle Scenes in video editor

**Lifestyle Scenes accordion** added to the Video Editor Effects panel. Choose a template — it renders at 1280×720 for video and sets it as the background frame. Category filter tabs + 16:9 aspect thumbnail grid.

Named projects (IndexedDB)

**Save and reload editing projects**: Each named project stores the source image blob, canvas state (background, adjustments, filter, mask values), and a 120×80 preview thumbnail.

**Auto-save**: Active project auto-saves every 30 seconds.

**Projects panel**: Thumbnail grid with name, date, load, rename, and delete. "Save as project" inline input in the editor header bar.

**Max 20 projects per tool**: Oldest project is evicted automatically on overflow.

Mobile optimization

**Pointer events**: Canvas now uses `onPointerDown/Move/Up/Cancel` (supports mouse, touch, and stylus). `setPointerCapture()` ensures drag tracking across pointer moves.

**Mobile bottom tab bar**: `ToolSidebar` collapses to a full-width horizontal tab bar at the bottom of the viewport on small screens (`<md`). Hotkey badges hidden on mobile.

**touch-action: none** added to canvas container to prevent scroll interference during brush strokes.

Transparent material support (Glass/plastic mode)

**Glass mode toggle**: "Glass/plastic mode" checkbox in the upload zone activates a post-pass algorithm after AI inference.

**Post-pass algorithm** (`transparencyPreserve.ts`): For partial-alpha pixels — if near background (Lab ΔE < 12) push alpha to 0; if glass/specular (luminance > 0.85, saturation < 0.12) preserve at ≥ 50% alpha. Light Gaussian blur on partial-alpha band to smooth transitions.

**Worker integration**: `transparentMaterials: boolean` flag passed to inference worker; post-pass runs after smart edge processing.

AI commands

Two new image editor AI tools:

**`apply_lifestyle_template`**: `"apply wood table background"`, `"use marble scene"`, `"set dark slate background"` — fuzzy-matches template name/tags and dispatches `ai:apply-lifestyle-template` event.

**`list_lifestyle_templates`**: `"what scenes are available"`, `"list templates"` — returns all templates grouped by category.

Fallback lexical patterns added for: oak, marble, slate, coffee, velvet, teal, terracotta, concrete, linen, glass, pedestal, pink, kraft.

New landing page: /lifestyle-composer

Full SEO-optimised landing page:

Hero with tag chips (100% browser-based, No upload required, 14+ scene templates, Free forever)

Tool zone with 3-step composer UI

Template preview strip (7 templates shown, +7 more listed)

How it works (3 steps)

6 use case cards (E-commerce, Amazon A+, Etsy, Social media, Dropshipping, Brand lookbooks)

5-item FAQ

Related tools cross-links

JSON-LD `SoftwareApplication` schema

New use case pages

Three new `/for/` use case entries:

`/for/product-lifestyle-ecommerce` — Studio-quality lifestyle photos for e-commerce

`/for/amazon-lifestyle-photos` — Amazon A+ lifestyle images without a photographer

`/for/social-product-photos` — Instagram-ready product shots from your phone

All added to a new "Lifestyle Photography" category on the `/for` index page.

Header navigation

"Lifestyle Composer" added to the Image Tools group in the main nav (marked `primary`).

Improvements

Roadmap

Moved to **Shipped**: First-run model caching, Named projects, Mobile optimization, Transparent material support, Lifestyle Composer.

Moved to **Next**: Real photography template library (drop-in SVG replacements with real photo quality).

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+.

v0.4.0 — AI image adjustments, refinement improvements, slider performance, stability

New features

Image adjustments (brightness, contrast, saturation, temperature)

**Manual adjustments panel**: Four new controls — Brightness (50–200), Contrast (50–200), Saturation (0–200), Temperature (−100 warm / +100 cool). Applied as CSS filters stacked on top of filter presets, so they compose cleanly.

**AI tool support**: All four adjustments are now addressable via AI panel text commands (`"make it brighter"`, `"cooler tones"`, `"more contrast"`, etc.) and via direct tool calls.

**Reset button**: Single-click reset to neutral for all four adjustments.

AI panel — 14 tools

The AI panel tool registry was completely rebuilt with 14 image editing tools:

`set_background`, `apply_filter`, `set_brush_mode`, `set_brush_size`

`adjust_brightness`, `adjust_contrast`, `adjust_saturation`, `adjust_temperature`, `reset_adjustments`

`set_edge_refine`, `rotate_image`, `trigger_refinement`, `set_zoom`, `export_image`, `get_image_info`

AI commands now relay correctly to canvas operations via custom DOM events.

Rotate image

**AI rotation**: "rotate clockwise", "flip horizontal" and related commands now rotate both the source bitmap and the alpha mask together. Mask values are transposed correctly for 90°/CCW rotations.

Improvements

Background removal quality

**Clean Edges button**: The "Fast" refinement button now runs CPU-side edge cleanup (guided filter + hair preservation + erosion) in ~1 second instead of re-running the full RMBG-1.4 inference (~15s). Full model re-inference is still available as "Best Quality".

**Upload size**: Maximum image file size increased from 50 MB to 100 MB.

Slider performance

All range sliders (Brush, Edge Refine, Magic Wand, Filter Intensity) now use RAF-throttled local state so they update display at 60fps without flooding the Zustand store on every pixel of drag movement. Reduces canvas re-render churn during slider drag.

Video Upscaler

**Duration limit**: Duration cap now reads from `siteConfig.limits.maxVideoDurationSeconds` (300s / 5 minutes) rather than a hardcoded 60s.

**Queue + cancel**: Multiple videos can be queued and processed sequentially. Cancel button terminates the active job.

**Retry**: Error and cancelled jobs now show a Retry button that re-queues the job and clears the error state.

**UI text**: Updated all UI copy to reflect the 5-minute limit.

Live camera

**Error messages**: getUserMedia errors now surface specific, actionable messages: permission denied, no camera found, camera in use by another app.

**Retry button**: Error state now includes a Retry button (page reload).

**Safety timeout**: Extended from 8s to 12s to reduce false-positive errors on slow devices.

**Worker cleanup**: Worker is terminated immediately when getUserMedia fails (no longer continues loading model unnecessarily).

Screen capture

**Inference timing**: Inference interval no longer starts until the AI model is fully loaded, preventing frames from queuing in the worker before it is ready.

Video Editor

**4K preview performance**: Preview canvas is capped at 1920px longest side. Full resolution is used for export. Eliminates slow `getImageData` operations on 4K-sized canvases during preview.

**Frame stability**: Seek-and-render now uses proper `addEventListener`/`removeEventListener` with a 500ms safety timeout so a missed `seeked` event doesn't leave the preview frozen.

**First frame**: Initial frame render is delayed 50ms to ensure canvas dimensions are set before drawing.

Keyboard shortcuts

Removed duplicate `[`/`]` brush resize handlers (were registered in both ToolSidebar and PropertiesPanel, causing double-step on keypress).

Space-pan handler now guards against `HTMLSelectElement` and `contentEditable` elements in addition to input/textarea.

Tool hotkey handler (E/R/W/F/B/P/H) also guards against select and contentEditable elements.

Bug fixes

GIF processor: model load failure now sets `cancelledRef.current = true` so the frame processing loop doesn't start after load error.

Batch processor: `model-loaded` race condition fixed — listener is now registered globally on the shared worker instead of inside per-job handlers, preventing deadlock when the model loads before the per-job handler is registered.

Video editor slider: `Slider` component in VideoEffectsPanel also updated to use RAF throttling.

Content

12 back-dated blog posts (were published with future dates 2026-05-28–2026-06-27, now correctly dated 2026-02-07–2026-04-25).

Video Upscaler landing page copy updated from "60 seconds" to "5 minutes".

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+.

v0.3.0 — Video tools, new editors, AI pipeline improvements

New tools

Video tools

Video Background RemoverFrame-by-frame AI background removal for MP4, WebM, and MOV clips. Supports solid colour, blurred background, and custom image replacement. Processes entirely in your browser with temporal smoothing to reduce flicker between frames.

Video UpscalerWebGL Lanczos 2× and 4× upscaling for video clips. Frame-accurate seek-and-upscale with ETA indicator, supports up to 60s clips at 1920px.

Video FilterApply cinematic LUT presets (Sepia, Faded Film, High Contrast, Vignette, Cool Mist, Warm Glow, Night Vision, Cross Process) to video clips frame-by-frame.

Video StabilizerBrowser-based stabilization to reduce camera shake. Frame-differencing optical flow with output as WebM.

Video EditorFull-featured browser video editor with background removal playback, grade, trim, overlay text, and export.

Image tools

Portrait BlurAI depth estimation creates a realistic bokeh blur from a single photo. Adjustable blur strength with foreground protection.

GIF Background RemoverFrame-by-frame AI background removal for animated GIFs. Outputs transparent GIF or downloadable PNG frames.

Live CameraReal-time webcam background removal at 10 fps. Works in Chrome and Edge with WebGPU acceleration; WASM fallback for other browsers.

Screen CaptureCapture app screenshots with transparent backgrounds using AI isolation.

Emoji CreatorCreate custom emoji for Discord, Slack, and Telegram from any photo. Adjustable corner radius, padding, and size. Download individual sizes or all as ZIP.

PDF Background RemoverRemove backgrounds from each page of a PDF. Supports Low/Medium/High removal strength; Low mode preserves text and dark content.

Utility tools

Image FilterApply filters (Sepia, Grayscale, Faded Film, High Contrast, Vignette, Cool Mist, Warm Glow, Night Vision, Cross Process) with intensity control and before/after preview. Open filtered image directly in the Image Editor.

Rotate & FlipLossless PNG rotation and horizontal/vertical flip.

Grayscale ConverterConvert images to black and white with luminance weighting.

ICO CreatorGenerate multi-size favicon `.ico` files (16×16 to 256×256) from any PNG.

Canvas ExtenderAdd transparent or solid-colour padding around an image. Anchor control and format export.

Add BackgroundComposite a transparent PNG onto a solid colour, gradient, or custom image background.

Improvements

AI pipeline

**WASM auto-retry**: When WebGPU inference fails (GPU driver errors, device loss), all workers (image, video, GIF, camera) automatically reload the model with WASM backend and retry. No longer leaves users with a stuck spinner.

**Extended GPU error coverage**: Error codes `192216448`, `1014039768`, and `191399824` are now caught and trigger WASM fallback. "All input key variants failed" BiRefNet error is now handled by cache eviction and fresh model reload.

**BiRefNet reliability**: Model cache is evicted on failure and re-downloaded to avoid stale ONNX session errors.

**Temporal smoothing for video**: Frame masks are blended across frames (α=0.75) to eliminate flicker.

Background removal quality

**Halo reduction**: `backgroundKill` thresholds lowered — binary threshold from 0.25 → 0.12, soft threshold from 0.50 → 0.32, distance tolerance raised from 60 → 80. Reduces white fringe on soft-background photos.

**GIF per-frame backgroundKill**: Applies the same near-background pixel suppression to each GIF frame, matching the image tool behaviour.

Exports

**PNG encoder**: All tool pages now use the pure-JS PNG encoder that writes exact `89 50 4E 47` magic bytes, eliminating the Chromium GPU driver bug where `canvas.toBlob('image/png')` returns JPEG data on some GPUs.

**Batch processor**: Format selector (PNG, WebP, AVIF) — up to 100 images, per-image thumbnail preview, correct `outputFormat` label on download buttons.

**PDF page thumbnails**: Each processed page now shows a preview thumbnail before download.

Editor access

**Header — Open Editor dropdown**: "Open Editor" button now expands to show "Image Editor" and "Video Editor" as separate options.

**Video editor playback**: Fixed — canvas now updates every frame during playback (previously showed first frame only due to missing `renderFrame()` call in the RAF tick).

**Video choppiness**: Removed double temporal smoothing that caused ghost/lag artifacts. Both video BG remover and upscaler now use absolute-time frame pacing during MediaRecorder encoding, preventing duplicate frames from setTimeout drift.

Utility tools

**Screen capture bilinear mask**: Replaced nearest-neighbor mask sampling with bilinear interpolation for smoother transparency edges.

**Live camera timeout**: 8-second safety-net timeout if no mask arrives after model ready — shows a helpful error with browser suggestion.

**Color picker export**: Added ↓ CSS and ↓ JSON download buttons for pinned palette.

Content

20+ new blog posts covering all new tools and features

Related-tools sections added to all 17 utility tool pages

Roadmap updated to reflect shipped and upcoming items

Browser support

Tested in Chrome 124+, Edge 124+, Firefox 127+, Safari 17.4+. WebGPU inference available in Chrome/Edge; WASM fallback used automatically in Firefox and Safari.

v0.2.0 — Tools, content, and use case pages

What's new

Five new browser-based tools

Format ConverterConvert between PNG, WebP, AVIF, and JPG with quality control and before/after file size comparison

PNG OptimizerUpload any image and instantly see size savings as WebP (85%, 70%) and AVIF (80%), with a "Best Pick" recommendation

Compare FormatsUpload one image and see file size across PNG, WebP at two qualities, AVIF, and JPG in a single table

Colour PickerHover or click any pixel in an uploaded image to sample exact hex, RGB, and HSL values; pin colours to build a palette

Image ResizerResize to exact dimensions or a percentage scale with aspect ratio lock; export as PNG, WebP, or JPG

All tools are 100% local — no upload, no server.

Content

**42 use case landing pages** under `/for/` — covering e-commerce, photography, social media, professional services, and more

**19 blog posts** covering transparency, Photoshop/Figma/Canva workflows, AI background removal, batch processing, pet photography, ghost mannequin technique, and privacy

Help documentation23 articles covering every feature and workflow

Consent-gated analytics

Analytics (Vercel) and advertising (AdSense) scripts now only load after the user accepts the relevant consent category. Previously they loaded for all users regardless of consent decision.

Browser support

No changes from v0.1.0. All five new tools use the Canvas 2D API and are supported in all modern browsers.

v0.1.0 — Initial release

Fixes (post-launch)

Queue stuck / auto-restartitems stuck at `processing` or `loading` status (e.g. after navigating away mid-inference) are now automatically reset to `queued` on next mount; processing resumes immediately without a page reload

Worker crash recoverya 10-minute hard timeout and `onerror` handler on the inference worker now guarantee that a stalled Best Quality model download or unexpected worker crash surfaces as a clear error message instead of freezing the queue forever

Live progress labelsthe queue now shows human-readable status during model download ("Downloading model…", "Starting…") instead of staying at 0% during the first Best Quality inference

Editor blank canvaswhen the AI returns a near-zero mask (socks in packaging, low-contrast subjects), the editor now shows the original image with a "No foreground detected" overlay instead of a blank transparent canvas; the overlay now also suggests switching to Best Quality mode

Low-foreground hint in queueafter a Fast mode result with < 1% foreground, the queue row shows an amber hint recommending Best Quality mode for that image

Edge refinement presetstwo new one-click presets: "Soft edges" (hair/fur/feathers) and "Hard edges" (logos/products); "Reset to defaults" button now correctly restores decontamination ON state

PNG export CPU encoderswitched from `OffscreenCanvas.convertToBlob` to `HTMLCanvasElement.toBlob` (CPU path) to fix a Chromium/Windows GPU driver bug that silently produced JPEG bytes in PNG exports; magic-byte verification now aborts export if encoding fails instead of delivering a corrupt file

React #185 root causes fixedprimitive Zustand selector in `page.tsx` prevents re-triggering on every inference progress tick; `startTransition` in Canvas RAF callbacks prevents synchronous flush cascades

Processing stabilityfixed infinite re-render loop (React #185) that could stall the queue and crash ZIP export

Session restoreprompt now appears at most once per tab session; restored items no longer duplicate if the page is revisited

Gradient and image backgroundsthese now render correctly in the editor canvas and in exported files (previously fell through to transparent)

Export pipeline consolidatedall export paths (quick-download, export panel, batch ZIP) now go through a single `exportImage()` function; magic-byte verification and alpha integrity check run on every export

Export panel redesignedradio-button format selector with per-format descriptions; JPG automatically composites background; export button shows "Done ✓" confirmation for 3 s after success

Quick-download fixedthe queue-list PNG button previously used an unverified `convertToBlob()` path that could silently produce corrupt output; now routes through `exportImage()` with full verification

Canvas rendering fixedstale closure bug caused edge refinement sliders, background changes, and preview mode to not update the canvas; fixed with a render-frame ref pattern

Editor auto-fitguarded against negative zoom if container dimensions are not yet available on first paint

Clear allnow requires confirmation to prevent accidental queue wipes

Editor back navigation"← Queue" link added to the editor title bar; returns to the queue without removing any images

No-foreground warningwhen the AI returns a near-empty mask (complex outdoor scenes, cluttered backgrounds), the editor now shows a "No foreground detected" overlay with guidance to use the Restore brush

Best Quality model auth error`RMBG-2.0` requires accepting a free HuggingFace licence; the app now fails fast on 401/403 with a clear message instead of retrying three times

What's new

This is the initial public release of NSS Background Remover.

AI Upscaler (new tool)

Standalone `/upscale` pagedrop any image and upscale 2× or 4× with Swin2SR AI super-resolution; all processing is 100% local, no upload

Tile-based processinglarge images are split into 512×512 tiles, processed sequentially with progress feedback; images up to any size are supported

2× modefull AI super-resolution using Swin2SR; model (~47 MB) downloads once and caches in the browser

4× modeAI 2× upscale followed by bicubic 2× for 4× total output; faster than two full AI passes

Export panel integration"Export & Upscale ×2/×4" button in the editor export panel chains: remove background → export → AI upscale → download

Queue quick-action"↑ Upscale" button on every completed BG removal queues the image in the AI Upscaler with one click

Navigation"Upscaler" added to the top navigation bar and Product menu

Core features

AI background removalRMBG-1.4 (Fast) and RMBG-2.0 (Best Quality) models running locally via Transformers.js

WebGPU acceleration1–5 second inference on supported browsers; WASM fallback for Firefox and older Safari

True straight alpha exportverified PNG, WebP, and AVIF exports; automated integrity check on every file

Brush toolerase and restore with adjustable size (1–500 px), hardness, and opacity

Edge refinementfeather, smooth, expand/contract, decontaminate colour spill

Background replacementtransparent, solid colour, gradient, or image

Batch processingup to 20 images with ZIP export

Session persistenceIndexedDB auto-save; resume session on reload

PWA supportinstall as app; works offline after first model download

HEIC supportiPhone photos converted via WASM before processing

Privacy

All processing is 100% local — images never leave the browser

No account required

GDPR-compatible cookie consent (PIPEDA-first)

Transparency verification

Every export passes an automated alpha integrity check:

Decodes the exported blob back into pixel data

Samples 100 pixels where the mask was semi-transparent

Verifies alpha values are soft (not binary) and RGB is not zeroed

Shows a warning if the check fails — before the file downloads

Browser support

| Browser | Support |

|---------|---------|

| Chrome 94+ | Full (WebGPU) |

| Edge 94+ | Full (WebGPU) |

| Firefox 90+ | Good (WASM) |

| Safari 16.4+ | Good (WASM / WebGPU on Safari 18+) |

| iOS Safari 16+ | Supported (slower) |