- Add bidirectional HEIF support: decode (input) and encode (output) via system heif-convert/heif-enc
- Add server-side WebP preview generation for non-browser-previewable formats (HEIC, TIFF)
- Fix content-aware resize failing on HEIF input (decode before passing to caire)
- Fix content-aware resize timeout on large images by downscaling to max 1200px and using JPEG intermediate
- Add HEIF as target format in convert tool
- Add loading spinner for HEIF preview decode in file store
- Fix file picker not accepting HEIF files (explicit .heic,.heif,.hif extensions)
- Extend frontend timeout for medium tools to 180s with 45s progress animation
- Redesign rotate controls with preset buttons and compact flip section
- Remove misleading savings percentage from convert tool
Replace the Python seam-carving library with caire (esimov/caire v1.5.0),
a Go-based content-aware resize engine that is faster and supports both
shrinking and enlarging via seam insertion.
- Add Go builder stage in Dockerfile to compile caire from source
- Rewrite seam-carving.ts to call caire via execFile (no Python sidecar)
- Remove content-aware-resize from PYTHON_SIDECAR_TOOLS (60s timeout)
- Add new options: blur radius, edge sensitivity, square mode, face detection
- Move content-aware toggle below standard resize in UI (subtler placement)
- Rename "Don't enlarge" to "Limit to original size" with hover tooltip
- Add smooth progress bar for medium-duration tools
- Delete seam_carve.py and remove seam-carving pip dependency
- Update integration tests and visual regression screenshots
Several RBAC features from feat/rbac-permissions were silently lost
during the merge into main. This restores and completes them:
- Add permissions and teamName to login/session API responses
- Export Permission and Role types from shared package
- Filter settings tabs by user permissions in frontend
- Extend useAuth hook with role, permissions, and hasPermission
- Restrict teams listing to admin only
- Add admin override for API keys, files, and pipelines listing
- Add ownership scoping to file access, download, and delete routes
- Register userFileRoutes in integration test server
- Mock auth import in unit permissions test to avoid SQLite lock
* feat: add resolveOutputFormat utility for input format preservation
* fix: preserve file order in batch processing with X-File-Results header
Collect all results before streaming the ZIP to guarantee upload order.
Replace X-File-Order with index-based X-File-Results header that maps
each upload index to its processed filename, handling failures and
duplicate filenames correctly.
Closes#13
* fix: use X-File-Results for index-based batch file matching
The frontend now matches processed files to entries by upload index
instead of fragile name/position matching.
* feat: preserve input format in smart-crop with quality control
Smart crop now outputs in the same format as the input (JPG in, JPG out)
instead of always converting to PNG. Adds an optional quality setting
(default 95) for lossy formats.
Closes#14
* feat: add output quality slider to smart crop settings UI
* feat: preserve input format in crop tool
* feat: preserve input format in color adjustment tools
Applies to brightness-contrast, saturation, color-channels, and
color-effects tool routes.
* refactor: avoid double encode in smart-crop content mode
For the simple trim path (no pad-to-square), chain .toFormat() on the
trim pipeline directly instead of creating a second Sharp instance.
This eliminates a redundant intermediate encode that degraded quality
for lossy formats. Also use trimmed.info dimensions instead of a
separate metadata() call for the pad-to-square path.
---------
Co-authored-by: Siddharth Kumar Sah <siddharth123sk@gmail.com>
Centralize duplicated getToken() + Bearer header logic into a single
formatHeaders() helper in lib/api.ts. When no token exists, the
Authorization header is omitted entirely instead of sending an empty
Bearer token, which breaks forward-auth proxies like Authelia behind
Caddy.
Changes:
- Add formatHeaders() with try-catch around localStorage access
- Replace 20+ duplicated getToken() definitions across tool components
- Migrate all call sites including file-details, settings, change-password
- Update tests to verify header omission on empty token
Based on the fix proposed by @jules2689 in #6, with improvements:
file placement (lib/api.ts vs components), localStorage error handling,
simplified truthiness check, and complete call-site coverage.
Co-Authored-By: Julian Nadeau <julian@jnadeau.ca>
The backend sets mustChangePassword=true for all new accounts and
blocks API calls until the password is changed. The frontend was not
handling this flag - it logged the user in and redirected to the
dashboard where every API call silently failed with 403.
Add a /change-password page that is shown when mustChangePassword is
true. The login page now redirects there instead of home, and the
AuthGuard intercepts any direct navigation to force the change first.
checkAuth was defined as a plain function and used as a useEffect
dependency, causing it to fire on every render. Moved it inside the
effect with an empty dependency array so it runs once on mount.
Add serverFileId to FileEntry, pass fileId in tool processor formData when
a file originates from the Files page, and set serverFileId on the loaded
entry so subsequent tool runs create new file versions instead of duplicates.
- Remove @fastify/swagger and @fastify/swagger-ui (API docs live on GitHub Pages)
- Run typecheck, build, and docker CI jobs in parallel instead of sequentially
Upload occupies 0-15% of the bar, server processing 15-100%.
SSE progress from the server is scaled into the 15-100 range.
The bar now moves smoothly from start to finish.
The Zustand setError() setter has a side effect: it sets
processing=false. When called after setProcessing(true), it
immediately killed the processing state, so the ProgressCard
never rendered. Fix: call setError(null) before setProcessing(true).
Home page: after uploading an image, shows tool selector on the left
(quick actions + all 37 tools by category) with image preview on the
right. Stays on the main page — no popup overlay.
Auth: when AUTH_ENABLED=true, unauthenticated users are redirected to
/login. Default credentials admin/admin. When auth is disabled (dev
default), no redirect happens.
1. Home page file drop now shows quick-action tool selector
2. Auth disabled by default in dev (Docker still defaults to true)
3. Tool settings wrapped in forms - Enter key triggers processing
Add useMobile hook for viewport detection (<768px). Update AppLayout
with hamburger menu, slide-over sidebar overlay, and fixed bottom
navigation bar (Tools, Automate, Files, Settings) for mobile. Update
Sidebar with expanded mode for mobile overlay. Update ToolPage to
stack settings above dropzone on mobile with collapsible panel. Add
new routes for /automate and /fullscreen. Integrate Settings dialog
and keyboard shortcuts at the App root level.
Create translation key system in packages/shared/src/i18n/ with full
English locale covering common actions, all 37 tools, settings sections,
auth, pipeline, and navigation strings. Add useI18n hook that returns
typed translations. Architecture enables adding new languages by
creating locale files matching the TranslationKeys type.
Register global keyboard shortcuts: Cmd/Ctrl+K to focus search,
Cmd/Ctrl+/ for tools view, Cmd/Ctrl+Shift+D to toggle theme,
Cmd/Ctrl+Alt+1-8 for quick tool navigation. Uses platform-aware
mod key detection (Cmd on Mac, Ctrl on Windows/Linux).
Backend: POST /api/v1/tools/:toolId/batch accepts multiple files +
settings, processes via p-queue with CONCURRENT_JOBS concurrency limit,
streams ZIP response using archiver. Tool registry in tool-factory
enables batch to reuse any registered tool's process function. SSE
endpoint at GET /api/v1/jobs/:jobId/progress provides real-time updates.
Handles partial failures gracefully, preserves filenames, deduplicates
collisions. Frontend: use-batch-processor hook handles upload, SSE
progress tracking, and automatic ZIP download.
Adds Zustand file store, useToolProcessor hook for upload/process/download
flow, and 7 settings components: resize (with social media presets), crop
(with aspect ratio presets), rotate/flip, convert, compress (quality +
target size modes), strip-metadata, and color adjustments (brightness,
contrast, saturation, channels, effects). Updates tool-page to render the
appropriate settings panel based on toolId.