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

payload-files-proxy

v2.0.1

Published

Plugin to getting production files on a development server on demand.

Readme

Payload Files Proxy

Small Payload CMS plugin to fetch missing media files from an origin site during local development, inspired by Drupal's stage_file_proxy approach.

Use this when you do not want to sync a large uploads folder locally but still need media files to appear in pages and the admin UI.

Requirements and compatibility

  • Node.js ^22.23.4 || >=24.22.1 and Payload CMS ^3.92.0.
  • The development application uses Payload 3.92.0, Next.js 15.4.11, and React / React DOM 19.1.2. Earlier Payload and Node versions are no longer supported by this package.

Install

npm install payload-files-proxy
# or
pnpm add payload-files-proxy
# or
yarn add payload-files-proxy

Quick Start

import path from 'path'
import { buildConfig } from 'payload'
import { payloadFilesProxy } from 'payload-files-proxy'

export default buildConfig({
  collections: [
    {
      slug: 'media',
      upload: {
        staticDir: path.resolve('./uploads'),
      },
    },
  ],
  plugins: [
    payloadFilesProxy({
      mediaCollectionSlug: 'media',
      mediaDirectory: path.resolve('./uploads'),
      originUrl: 'https://your-production-site.com',
      disabled: process.env.NODE_ENV === 'production',
    }),
  ],
})

Configuration

payloadFilesProxy receives:

  • mediaCollectionSlug?: string
    • Slug used to find the upload collection in config.collections.
    • If omitted, not found, or not an upload collection, no proxy handler is added.
  • mediaDirectory: string (required by type)
    • Retained for compatibility; it does not determine where files are written.
    • Payload's runtime upload.staticDir is used, falling back to the collection slug.
  • originUrl: string
    • HTTP(S) origin used with the requested Payload file URL pathname. The origin's path, query, and fragment are ignored.
  • disabled?: boolean
    • If true, plugin is a no-op and config is returned unchanged.

Runtime Behavior

The plugin appends a file handler without replacing existing handlers. Payload checks read access before calling it. Document reads do not download files: on a file request, the handler checks the runtime local upload directory and fetches only a missing requested file. Payload then serves the local file, including its normal range handling. Image variants are fetched individually when requested.

Downloads are limited to 50 MiB and 15 seconds, require HTTP 200, and reject redirects. Completed downloads are published without overwriting an existing file; concurrent requests in the same process share a download. Failed downloads return HTTP 502 and are not cached.

Important Limitations

  • Requests are anonymous; authenticated origins and redirects are not supported. The origin must serve the same Payload file pathname.
  • Configure only a trusted origin: the server makes outbound requests to it. Do not expose this development proxy in production. Downloaded content is trusted and is not scanned or validated as an image.
  • Payload's read access controls apply, but boolean public read access can permit requests for filenames without a matching database document. Restrict access and the origin accordingly.
  • Local storage must be enabled. The destination is created if necessary and must be writable; storage adapters or handlers that return a response before this handler take precedence.
  • Deduplication is process-local. Existing local files are never refreshed, and the 50 MiB limit is buffered in memory.

Development vs Production

  • Local/dev: enable plugin to auto-pull missing files on demand.
  • Production: disable plugin (disabled: true or NODE_ENV guard).

Troubleshooting

  • Files are not downloaded:
    • confirm mediaCollectionSlug matches your upload collection and read access permits the request
    • confirm the requested pathname is reachable on originUrl without redirects or authentication
    • confirm Payload's local upload directory is writable and local storage is enabled
    • check server logs for origin failures, the size limit, or timeout

Development and tests

The dev/ directory contains the Payload development application. Development requires pnpm 11 (the project pins pnpm 11.25.0). Dependency install scripts are allowed only for sharp. Integration tests use Vitest, an isolated temporary SQLite database, and a local HTTP origin; they do not need production services.

pnpm install
DATABASE_URI=file:./dev/local.db PAYLOAD_CONFIG_PATH=./dev/payload.config.ts pnpm dev

Open http://localhost:3000/admin. The SQLite URI selects a local database; choose a different file if you want an isolated database. PAYLOAD_CONFIG_PATH points Next.js to the development Payload configuration. To regenerate the admin import map after changing components, run:

DATABASE_URI=file:./dev/local.db PAYLOAD_CONFIG_PATH=./dev/payload.config.ts pnpm dev:generate-importmap

The development configuration uses an external origin (https://inet2you.itfumh.es); missing files can only be fetched if that origin is reachable and serves the requested paths. Startup and tests do not require production services.

pnpm test
pnpm test:watch

Contributing

PRs are welcome. If behavior changes, document migration notes clearly in the README.

License

MIT

Acknowledgements

Inspired by Drupal's stage_file_proxy module and similar on-demand media proxy patterns.