Skip to content

Repository files navigation

Image Converter Web App

A browser-native image converter for batch image processing. Files are processed locally in the browser with Web Workers and the @walujanle/image-converter-wasm Rust/WebAssembly package. This repository does not include an upload API.

Current project version: 1.1.2 - Stable Version (feature-complete; maintained as an archive)

What It Does

  • Converts images in batches.
  • Supports JPEG, PNG, WebP, AVIF, and HEIC/HEIF as inputs.
  • Outputs JPEG, PNG, WebP, and AVIF.
  • Uses a worker pool for conversion work.
  • Warms the converter worker after page load so the WASM engine is ready before the first conversion.
  • Production builds generate a service worker that precaches hashed JS, CSS, worker, and WASM assets for faster repeat visits.
  • Applies memory checks before unsafe conversions.
  • Supports crop, resize, quality controls, WebP lossless mode, PNG optimization toggle, filename transforms, auto suffix, dataset logs, presets, and ZIP download with lazy-loaded ZIP packaging.
  • Keeps simple and advanced modes independent with separate queues, settings, and persisted settings.
  • Lets a converted image be converted again at different settings without removing and re-adding the file, per image or for the whole batch.
  • Can preserve supported metadata when enabled; coverage depends on the selected output format.

Tech Stack

  • React 19
  • TypeScript 6
  • Node 24 LTS
  • Vite 8
  • Bun
  • Zustand
  • Tailwind CSS 4
  • Web Workers
  • @walujanle/image-converter-wasm 1.1.0 Rust/WASM image engine package
  • JSZip
  • Biome
  • Vitest

WASM Engine Package

Image processing is not implemented directly in this web app. The conversion engine is provided by the npm package @walujanle/image-converter-wasm.

The web app uses that package from its Web Worker boundary for image decoding, crop, resize, encoding, metadata handling, and output dimension parsing. UI, queueing, presets, storage, downloads, ZIP packaging, cache registration, and service-worker generation stay in this repository.

Quick Start

bun install
bun run dev

The Vite dev server usually runs at http://localhost:5173. The local port can change if another server is already using it.

Commands

bun run lint
bun run check
bun run typecheck
bun run test
bun run test:coverage
bun run audit

Build and preview:

bun run build
bun run preview

Documentation

Detailed documentation lives in docs/.

Architecture Summary

src/
|-- core/          Shared contracts, constants, and errors
|-- domain/        Pure validation, crop, format, and naming rules
|-- data/          Browser adapters for workers, storage, presets, ZIP, cache, and downloads
|-- presentation/  React UI, hooks, Zustand store, pages, and theme
|-- utils/         Shared utilities
|-- workers/       Conversion worker bridge to @walujanle/image-converter-wasm
`-- __tests__/     Vitest tests and binary fixtures

Imports inside src/ are written through the @/ alias, which resolves to src/.

Core flow:

page load
  -> converter worker warmup
  -> production cache registration when available

file selection
  -> validation
  -> mode-specific queue state
  -> conversion orchestration
  -> worker pool
  -> worker bridge
  -> @walujanle/image-converter-wasm decode/crop/resize/encode/metadata
  -> artifact download or ZIP

Security and Privacy Notes

  • Image conversion is local-first in the browser.
  • The repository has no upload API, cookies, or first-party analytics code.
  • Production static headers are generated into dist/_headers at build time and include a Content-Security-Policy, HSTS, Referrer-Policy, Permissions-Policy, nosniff, frame denial, COOP/COEP, and CORP directives.
  • The CSP is strict by default. Where a hosting platform injects its own scripts, extra sources can be allowed at build time through CSP_SCRIPT_ORIGINS (for script-src) and CSP_CONNECT_ORIGINS (for connect-src) without weakening the default for other deployments — see .env.example. The app needs neither; connect-src 'self' is what makes local-only processing browser-enforced, so widening it is a deliberate tradeoff described in Deployment Requirements.
  • The _headers format is host-specific and is ignored silently by hosts that do not support it. GitHub Pages cannot serve these headers at all, and some platforms override individual headers with their own settings. See Deployment Requirements before deploying or migrating hosts.
  • File validation checks declared MIME, binary signatures, and ISO BMFF brands where supported.
  • Large or unsafe images may be rejected before conversion.
  • Metadata preservation is opt-in because metadata can include private information such as location, camera, author, or editing history.

Accessibility Notes

The UI includes keyboard and screen-reader-oriented behavior, including focus states, skip-link support, modal semantics, switch semantics, mode button states, icon button labels, and live conversion status messaging.

Full WCAG conformance still requires manual assistive technology testing and automated accessibility checks outside the unit test suite.

Current Limits

  • Separate chunked streaming conversion does not exist; conversions use the worker pipeline after memory checks.
  • Maximum input size is about 10.7 MB for JPEG and WebP, and about 7.1 MB for PNG, AVIF, and HEIC. The limit is derived from a peak-memory model rather than chosen, because the browser engine holds the encoded input, the decoded frame, and the output at once. Oversized files are now rejected when you add them, with the real limit for that format in the message. Earlier versions advertised a 256 MB limit and then failed the conversion instead.
  • Images above 8192 x 8192 pixels are rejected. The engine cannot hold a larger decoded frame on a 32-bit WebAssembly heap, so this is a hard limit rather than a tuning choice.
  • AVIF output has limited metadata preservation compared with JPEG, PNG, and WebP.
  • GIF and BMP input are not part of the current Rust/WASM image engine contract.
  • Resize controls are available in advanced mode only with optional aspect ratio lock. Maximum resize input is 7680 px.
  • HEIC/HEIF is input-only; HEIC output encoding is intentionally unavailable in the current Rust/WASM engine.
  • PNG compression optimization is optional.
  • Auto suffix appends resolution and quality info to output filenames when enabled.
  • Numbering is available only when dataset log generation is enabled and applies to the generated dataset log file, not to individual filenames.
  • Dataset log generation forces non-individual downloads through ZIP packaging when enabled, including single-image batch downloads, so dataset_log.txt is delivered with the images.
  • Production bundle size is not stated here; run a fresh build when release measurement is required.

Validation Baseline

Last verified on 2026-07-28, against @walujanle/image-converter-wasm 1.1.0, TypeScript 6.0.3, Node 24.14.0, and Bun 1.3.14:

  • bun run lint: passed, on Biome's recommended preset.
  • bun run check: passed, including formatting and import order.
  • bun run typecheck: passed.
  • bun run test: 321 tests passed across 21 test files.
  • bun run test:coverage: passed, 44.92% statements and 42.71% branches, measured across all of src/.
  • bun run audit: no vulnerabilities found.
  • bun run build: passed.

The coverage figure is lower than 1.1.0's because it is now measured honestly. Coverage previously excluded the store, hooks, components, and worker bridge, reporting 96.57% over the pure layers alone. Nothing stopped being tested; the denominator more than doubled. See the Documentation Index for the full explanation.

Stable Status

The project is feature-complete and maintained as an archive. 1.1.1 was an audit release: no new features, two data-loss fixes, an honest set of quality gates, and documentation corrected against the source. 1.1.2 adds build-time CSP configuration and finishes the archival pass — one import alias across the source, explanatory comments moved into docs/, and formatting and import order verified repo-wide.

Legal compliance certification, full WCAG certification, and production header verification still depend on the final deployment environment and operational controls.

License

AGPL-3.0-only. See LICENSE.

This web app distributes and runs the @walujanle/image-converter-wasm package in the browser. That package is also licensed as AGPL-3.0-only, so the web app repository is licensed the same way for release consistency.

About

Image Converter Web App. Made with React, TypeScript, and Customised Image Converter WASM Engine Package.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages