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

@pelicanplatform/components

v1.6.4

Published

Pelican Client Components

Readme

@pelicanplatform/components

Ready-made React + MUI components for browsing, uploading, and downloading objects from a Pelican Platform federation. These components are the UI layer on top of @pelicanplatform/web-client (the core client) and @pelicanplatform/hooks (the React state layer).

Installation

npm i @pelicanplatform/components @mui/material @emotion/react @emotion/styled

MUI and Emotion are peer dependencies — your app must provide them (and an MUI ThemeProvider). React 17, 18, or 19 is supported.

What's exported

The package's public surface is intentionally small:

| Export | Type | Description | | --- | --- | --- | | AuthenticatedClient | component | A complete, self-contained file browser: object list, breadcrumbs, upload, collection navigation, login, error toasts, and an embedded DownloadManager. Takes no props — it reads everything from the Pelican client context. | | DownloadManager | component | A floating, minimizable panel showing active and interrupted downloads with progress, ETA, cancel, and "resume all". Already embedded inside AuthenticatedClient; render it yourself only when building a custom UI. Takes no props. | | everything from @pelicanplatform/hooks | — | Re-exported for convenience, most importantly PelicanClientProvider and usePelicanClient. |

Because both components consume React context, they must be rendered inside a PelicanClientProvider.

Quick start

Three pieces are required: a theme, the provider, and the component.

// app/page.tsx
"use client";

import { ThemeProvider, createTheme, CssBaseline } from "@mui/material";
import { PelicanClientProvider, AuthenticatedClient } from "@pelicanplatform/components";

const theme = createTheme();

export default function Page() {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <PelicanClientProvider
        initialObjectUrl="pelican://osg-htc.org/ncar"
        enableAuth={true}
      >
        <AuthenticatedClient />
      </PelicanClientProvider>
    </ThemeProvider>
  );
}

That single AuthenticatedClient gives you a working browser for the namespace at initialObjectUrl: listing objects, navigating into collections/folders, downloading files, and (when enableAuth is on and the user logs in) uploading and creating collections.

PelicanClientProvider props

| Prop | Default | Description | | --- | --- | --- | | initialObjectUrl | "" | The pelican://<federation>/<path> URL to load on mount. | | enableAuth | true | Enables login, upload, and collection-creation UI. Set to false for a read-only, public browser. | | children | — | Your component tree. |

The provider handles federation discovery, namespace resolution, token storage (in sessionStorage), the OAuth authorization-code flow, object-list caching, and download progress tracking. Components below it stay stateless.

Enabling downloads (service worker)

Downloads stream through a service worker so large files don't have to be buffered in memory, and so transfers can resume after an interruption. The DownloadManager (and the one embedded in AuthenticatedClient) only reports progress once that worker is registered.

  1. Make the worker file available at a public URL. The script ships in @pelicanplatform/web-client; copy it into your static assets at build time:

    // package.json
    "scripts": {
      "predev": "cp node_modules/@pelicanplatform/web-client/dist/serviceWorker/downloadServiceWorker.js public/downloadServiceWorker.js"
    }
  2. Register it on the client once, early in your app:

    "use client";
    import { useEffect } from "react";
    import { registerPelicanSw } from "@pelicanplatform/web-client";
    
    export default function PelicanSwRegistrar() {
      useEffect(() => {
        registerPelicanSw("/downloadServiceWorker.js");
      }, []);
      return null;
    }

The service worker is a crucial part of the security infrastructure and therefore is not optional. It holds the access and refresh token in memory inaccessible to the rest of the application prevent token exfiltration in the case of XSS in your web application.

Building a custom UI with usePelicanClient

If AuthenticatedClient doesn't fit your design, drive the client directly with the usePelicanClient hook (re-exported here) and compose your own components — optionally dropping in DownloadManager for the download panel.

"use client";

import { usePelicanClient, DownloadManager } from "@pelicanplatform/components";
import { useEffect, useState } from "react";
import type { ObjectList } from "@pelicanplatform/web-client";

function Browser() {
  const {
    objectUrl,
    setObjectUrl,
    getObjectList,
    handleDownload,
    handleLogin,
    authorized,
    loading,
  } = usePelicanClient();

  const [objects, setObjects] = useState<ObjectList[]>([]);
  useEffect(() => {
    getObjectList(objectUrl).then(setObjects);
  }, [objectUrl, getObjectList]);

  if (loading) return <p>Loading…</p>;

  return (
    <>
      {!authorized && <button onClick={handleLogin}>Login</button>}
      <ul>
        {objects.map((o) => (
          <li key={o.href}>
            {o.iscollection ? (
              <button onClick={() => setObjectUrl(`pelican://osg-htc.org${o.href}`)}>
                {o.href}/
              </button>
            ) : (
              <button onClick={() => handleDownload(`pelican://osg-htc.org${o.href}`)}>
                {o.href}
              </button>
            )}
          </li>
        ))}
      </ul>
      <DownloadManager />
    </>
  );
}

The context exposes everything the built-in components use, including:

  • objectUrl / setObjectUrl — the currently viewed pelican:// URL.
  • getObjectList(url?, forceRefresh?) — list objects (TTL-cached); returns ObjectList[].
  • handleDownload(url) / handleUpload(file, url?) — stream a download / upload a File.
  • handleLogin() — start the OAuth authorization-code flow for the current namespace.
  • authorized, authorizationRequired, loading, error, setError.
  • federation, namespace, collections — resolved metadata for the current URL.
  • downloadsInProgress — live map of download progress (what DownloadManager renders).

Notes

  • All components are marked "use client"; in Next.js App Router, render them in client components / below a client boundary. The PelicanClientProvider is typically placed in your root layout.tsx.
  • A full working example — provider in the layout, AuthenticatedClient on the page, service-worker registration, and a namespace selector — lives in website/ at the repo root.

License

Apache-2.0.