Skip to content

dearabhin/metadata-cleaner

Repository files navigation

Metadata Cleaner

A fully client-side, privacy-first web app to inspect, edit, remove and export metadata from virtually any file type — images, video, audio, documents, archives and more.

Everything happens entirely inside your browser. No files are uploaded anywhere. No analytics. No telemetry. No tracking. Works offline as a PWA.

Built with Vue 3 + Vite + TypeScript + Pinia + TailwindCSS. The metadata engine is the real ExifTool 13.x compiled to WebAssembly (@uswriting/exiftool), run inside a Web Worker so the UI never freezes — giving you exactly what the exiftool command line shows, in the browser.


✨ Features

Area What you get
Inspect Everything ExifTool reads — EXIF · IPTC · XMP · ICC · GPS · PNG chunks · JPEG segments · ID3/Vorbis/FLAC · MP4/QuickTime atoms · Matroska tags · PDF & Office properties · C2PA / JUMBF provenance · maker notes · hundreds more · plus SHA-256 & magic bytes
Views Flat (verbatim exiftool Tag : Value) · Grouped · JSON · Hex — with search, filtering, collapse/expand, copy value / copy all / copy JSON
Edit Writable fields across many formats (images, PDF, audio/video) via ExifTool writeMetadata, with validation
Remove EXIF · GPS · XMP · IPTC · thumbnails · comments · maker notes · all · deep clean
Batch Drag whole folders, multi-select, bulk deep clean → ZIP download
Compare Original vs. cleaned/edited metadata diff (added / removed / modified)
Preview Inline image / video / audio player and PDF viewer
Export Metadata as JSON · TXT · CSV; download cleaned/edited files
UX Dark/light mode · mobile responsive · keyboard shortcuts · drag-and-drop · accessible (focus rings, ARIA, skip link, high-contrast aware)

Keyboard shortcuts

/ focus search · 14 Flat / Grouped / JSON / Hex · j/k next/previous file · d toggle theme · esc clear search


🧱 Architecture

src/
├─ components/        Reusable Vue components (viewer, panels, dropzone, …)
│  └─ viewer/         Flat / Grouped / JSON / Hex views + viewer toolbar
├─ composables/       useDropzone, useClipboard, useKeyboard
├─ parsers/           capabilities (writable formats) + exiftoolJson (normalise)
├─ services/          exiftool.ts (engine wrapper) + workerClient (promise API)
├─ stores/            Pinia stores (files, ui)
├─ types/             Shared TypeScript types
├─ utils/             format, hex, hash, export, files helpers
├─ views/             Router views (Home, About)
└─ workers/           metadata.worker.ts — runs ExifTool off the main thread

Flow: a dropped file → stores/files reads its bytes (computing SHA-256 / magic bytes / hex preview) → services/workerClient transfers the ArrayBuffer to workers/metadata.worker → the worker runs ExifTool (services/exiftool.ts) and parsers/exiftoolJson.ts normalises the output into grouped + flat + JSON form. Edits/cleans call ExifTool writeMetadata and the result is re-parsed for Compare mode. The ~25 MB wasm engine is lazy-loaded on first use (with a progress bar) and runtime-cached for offline use.

Key libraries

@uswriting/exiftool — ExifTool 13.x via WebAssembly (@6over3/zeroperl-ts) · JSZip for batch ZIP export. Both run fully in the browser.


🚀 Getting started

npm install
npm run dev        # http://localhost:5173

Build & preview the production bundle:

npm run build      # type-checks then builds to dist/
npm run preview

🌍 Deployment

The output is a static site in dist/. It uses hash-based routing, so it works on any static host with no server rewrite rules.

GitHub Pages

A workflow is included at .github/workflows/deploy.yml. Push to main and enable Pages → "GitHub Actions". For a project page (user.github.io/repo/) the base path is set automatically from the repo name via VITE_BASE_PATH.

# Manual build for a project sub-path:
VITE_BASE_PATH=/your-repo/ npm run build

Cloudflare Pages

  • Build command: npm run build
  • Build output directory: dist
  • (Custom domain / root deploy: leave VITE_BASE_PATH unset.)

Vercel

vercel.json is included. Framework preset: Vite. Output dir: dist.

Netlify

netlify.toml is included. Build command npm run build, publish dist.


🔐 Privacy

There is no backend. Files are read with the File/Blob APIs, processed in a Web Worker, and never leave the device. The only network requests are for the static app assets themselves (and none at all once the PWA is cached). The app ships with no analytics, trackers or third-party beacons.


⚠️ Notes

  • First load: the ExifTool engine is a one-time ~25 MB (≈7.7 MB gzipped) WebAssembly download, fetched lazily on your first file with a progress bar and then cached (it is deliberately not in the service-worker precache, so the app shell stays tiny). After that it runs fully offline.
  • Reading covers everything ExifTool supports.
  • Editing / removal is enabled for ExifTool's writable formats (JPEG, TIFF, PNG, WebP, PDF, many RAW formats, MP4/MOV, MP3/FLAC…). Other containers are read-only in the browser — you can still inspect and export their metadata.

📄 License

MIT

About

A fully client-side, privacy-first web app to inspect, edit, remove and export metadata from virtually any file type — images, video, audio, documents, archives and more.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors