Library / SDK
pqina/vue-filepond avatar
pqina/vue-filepond

vue-filepond: a Vue 3 adapter whose build still runs on Vue 2

🔌 A handy FilePond adapter component for Vue

2,001 stars117 forksJavaScriptMIT

At a glance

What is it?
vue-filepond wraps the FilePond upload widget so a Vue app can drive it with template attributes, but the npm install line covers two packages while the factory call needs separate plugins, and the development tree still pins Vue 2.6.11.
Who is it for?
Vue 3 teams that want FilePond's drop, paste and directory upload with previews get a small adapter that removes most of the glue a hand-written wrapper needs, so the factory call and the `this.$refs.pond` handle make it worth installing. Vue 2 projects must stay on `vue-filepond@^6.0.0`, since the current peer range rejects them outright.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 102 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

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

Editorial analysis

One factory call turns FilePond options into Vue props

vue-filepond is an adapter, not an upload library of its own. It takes the instance FilePond builds and exposes it as a Vue component, so FilePond settings such as `server`, `label-idle` and `accepted-file-types` become attributes on a `<file-pond>` tag instead of a JavaScript configuration object. The plugin list is decided in code rather than in markup. Registration is one import plus one call: the example hands the factory a file type validation plugin and an image preview plugin, and the value that comes back is what you register under `components`. Because the component is produced by a factory and not exported directly, the plugin set is fixed when the module loads. A component that needs a third plugin has to call the factory with it, and two components wanting different plugin sets have to build two component objects.

Who this is for is narrow and clear. It suits a Vue app that wants FilePond's drop, browse, paste and directory behaviour without writing its own wrapper element and its own lifecycle plumbing. What it carries is none of the transport code. `server="/api"` only names an endpoint, and the README gives FilePond the job of sending bytes, either as an asynchronous request or as base64 data carried along in a form post.

The peer range says Vue 3, the dev tree pins 2.6.11

package.json sets peerDependencies to `>=3 < 4` for vue and `>=4.7.4 < 5.x` for filepond, so a Vue 2 project cannot install the current adapter at all. The development dependencies sitting a few lines below say something different. There, vue is pinned to 2.6.11 and filepond to 4.9.3.

Put the two blocks together and the tree the maintainers compile against is a Vue 2 tree, while the tree a user is permitted to install is a Vue 3 tree. Nothing in the repository bridges that gap, and the Vue 3 claim rests on the peer range alone. A second boundary hides in the same file: the upper bound `< 5.x` excludes FilePond 5, pinning the adapter to a FilePond 4 line.

The version field adds a third wrinkle. It reads 8.0.0, while the two most recent published entries are 5.1.3 from 2019-08-05 and 5.1.2 from 2019-07-19. The package is MIT licensed and the last push was on 2026-07-13, so the source tree has moved on since then without a matching published version behind it.

Two plugins are named, the rest of the feature list is not

The install line is `npm install vue-filepond filepond` and it installs nothing else. Everything beyond those two packages comes from separate npm packages, and the source file says so in a comment above the plugin imports, telling you that you need to install these plugins separately. Type validation and image previews are therefore two extra installs you only discover by reading the imports. Copy the install line on its own and you end up with a drop zone, no enforcement of `accepted-file-types`, and no thumbnail previews.

The feature list at the top of the README is wider than the setup it documents. It promises that FilePond accepts directories, files, blobs, local URLs, remote URLs and Data URIs, and that it does automatic image resizing, cropping, and fixes EXIF orientation. Only two plugin packages are named anywhere in the file. Resizing and cropping have no package named for them in the example, which means the promise and the imports are not the same list.

For editing beyond a resize, the README points at Pintura, a separate image editor from the same author, for crop aspect ratios, resizing, rotating, cropping and flipping, and says it integrates with FilePond. Accessibility claims travel on the same list: tested with AT software like VoiceOver and JAWS, and navigable by keyboard. All of that describes FilePond itself, and the adapter adds no accessibility layer of its own.

Mounting the component and binding files to data

Install the adapter and FilePond core, then register the factory in the same file as the component that uses it.

bash
npm install vue-filepond filepond

In the template, FilePond settings are plain attributes, and two bindings carry data in each direction: `v-bind:files` hands your array to the widget and `v-on:init` calls back when the component reports ready. The `ref="pond"` attribute on the tag is what makes the underlying instance reachable later.

vue
<script>
// Import Vue FilePond
import vueFilePond from "vue-filepond";

// Import FilePond styles
import "filepond/dist/filepond.min.css";

// Import image preview and file type validation plugins
import FilePondPluginFileValidateType from "filepond-plugin-file-validate-type";
import FilePondPluginImagePreview from "filepond-plugin-image-preview";

// Create component
const FilePond = vueFilePond(
  FilePondPluginFileValidateType,
  FilePondPluginImagePreview
);
</script>

Every import above names a different package, and two of them are style sheets that point inside FilePond and inside a plugin. Drop the CSS imports and the widget renders unstyled.

In the component body, `data` starts with one entry, `["cat.jpeg"]`, which is how a file that already exists is shown on first render. The init handler logs a line, and its comment states that FilePond instance methods are available on `this.$refs.pond`. That reference is the documented handle for calling into the widget from your own code.

Server rendered apps need the no-ssr wrapper

When a Vue app is served through Nuxt.js, the widget has to stay out of the server render pass. The guidance is a single wrapper element, and nothing further is documented about it.

vue
<template>
  <no-ssr>
    <file-pond />
  </no-ssr>
</template>

The reason is visible in the attribute style of the props. FilePond settings arrive as HTML attributes on a custom element, so they mean nothing until the browser has mounted the client side runtime. The repository documents no alternative to the wrapper for that case.

There is a layout cost. A `<no-ssr>` boundary means the server sends no markup for the widget at all, so any page that reserves space by measuring the element before hydration needs its own placeholder. The repository ships an `example` directory with its own `package.json`, `babel.config.js`, `public` and `src`, and no server side rendering arrangement is described inside that tree.

The paste and run browser page still mounts Vue 2

The README also carries a plain HTML page that runs from unpkg with no build step, and it is the one sample you can save to a file and open directly.

html
    <script src="https://unpkg.com/filepond-plugin-image-preview"></script>
    <script src="https://unpkg.com/filepond"></script>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/vue-filepond@6"></script>

It pins the adapter to version 6 on the CDN while the install line further up installs the current major, so the two paths in the same document target different major versions. The mount code that follows is Vue 2 as well, with `new Vue` and an el option pointing at a div that already exists in the page.

js
      new Vue({
        el: "#app",
        components: {
          FilePond: vueFilePond.default(FilePondPluginImagePreview),
        },
      });

Neither `new Vue` nor the el option exists in Vue 3, so this block cannot run against the range in peerDependencies. Read next to the note that Vue 2 users should install `npm install vue-filepond@^6.0.0`, the file carries two different answers to which version to use. Script order matters in the snippet too: the plugin loads before FilePond and before Vue, and the factory is reached through `.default` in the last block, which the sample does not explain.

The build writes three files into a checked in dist

Building is four npm scripts. The top level `build` creates the output directory and runs two pipelines, one for the browser bundle and one for the module build.

bash
mkdirp dist && npm run build:browser && npm run build:module

Those two pipelines do not treat their input the same way. One pipes an entire directory through Babel, the other concatenates a single file and adds a banner.

bash
babel lib | bannerjs -m > dist/vue-filepond.js
bash
cat lib/index.js | bannerjs -m > dist/vue-filepond.esm.js

Only the browser bundle is minified, and it is written by the `postbuild:browser` hook rather than by the build script itself. That is why the `unpkg` entry points at a file which does not exist until npm runs that lifecycle step, and why a plain `npm run build` without the hook leaves the CDN target missing.

The `dist` directory appears in the top level repository listing next to the lib sources, `.babelrc` and `types`, and the package publishes `dist` rather than its sources, with `files` limited to that directory and `types/*.d.ts`. Contributors can therefore read the same component twice, once in lib and once in `dist`, and a watcher script for rebuilding is available as `build:watch`.

What the adapter leaves undocumented for server errors

The adapter is deliberately thin, and the thinness shows up as work you have to absorb. package.json defines six scripts, running from `build` through `build:watch` to `prepare`, and none of them executes a test. The top level repository entries contain no test directory either, so a change to the mapping between props and FilePond options has no automated check behind it.

The README does not document what the widget expects back from `server="/api"`, which leaves the response contract with your endpoint to be worked out from FilePond's own documentation. There is no two way binding shorthand in the sample either. `v-bind:files="myFiles"` pushes your array in, and the data function seeds it with `["cat.jpeg"]`, yet nothing states what happens to that array when a file is removed from the widget, or what the component emits when the server rejects an upload.

The Vue 3 path is missing too. The installation note covers a Vue 2 escape hatch, the browser page uses Vue 2 mount code, and the only Vue 3 signal anywhere in the repository is the peer range in package.json.

Editorial conclusion

Vue 3 teams that want FilePond's drop, paste and directory upload with previews get a small adapter that removes most of the glue a hand-written wrapper needs, so the factory call and the `this.$refs.pond` handle make it worth installing. Vue 2 projects must stay on `vue-filepond@^6.0.0`, since the current peer range rejects them outright. Check two things before wiring it in: that your plugins exist as separate npm packages, and that the endpoint behind `server="/api"` returns the shape FilePond expects.

Frequently asked questions

Which Vue versions can install vue-filepond?

package.json declares peerDependencies of `>=3 < 4` for vue and `>=4.7.4 < 5.x` for filepond, so the current version targets Vue 3 only. For Vue 2, the installation note directs you to `npm install vue-filepond@^6.0.0`.

Does installing vue-filepond give me image previews and file type validation?

No. The install line `npm install vue-filepond filepond` covers only the adapter and FilePond core. The plugins are separate packages, and the example passes them to the factory as arguments.

How do I use vue-filepond in a Nuxt.js application?

The README says to wrap the component in `<no-ssr>` tags when working with an SSR configuration such as Nuxt.js. No further server side guidance is given.

How do I get a reference to the FilePond instance in my component?

Add `ref="pond"` to the tag and the instance methods are available on `this.$refs.pond`, as the comment in the example states. The component also emits an init event through `v-on:init`.

Which files are shipped in the published npm package?

The `files` array in package.json lists `dist` and `types/*.d.ts` only. The lib sources, the `example` application and the config files are not part of the published package.

Official sources

  1. License: MIT
  2. pqina/vue-filepond on GitHub
  3. Project website
  4. README
  5. Releases
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/pqina-vue-filepond.svg)](https://hysenlabs.com/projects/pqina-vue-filepond)

Was this useful?