use-courier

A headless React hook and Vue 3 composable for file uploads with progress tracking, retries, cancellation, and chunked uploads for large files.
1,449 1
Install
npm install use-courier
Latest Version:1.0.0
Vue:3
License:MIT
Last Updated:Oct 20, 2026
Links: GitHub  ·  npm
Maintainer: mrphilipp7

useCourier logo

use-courier

npm version license

A headless React hook and Vue 3 composable for file uploads with real progress tracking, retries, cancellation, and chunked uploads for large files.

Why useCourier?

fetch can't report upload progress — there's no way to know how many bytes of a file have actually been sent, only when the whole request finishes. useCourier uses XMLHttpRequest under the hood specifically to expose real 0-100% upload progress, wrapped in a small, typed, headless hook you build your own upload UI on top of.

  • Real upload progress — accurate 0-100% progress per file as bytes are actually sent, not a spinner
  • Retries — re-run a failed upload without asking the user to re-select the file
  • Cancellation — abort an in-flight upload, or every upload in flight on unmount
  • Chunked uploads — automatically splits large files into sequential requests, retrying failed chunks independently
  • Authenticated APIs — send auth headers (including async tokens), cookies, and extra form fields with every request
  • Lifecycle callbacks — beforeUpload, onUploadSuccess, onUploadError, onUploadFinish, onUploadRetry, onRemoveFile
  • React and Vue — the same API as a React hook (use-courier) and a Vue 3 composable (use-courier/vue)
  • Headless — no UI, no styling opinions; works with any component library
  • Typed — full TypeScript support, generic over your API's response shape

Installation

npm install use-courier

use-courier supports React 18 and 19, and Vue 3.3 and later. Install only the framework you use.

Basic usage

React

import type { ChangeEvent } from "react";
import { useCourier } from "use-courier";

export function FileUpload() {
  const { files, addFile } = useCourier({
    url: "/api/uploads",
  });

  function handleFileChange(event: ChangeEvent<HTMLInputElement>) {
    Array.from(event.target.files ?? []).forEach((file) => {
      void addFile(file);
    });
  }

  return (
    <>
      <input type="file" multiple onChange={handleFileChange} />
      {files.map((item) => (
        <p key={item.id}>
          {item.file.name}: {item.status} ({item.uploadProgress}%)
        </p>
      ))}
    </>
  );
}

Vue

<script setup lang="ts">
import { useCourier } from "use-courier/vue";

const { files, addFile } = useCourier({ url: "/api/uploads" });

function handleFileChange(event: Event) {
  const input = event.target as HTMLInputElement;
  Array.from(input.files ?? []).forEach((file) => addFile(file));
}
</script>

<template>
  <input type="file" multiple @change="handleFileChange" />
  <p v-for="item in files" :key="item.id">
    {{ item.file.name }}: {{ item.status }} ({{ item.uploadProgress }}%)
  </p>
</template>

Documentation

Full API reference, backend integration guides for Express, Next.js, TanStack Start, and Hono, large-file chunking details, and a Shadcn attachments integration:

useCourier Documentation

The docs also publish an llms.txt and llms-full.txt for LLM tooling.

License

MIT © Zach Philipp

Related Packages

@visulima/storage-client

The upload client library. Simple and easy file uploads for React | Vue | Solid...

112,635 53
@schema-element-editor/host-sdk

Schema Element Editor (SEE) 插件宿主接入 SDK,支持 React/Vue/纯 JS

9,323 2
@netipar/chunky-vue3

Vue 3 composables and components for Laravel Chunky chunk uploads

7,403 0
@pinooxhq/pinion-client

Client for Pinion — resumable uploads with fetch or Axios, retry, resume, progre...

445 3
aws-s3

S3Client - A Javascript Library for AWS S3 File Upload

104,930 115

Version History

Version Released Vue License
1.0.0 ^3.3.0 MIT
0.8.0 ^3.3.0 MIT
0.7.1 MIT
0.7.0 MIT
0.6.0 MIT