Self-hosted service
VERT-sh/VERT avatar
VERT-sh/VERT

VERT: A WebAssembly File Converter That Runs Locally in the Browser

The next-generation file converter. Open source, fully local* and free forever.

15,663 stars839 forksSvelteAGPL-3.0

At a glance

What is it?
VERT is a file conversion utility built in Svelte and TypeScript that runs conversion operations using WebAssembly directly in the user's browser, without uploading files to a server. It supports over 250 file formats across images, audio, and documents, with video conversion handled by an optional self-hostable daemon.
Who is it for?
VERT suits users and teams who need to convert images, audio, and document files without sending them to a third-party server. The WebAssembly execution model means the conversion work stays on the device running the browser, which is a concrete privacy property rather than a marketing claim.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Svelte, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What VERT Does and the Local Conversion Model

VERT is a file conversion utility that performs the conversion work in the user's browser using WebAssembly, rather than uploading files to a remote server. The README states it converts files directly on your device. There are no file size limits enforced by the application, and no account or login is required to use the public instance at vert.sh.

The supported file categories are images, audio, documents, and video, with over 250 formats listed as supported. Video is the exception to the local model: the README notes with an asterisk that non-local video conversion is available through the official instance, and explains that the vertd daemon must be self-hosted to maintain fully local video functionality.

VERT is built in Svelte 5 and TypeScript. The package.json shows it uses SvelteKit with a static adapter (@sveltejs/adapter-static), meaning the application builds to a set of static files served by a web server with no server-side rendering at request time. The WebAssembly conversion libraries are loaded in the browser and execute there.

WebAssembly Libraries and What They Handle

The package.json dependencies show two WebAssembly-based conversion libraries: @imagemagick/magick-wasm for image conversion (version 0.0.43) and @ffmpeg/ffmpeg with @ffmpeg/util for audio and video processing (version 0.12.x). ImageMagick compiled to WebAssembly handles the image and document format conversions; FFmpeg compiled to WebAssembly handles audio and, when available locally, video.

The .env.example file reveals a detail about the FFmpeg worker specifically: the comment states that the ffmpeg worker is still downloaded via a CDN (cdn.jsdelivr.net) even when PUB_DISABLE_ALL_EXTERNAL_REQUESTS is set to true. This is a notable gap in the fully-offline use case: disabling all external requests blocks the Plausible analytics, the vertd daemon, and Stripe, but it does not block the CDN download for the FFmpeg worker. Teams deploying in air-gapped environments need to account for this.

The @bjorn3/browser_wasi_shim dependency provides a WASI (WebAssembly System Interface) shim for the browser, enabling WebAssembly modules compiled with WASI support to run in the browser environment. The fflate package handles in-browser ZIP creation for bundling multiple converted files into a single download.

Running VERT and Deploying with Docker

The live instance runs at vert.sh and requires no installation for a casual user. For a self-hosted deployment, the repository includes a Dockerfile and a docker-compose.yml.

The docker-compose.yml deploys a single service using the pre-built image from the GitHub Container Registry:

yaml
services:
  vert:
    container_name: vert
    image: ghcr.io/vert-sh/vert:latest
    restart: unless-stopped
    ports:
      - ${PORT:-3000}:80

The Dockerfile builds from oven/bun (Bun as the JavaScript runtime and package manager), installs dependencies with bun install, runs the SvelteKit build, and then copies the static output into an nginx:stable-alpine image for serving. The final image is an nginx server with no Node.js runtime requirement.

Before building, copy .env.example to .env and set the build arguments. The key ones are PUB_HOSTNAME (used for analytics), PUB_VERTD_URL (the video conversion daemon URL), and PUB_DISABLE_ALL_EXTERNAL_REQUESTS (set to true to block Plausible, Stripe, and vertd requests). PUB_ENV should be set to production for a live deployment.

The local development setup uses:

bash
npm run dev

which runs the Vite dev server with hot module replacement. The build script includes a paraglide-js compile step for internationalization before the Vite build.

Video Conversion and the vertd Daemon

Video conversion is the one area where VERT's local-first model has a clear boundary. The README's features list includes video with an asterisk, and the footnote explains: non-local video conversion is available with the official instance, but the vertd daemon is easily self-hostable to maintain privacy and fully local functionality.

The .env.example file shows the default PUB_VERTD_URL is https://vertd.vert.sh. When this URL points to the official instance and the user converts a video, the file is sent to that server for processing. The README links to the vertd repository at https://github.com/VERT-sh/vertd for teams that want to self-host the daemon.

The .env.example also shows PUB_DISABLE_FAILURE_BLOCKS, which defaults to false. When false, VERT blocks repeated video conversion attempts for a file that has failed multiple times within an hour. The comment notes this requires HTTPS to calculate file hashes, and suggests setting it to true for local deployments where HTTPS is not available. This is a detail that matters for development and testing environments rather than production deployments.

Privacy Configuration and External Requests

The .env.example documents five external services that VERT can contact by default. Plausible Analytics receives page view events when PUB_PLAUSIBLE_URL is set. The vertd daemon receives video files for conversion. Stripe handles donation flows when PUB_STRIPE_KEY is set. The CDN at cdn.jsdelivr.net serves the FFmpeg WebAssembly worker regardless of PUB_DISABLE_ALL_EXTERNAL_REQUESTS.

Setting PUB_DISABLE_ALL_EXTERNAL_REQUESTS to true in the build configuration disables Plausible, Stripe, and vertd. The donation URL defaults to https://donations.vert.sh, which can also be left unset for a deployment that does not want to display donation prompts.

For a deployment where all network requests should stay within a controlled environment, the FFmpeg CDN dependency is the remaining gap. The .env.example is explicit that this cannot be disabled through the existing configuration flag. A team in a fully air-gapped environment would need to serve the FFmpeg WebAssembly worker from an internal host and modify the code to reference it.

VERT Compared to ConvertX

ConvertX appears in the VERT-related search data as a direct comparison. Both are open-source file converters. The key architectural difference is where the conversion runs: VERT uses WebAssembly to execute the conversion in the user's browser, so the file never leaves the device for image, audio, and document formats. ConvertX runs conversions server-side; users upload their file to the server.

For a self-hosted deployment, ConvertX's server-side approach means the conversion work runs on the host machine's CPU, which handles large files more predictably than the browser's WebAssembly sandbox. VERT's browser-side execution means the conversion speed and memory limits depend on the user's device, not the server.

For the public instance use case, VERT's approach is the more privacy-preserving choice for image and audio conversions, since no file data is transmitted. The trade-off is that very large files or formats that stress the browser's memory limits may fail in VERT where a server-side tool would succeed. The README does not document specific memory limits or tested maximum file sizes.

License and Self-Hosting Considerations

VERT is licensed under AGPL-3.0. This license requires that anyone who distributes a modified version of VERT, including deploying a modified version accessible over a network, must make the modified source code available under the same license. For a team that simply self-hosts the unmodified VERT for internal use, this is a straightforward obligation. For a team that modifies VERT and offers it as a service to external users, the source disclosure requirement applies.

The last push to the main branch was on 2026-09-27. The repository is not archived. The package.json version is 0.0.1, which reflects the project's versioning convention rather than maturity; the live instance at vert.sh is an actively used production deployment.

Contributing guidelines are in CONTRIBUTING.md. The internationalization system uses @inlang/paraglide-js with message files in the messages/ directory, which means adding a new language is a matter of adding a translation file rather than modifying the core application.

Editorial conclusion

VERT suits users and teams who need to convert images, audio, and document files without sending them to a third-party server. The WebAssembly execution model means the conversion work stays on the device running the browser, which is a concrete privacy property rather than a marketing claim. Teams that need video conversion with the same privacy guarantee should self-host the vertd daemon rather than rely on the official instance, since the official instance processes video server-side. The AGPL-3.0 license requires that anyone distributing a modified version of VERT must release their modifications as source. Before deploying a private instance, read the .env.example file to understand which external services are contacted by default: Plausible analytics, the vertd daemon, and Stripe for donations can each be disabled or replaced.

Frequently asked questions

Is VERT safe to use for sensitive files?

For image, audio, and document formats, VERT uses WebAssembly to convert files in the browser, so the file data does not leave the device when using those formats. Video conversion through the official instance sends the file to the vertd server at vertd.vert.sh. For sensitive video files, self-host the vertd daemon as described in the README.

Does VERT have a file size limit?

The README states there are no file size limits enforced by the application. Practical limits depend on the browser's available memory for WebAssembly execution, since conversion runs on the user's device rather than a server.

Can VERT be self-hosted without any external network requests?

Setting PUB_DISABLE_ALL_EXTERNAL_REQUESTS to true in the build configuration disables Plausible analytics, Stripe, and the vertd video daemon. However, the .env.example notes that the FFmpeg WebAssembly worker is still downloaded from cdn.jsdelivr.net even with that flag set, which means a fully air-gapped deployment requires additional configuration.

Official sources

  1. Issues
  2. License: AGPL-3.0
  3. Project website
  4. README
  5. VERT-sh/VERT on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vert-sh-vert.svg)](https://hysenlabs.com/projects/vert-sh-vert)