npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gw-intech/upload-it

v0.3.6

Published

Flexible and reusable file upload library with support for S3 and filesystem storage

Downloads

2

Readme

UploadIt

A flexible and reusable file upload library with support for S3 and filesystem storage.

Features

  • 📤 Direct client-side uploads to S3
  • 💾 Local filesystem support
  • 🔒 Secure server-side credential handling
  • 📊 Upload progress tracking
  • 🔄 Automatic URL refreshing
  • ⚛️ React components and hooks
  • 📱 Next.js integration
  • 🔌 Provider-based architecture
  • 📂 File management utilities
  • 📑 Intuitive file listing with icons

Latest Updates (v0.3.6)

  • 🎨 Enhanced FileList component with file type icons - Beautiful visual indicators for different file types
  • 🖼️ Option to display file icons instead of image previews - More consistent UI and better performance
  • 🗂️ File management utilities - Easy-to-use functions for listing, fetching, and deleting files
  • 🔄 Improved filesystem integration - Better fallbacks for direct filesystem operations

Installation

npm install @gw-intech/upload-it
# or
yarn add @gw-intech/upload-it
# or
pnpm add @gw-intech/upload-it

Browser Compatibility

The library is designed to work in both browser and Node.js environments:

  • S3 Provider: Fully supported in browsers
  • Filesystem Provider: Only for server-side use (Node.js)

When using the library in client-side applications (like Vite, Create React App, etc.), you should:

  1. Use the S3 provider for direct client-side uploads
  2. Or set up server endpoints for secure uploads
// ✅ Works in browsers
import { UploadButton } from '@gw-intech/upload-it';

function App() {
  return (
    <UploadButton
      provider='s3'
      s3={{
        region: 'us-east-1',
        bucket: 'my-bucket',
        credentials: {
          // For development only! Use server mode in production
          accessKeyId: '...',
          secretAccessKey: '...',
        },
      }}
    />
  );
}

// ❌ Won't work in browsers - filesystem requires Node.js
import { UploadButton } from '@gw-intech/upload-it';

function App() {
  return (
    <UploadButton
      provider='filesystem' // ⚠️ This won't work in browsers
      filesystem={{
        uploadDir: './public/uploads',
        publicPath: '/uploads',
      }}
    />
  );
}

Usage

Basic Usage with React Component

import { UploadButton } from '@gw-intech/upload-it';

function MyApp() {
  return (
    <UploadButton
      provider='s3'
      s3={{
        region: 'us-east-1',
        bucket: 'my-bucket',
        credentials: {
          /* For development only! See secure usage below */
        },
      }}
      onUploadComplete={(files) => console.log('Uploaded files:', files)}
      multiple={true}
      accept='image/*,.pdf'
    />
  );
}

Secure Usage with Next.js

When using Next.js, you'll need to import the server-specific routes from the /server subpath:

  1. Create API routes for uploads:
// app/api/upload/presigned/route.ts
import { presignedUrlRoute } from '@gw-intech/upload-it/server';
export { presignedUrlRoute as POST };

// app/api/upload/complete/route.ts
import { completeUploadRoute } from '@gw-intech/upload-it/server';
export { completeUploadRoute as POST };

// app/api/upload/url/[fileKey]/route.ts
import { getFileUrlRoute } from '@gw-intech/upload-it/server';
export { getFileUrlRoute as GET };
  1. Configure environment variables:
UPLOAD_IT_S3_REGION=us-east-1
UPLOAD_IT_S3_BUCKET=my-bucket
UPLOAD_IT_S3_ACCESS_KEY=your-access-key
UPLOAD_IT_S3_SECRET_KEY=your-secret-key
UPLOAD_IT_S3_FOLDER=uploads
  1. Use the component with server mode:
import { UploadButton } from '@gw-intech/upload-it';

function MyApp() {
  return (
    <UploadButton
      provider='s3'
      server={{
        mode: 'server',
        endpoints: {
          getUploadUrl: '/api/upload/presigned',
          completeUpload: '/api/upload/complete',
          getAccessUrl: '/api/upload/url',
        },
      }}
      onUploadComplete={(files) => console.log('Uploaded files:', files)}
    />
  );
}

Using with Vite or non-Next.js environments

When using Vite or other build systems, you only need to import from the main package:

import {
  UploadButton,
  useUploader,
  createUploader,
} from '@gw-intech/upload-it';

The Next.js specific routes are isolated in the /server subpath to avoid dependency conflicts.

Using the React Hook

import { useUploader } from '@gw-intech/upload-it';
import { useState } from 'react';

function MyUploader() {
  const [files, setFiles] = useState([]);

  const uploader = useUploader({
    provider: 's3',
    s3: {
      region: 'us-east-1',
      bucket: 'my-bucket',
      credentials: {
        /* ... */
      },
    },
    onSuccess: (uploadedFiles) => {
      setFiles(uploadedFiles);
    },
  });

  const handleFileChange = async (e) => {
    const selectedFiles = e.target.files;
    if (selectedFiles.length > 0) {
      await uploader.uploadFiles(Array.from(selectedFiles));
    }
  };

  return (
    <div>
      <input type='file' multiple onChange={handleFileChange} />
      {uploader.isUploading && (
        <div>
          Uploading... {Object.values(uploader.progress)[0]?.percentage}%
        </div>
      )}
      {files.map((file) => (
        <div key={file.key}>
          {file.name} -{' '}
          <a href={file.url} target='_blank' rel='noopener noreferrer'>
            View
          </a>
        </div>
      ))}
    </div>
  );
}

Filesystem Storage

import { UploadButton } from '@gw-intech/upload-it';

function MyApp() {
  return (
    <UploadButton
      provider='filesystem'
      filesystem={{
        uploadDir: './public/uploads',
        publicPath: '/uploads',
      }}
      onUploadComplete={(files) => console.log('Uploaded files:', files)}
    />
  );
}

Core API (Non-React)

import { createUploader } from '@gw-intech/upload-it';

const uploader = createUploader({
  provider: 's3',
  s3: {
    region: 'us-east-1',
    bucket: 'my-bucket',
    credentials: {
      /* ... */
    },
  },
  onUploadProgress: (file, progress) => {
    console.log(`${file.name}: ${progress.percentage}%`);
  },
});

async function uploadFile(file) {
  try {
    const result = await uploader.uploadFile(file);
    console.log('File uploaded:', result);
    return result;
  } catch (error) {
    console.error('Upload failed:', error);
  }
}

Component Props

UploadButton Props

The UploadButton component accepts the following props:

Core Configuration

| Prop | Type | Required | Description | | ------------------ | ---------------------- | ----------------------------- | ---------------------------------------------- | | provider | 's3' \| 'filesystem' | Yes | Storage provider to use | | s3 | S3Config | Only with s3 provider | S3 configuration | | filesystem | FilesystemConfig | Only with filesystem provider | Filesystem configuration | | server | ServerConfig | No | Server configuration for secure mode | | maxFileSize | number | No | Maximum file size in bytes | | allowedFileTypes | string[] | No | Allowed file types (e.g., ['image/*', '.pdf']) |

UI Customization

| Prop | Type | Required | Default | Description | | -------------------- | ----------------- | -------- | --------------- | ----------------------------------- | | className | string | No | '' | CSS class applied to the button | | buttonText | string | No | 'Upload' | Text displayed on the button | | children | React.ReactNode | No | null | Content to render inside the button | | showProgressDialog | boolean | No | true | Whether to show the progress dialog | | dialogTitle | string | No | 'Upload File' | Title for the progress dialog |

Upload Options

| Prop | Type | Required | Default | Description | | ---------- | --------- | -------- | ----------- | ---------------------------------------- | | multiple | boolean | No | false | Allow multiple file selection | | accept | string | No | undefined | File type filter (e.g., "image/*,.pdf") | | folder | string | No | undefined | Optional folder path for uploaded files |

Callbacks

| Prop | Type | Required | Description | | ----------- | --------------------------------- | -------- | ----------------------------------------- | | onSuccess | (files: FileMetadata[]) => void | No | Called when uploads complete successfully | | onError | (error: Error) => void | No | Called when an error occurs |

Advanced Customization

| Prop | Type | Required | Description | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------- | | renderButton | (props: { onClick: () => void; isUploading: boolean }) => React.ReactNode | No | Custom button rendering | | renderDialog | (props: { isOpen: boolean; onClose: () => void; progress: number; isComplete: boolean; hasErrors: boolean; }) => React.ReactNode | No | Custom dialog rendering |

Configuration Options

Common Options

| Option | Type | Description | | ------------------ | ---------------------- | ------------------------------------------------ | | provider | 's3' \| 'filesystem' | Storage provider to use | | maxFileSize | number | Maximum file size in bytes | | allowedFileTypes | string[] | Allowed file types (e.g., ['image/*', '.pdf']) |

S3 Provider Options

| Option | Type | Description | | -------------- | -------------------------------------------------- | ------------------------------------------- | | region | string | AWS region | | bucket | string | S3 bucket name | | credentials | { accessKeyId: string, secretAccessKey: string } | AWS credentials | | endpoint | string | Custom endpoint (for S3-compatible storage) | | uploadFolder | string | Folder prefix for uploaded files |

Filesystem Provider Options

| Option | Type | Description | | --------------------- | --------- | ------------------------------------ | | uploadDir | string | Directory to store uploaded files | | publicPath | string | Public URL path to access files | | createDirIfNotExist | boolean | Create directory if it doesn't exist |

Server Options

| Option | Type | Description | | ----------- | --------------------------------------------------------------------------- | ------------------------------------ | | mode | 'client' \| 'server' | Whether to use client or server mode | | endpoints | { getUploadUrl?: string, completeUpload?: string, getAccessUrl?: string } | API endpoints for server operations |

License

MIT