Reduce Docker image from ~30GB to ~5-6GB by making AI features
downloadable post-install. Users cherry-pick feature bundles
(Background Removal, OCR, etc.) from the UI after pulling.
Allows re-triggering the release workflow after a Docker push failure
without needing new commits. If semantic-release produces no new version
the workflow now uses the latest existing git tag for the Docker build.
Prevents git on Windows (core.autocrlf=true) from checking out shell
scripts and Dockerfiles with CRLF line endings, which causes a
bad interpreter error when Docker runs entrypoint.sh on Windows.
Set U2NET_HOME=/opt/models/rembg so rembg models pre-downloaded at
build time as root are found at runtime by the non-root ashim user.
Without this every fresh container re-downloaded the 973 MB BiRefNet
models on first background-removal request.
Apply the same fix to PaddleOCR: download to /opt/models/paddlex and
symlink into both /root/.paddlex and /app/.paddlex so PaddleX finds
models regardless of which HOME gosu resolves at runtime.
Fall back to per-request spawning in bridge.ts when the persistent
dispatcher crashes mid-request (e.g. OOM loading a large ONNX model),
so the operation succeeds instead of surfacing "Python dispatcher
exited unexpectedly" to the user.
Improve entrypoint.sh permission warning to mention Windows bind mounts
as the likely cause.
- ci.yml: skip lint/test/docker on docs-only and markdown-only pushes
- deploy-docs.yml: only rebuild GitHub Pages when apps/docs/** changes
- README.md: updated key features and content
- images: updated dashboard screenshots, removed stale images
When SKIP_MODEL_DOWNLOADS=true the download script never runs, so
/opt/models was never created and the subsequent chown -R ... /opt/models
failed with exit code 1. mkdir -p it alongside the other required dirs.
esbuild (used by Vite) crashes under QEMU amd64 emulation on Apple Silicon,
the same way the Go runtime did. Building the frontend on the native platform
is safe because the output (HTML/CSS/JS) contains no architecture-specific code.
- Fix docker run commands (was pointing to old stirlingimage/stirling-image)
- Add Docker Images section with all available tags for both registries
- Add GHCR badge alongside Docker Hub badge
- Remove rename banner (rename is complete)
Replace CGO_ENABLED=0 (which fails because gioui.org requires CGO on Linux)
with a proper C cross-compiler approach using Debian multi-arch packages.
Running caire-builder with --platform=\$BUILDPLATFORM avoids QEMU crashes on
Apple Silicon; the C cross-compiler bridges the CGO gap for the target arch.
Also adds SKIP_MODEL_DOWNLOADS=true to the CI docker build job to prevent
HuggingFace CDN 504s in CI (image structure is what matters there).
The caire-builder stage now runs the Go toolchain on the native build
platform instead of under QEMU emulation. For cross-arch builds
(arm64 host → amd64 image) CGO_ENABLED=0 avoids needing a full C
cross-toolchain; the display window is unused in server mode anyway.
The binary is staged to /tmp/caire so the COPY path is stable across
both native and cross-compiled builds.
Run both short-range and full-range MediaPipe models and merge results,
then apply non-maximum suppression to remove duplicate bounding boxes.
Fixes missed faces in group photos where the single-model loop exited
early after the first positive detection.
canBrowserPreview() was checking for a file extension in blob: URLs, which
have none (blob:http://localhost:1349/<uuid>). This caused the optimize-for-web
live preview — which stores a blob: URL in processedUrl — to always return false
and show the 'Conversion complete' fallback card instead of the BeforeAfterSlider.
Fix: blob: URLs are always renderable in <img> tags; short-circuit the extension
check with `if (url.startsWith('blob:')) return true` in both tool-page.tsx and
multi-image-viewer.tsx.
Both routes showed "Tool not found" — the UI was never implemented.
Pipeline functionality already lives at /automate (the Automate page).
Also removed the empty Automation category and unused Workflow/FolderInput
icons from icon-map.ts.
- Fix "Cannot access 'a' before initialization" TDZ error after login
caused by manualChunks splitting react-vendor + lucide icons into
circular ES-module chunks. Removed manualChunks entirely.
- Replace `import * as icons from "lucide-react"` (pulls all ~1000 icons)
with a targeted icon-map of ~50 icons actually used by tool definitions.
Reduces shared icons chunk from 745KB to 62KB (132KB→16KB gzip).
- Exclude static files from @fastify/rate-limit via allowList so rapid
page navigations don't 429 on JS/CSS chunk requests.
- Move Docker auth defaults (AUTH_ENABLED, DEFAULT_USERNAME,
DEFAULT_PASSWORD) from Dockerfile ENV to entrypoint.sh runtime exports
to avoid SecretsUsedInArgOrEnv warnings.
- Fix Docker CMD to use pnpm --filter for workspace-scoped tsx binary.
- Set COREPACK_HOME system-wide so non-root user can access pnpm cache.
- Lazy-load all pages in App.tsx and all controls in
pipeline-step-settings.tsx to keep main bundle under 300KB.
urlretrieve against the HuggingFace CDN was consistently returning HTTP
504 in GitHub Actions runners for LaMa, NAFNet, and the OpenCV caffemodel.
The huggingface_hub library has built-in retry logic, resumable downloads,
and better CDN routing than bare urlretrieve.
- download_lama_model: urlretrieve → hf_hub_download (Carve/LaMa-ONNX)
- download_nafnet_model: urlretrieve → hf_hub_download (mikestealth/nafnet-models)
- download_opencv_colorize_models: caffemodel → hf_hub_download (space repo_type)
- _urlretrieve: retry count 3→5, flat 10s delay → exponential backoff (10/20/40/80s)
- Also reverts the SKIP_MODEL_DOWNLOADS=true from CI workflow (wrong approach)
The Docker Build Test was consistently failing because HuggingFace CDN
returns 504 Gateway Timeout when downloading the LaMa ONNX model (~200MB)
from GitHub Actions runners. Model availability is an external dependency,
not something CI can control.
Added SKIP_MODEL_DOWNLOADS build arg (default: false). When set to true,
the download_models.py step is skipped entirely. CI only needs to verify
the image structure builds — Python deps install, Node build runs, app
code is copied — not that every ML model CDN is reachable.
Production builds (docker build without the arg) still download all models
as before.
download_models.py used bare urllib.request.urlretrieve() with no retry
logic. CI hit a HTTP 504 Gateway Timeout mid-build, failing the Docker
Build Test. Added _urlretrieve() wrapper that retries up to 3 times with
a 10s delay on any 5xx or network error. Also adds imports for time and
urllib.error.
vitest was spawning multiple worker processes (one per test file) that
each independently opened the same SQLite database and raced to set
journal_mode = WAL. Adding pool: "forks" with singleFork: true runs all
test files in the same child process, eliminating the concurrent-open
race. The test suite (~830 tests) remains fast enough for CI.
The test-with-exif.jpg fixture still had "Stirling-Image Test" as its
Software EXIF field. Updated to "ashim Test" to match the assertions in
operations.test.ts that were already updated during the rebrand.