Skip to main content

Uppy 3.0: Future-proof, conveniently easy, stable as ever

· 7 min read

Screenshot of Uppy 3.0.0 UI

For those new to Uppy, coming from Reddit, Hacker News and Product Hunt today: Uppy is a popular open source file uploader for the browser. Pick files from local disk or camera, remote sources like Instagram, Unsplash, Dropbox etc, record audio and screencasts. Crop and tweak images with the image editor plugin. Supports resumable uploads to a server, AWS S3 (and many others with similar API like DigitalOcean), multipart. Try it!

Uppy is turning three! When you’re counting in dog years – which we most certainly are – that’s 29 already. An age like that signifies proper adulthood. For Uppy, this means it’s ready to stay loyal, but without the silly mistakes (read: bugs). Uppy also underwent (ESM) surgery to keep it strolling by your side in the current ecosystem, and received other behavioral improvements 🐶

TL;DR: ESM transition, native mobile camera, new Remote Sources plugin, sweeping Companion rewrite and streaming support, async/await everything, React 18 and Vue 3 support, all examples rewritten.

ESM surgery

ECMAScript Modules (ESM) are the future and we’re ready to adopt it. Benefits over CommonJS include: improved security, better tree shaking, and a syntax that can be understood natively by browsers, which can greatly improve the DX if the tools are configured to take advantage of that.

Following in the footsteps of many other packages, we now only ship Uppy core and its plugins as ESM. For Uppy 2.x, we were shipping CommonJS.

If you are already using ESM or the CDN builds, nothing changes for you! If you are using CommonJS, you may have to add extra tooling for everything to work, or consider refactoring your codebase to ESM. Please refer to the Pure ESM package gist for more information and help on how to do that.

Less integration code with the new remote sources preset

We’ve introduced a new Uppy preset plugin, @uppy/remote-sources, which combines Instagram, Facebook, Google Drive, Box, Unsplash, Dropbox, One Drive, Zoom and any other remote cloud sources that Uppy will support in the future. The plugin only works with Dashboard and allows you to enable all the above sources in a single line.

Before, you had to manually include every cloud provider / remote source:

.use(Instagram, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
.use(GoogleDrive, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
.use(OneDrive, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
.use(Instagram, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
.use(Facebook, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
.use(Unsplash, {
companionUrl: COMPANION_URL,
companionAllowedHosts: COMPANION_ALLOWED_HOSTS,
// ...


uppy.use(RemoteSources, { companionUrl: COMPANION_URL });

To get started, check out the RemoteSources docs.

Robodog ends its service

Uppy is flexible and extensible through plugins, but the integration code could sometimes prove daunting. This is what brought Robodog to life. It served as an alternative with the same features, but with a more ergonomic and minimal API.

It did, however, come with its own set of new problems:

  • Robodog tries to do the exact same thing as Uppy, but looks like an entirely different product.
  • Users are faced with a confusing choice between using Robodog or using Uppy directly.
  • Robodog is more ergonomic because it’s limited. When hitting such a limit, the user has to refactor everything to Uppy using plugins.

This has now led us to deprecating Robodog and embracing Uppy for its strong suits: modularity and flexibility. At the same time, we’re also introducing something to take away some of the repetitive integration code: @uppy/remote-sources.

Are you using Robodog in your code base? You can check out the migration guide to see how you can transition to Uppy plugins without losing functionality. We have committed ourselves to extending Robodog support for one year to give our users more time to migrate.

Native mobile camera

As you are probably aware, Uppy’s Webcam plugin provides a nice UI for desktop devices to take pictures and record videos. Up until 3.0, the same UI was utilized on mobile as well.

Since most mobile devices have a system UI for taking pictures and recording videos – which is usually better than any custom solution we can offer – we’ve introduced a new option called mobileNativeCamera for the Webcam plugin:

uppy.use(Webcam, {
mobileNativeCamera: isMobile({ tablet: true }),

By default, it uses the is-mobile package to detect mobile devices, like smartphones and tablets, but you can manually set this option to true or false if you wish. When enabled, instead of the usual Camera/Webcam Uppy UI, users will be presented with buttons that open their device’s native camera interface:

Uppy native camera UI

videoConstraints.facingMode is also supported by this option via the capture attribute (in the browsers and devices that respect it).

uppy.use(Webcam, {
videoConstraints: {
facingMode: 'user',

The same applies to modes, allowing you to enable only video or only photos.

Devotedly stable

Since the Uppy 2.7.0 release, we’ve fixed over 95 bugs! This includes fixes to bugs that made uploading less stable, documentation corrections, and dependency upgrades.

Companion turns 4.0

Everyone’s favorite Companion also received some love.

Streaming upload

Streaming upload can now also be enabled in Companion when using Tus. This comes with greatly improved upload speeds and allows uploading up to hundreds of gigabytes without needing a large server storage. We found that this improves speeds by about 37% for a Google Drive upload of a 1 GB file (source). This feature was also available before Companion 4.0, but it didn’t work with Tus until now.

With streaming upload disabled (default), the whole file will be downloaded first. The upload will then start when the download has completely finished.

When streaming upload is enabled, Companion will start downloading the file from the provider (such as Google Drive), while at the same time starting the upload to the destination (such as Tus), and sending every chunk of data consecutively.

For more information, see the Companion docs.

Event emitter

Companion now has a server-side event emitter that can be used to detect when uploads start, finish and fail, without having to depend on the client (so it works even when users have closed their browser).

Example code:

const { app, emitter } =;

emitter.on('upload-start', ({ token }) => {
console.log('Upload started', token);

function onUploadEvent({ action, payload }) {
if (action === 'success') {, onUploadEvent); // avoid listener leak
console.log('Upload finished', token, payload.url);
} else if (action === 'error') {, onUploadEvent); // avoid listener leak
console.error('Upload failed', payload);
emitter.on(token, onUploadEvent);

Internal improvements

Companion’s internal request code and Providers have been rewritten to async/await, which has greatly simplified and reduced the amount of code. This will lead to less bugs and security issues, and make it easier to implement new custom Providers.

We have also replaced the deprecated request library with got. This also removed the need for purest.

And more!

  • Compressor is officially stable. The Compressor plugin for Uppy optimizes images (JPEG, PNG), saving on average up to 60% in size. It has proven itself through extensive battle testing.
  • AWS S3 Multipart also became more stable this release, as a result of us hammering out some of the last edge cases with lots of files and/or huge files.
  • React 18 is now supported in @uppy/react, Vue 3 is supported for @uppy/vue, and Angular 14 for @uppy/angular.
  • Our examples have received a fresh round of updates to keep them relevant.

Animate picture of a visibly happy dog getting a head massage

For more details, see the full changelog and the migration guide.

That’s it from us for now! As you can see, Uppy may be slowly turning into an old dog, but we’re still committed to keep teaching it new tricks. We hope you’ll enjoy this latest major release, and all the features and improvements it includes. We can’t wait to hear your thoughts about it on Twitter!