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

@knaw-huc/panoptes-react

v0.0.1

Published

Panoptes React is a React-based dataset search/browse tool backed by Panoptes. It is both a reusable React library (ES module) that you can embed in your own React app and a standalone application if no further customization is needed.

Readme

Panoptes React

Panoptes React is a React-based dataset search/browse tool backed by Panoptes. It is both a reusable React library (ES module) that you can embed in your own React app and a standalone application if no further customization is needed.

The library exposes helpers to bootstrap a Panoptes-enabled React application and requires TanStack Query for data fetching and caching and TanStack Router for client-side routing.

Install the library using: npm install @knaw-huc/panoptes-react
Build the library using: npm run build
Build the application using: npm run build:app
Run for development: npm run dev

How to run the application

The application uses the following Vite env vars (prefix VITE_). You can set them in a .env, .env.local, or via the shell when running Vite. You can also set them when running the app as a Docker container.

  • VITE_PANOPTES_URL — Base URL of the Panoptes backend
  • VITE_PANOPTES_IS_EMBEDDEDtrue to run in embedded mode, else false for rendering a menu bar at the top of the page
  • VITE_PANOPTES_SEARCH_PATH — Route for search page; it must include the dataset parameter $dataset unless the dataset is configured globally via VITE_PANOPTES_DATASET
  • VITE_PANOPTES_DETAIL_PATH — Route for detail page; it must include the dataset parameter $dataset unless the dataset is configured globally via VITE_PANOPTES_DATASET, and it must include the id parameter $id
  • VITE_PANOPTES_DATASET — Optional dataset identifier to use globally for all routes

Mock behavior

If VITE_PANOPTES_URL resolves to https://example.org, the application will start a mock API using MSW (see src/serverMock.ts) so you can try the UI without a real backend. The MSW service worker is emitted into public/ (configured via the msw field in package.json).

How to use this library

Setup

To use this library, you will have to set up TanStack Query and wrap the application tree with the Panoptes context. This context contains the configuration for the application:

| Parameter | Value type | Required? | Default value | Description | |-------------------|-------------------------------------|-----------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| | url | string | ✓ | | Base URL of the Panoptes backend | | isEmbedded | boolean | | false | true to run in embedded mode, else false for rendering a menu bar at the top of the page | | searchPath | string | ✓ | | Route for search page; it must include the dataset parameter $dataset unless the dataset is configured globally | | detailPath | string | ✓ | | Route for detail page; it must include the dataset parameter $dataset unless the dataset is configured globally, and it must include the id parameter $id | | dataset | string | | | Optional dataset identifier to use globally for all routes | | searchComponent | RouteComponent | | | Replace the default Search component with a custom React component | | detailComponent | RouteComponent | | | Replace the default Detail component with a custom React component | | blocks | Map<string, FC<{ block: Block }>> | | | Add additional Blocks to Panoptes for customized rendering using the Block type as key, see Blocks |

You can use the createPanoptesRoot helper as an alternative for createRoot (see React docs) to create a root element for your application tree. It behaves just like createRoot but will set up TanStack Query and the Panoptes context provider for you in Strict Mode.

In addition to TanStack Query, the library also requires TanStack Router for client-side routing. You can set up the RouterProvider yourself or use the PanoptesRouterProvider component provided by this library. The PanoptesRouterProvider will configure the application routes based on the configuration provided in the Panoptes context.

Example setup:

import {createPanoptesRoot, PanoptesRouterProvider, Block} from '@knaw-huc/panoptes-react';

interface HelloBlock extends Block {
    type: 'hello';
    value: string;
}

function HelloBlockComponent({block}: { block: HelloBlock }) {
    return <p>Hello {block.value}!</p>;
}

const root = createPanoptesRoot(document.getElementById('root')!, {
    url: 'https://your-panoptes.example.org',
    isEmbedded: false,
    searchPath: '/search',
    detailPath: '/detail/$id',
    dataset: 'your-dataset-id',
    blocks: new Map([['hello', HelloBlockComponent]]),
});

root.render(<PanoptesRouterProvider/>);

Customization

The library exposes a set of hooks to use Panoptes in your own React components. Both the default Search and Detail components can be replaced with custom components (using these hooks) by providing custom components to the searchComponent and detailComponent parameters of the Panoptes context. That is one way of customizing the UI. The other way is by providing custom blocks for Panoptes to render.

Hooks

const conf = usePanoptes()

Returns the configuration object from Panoptes. See Setup for the available parameters.

const [dataset, id] = useDataset(source: 'search' | 'detail')

Returns the dataset and the identifier for the current route.

const {searchFn, facets, pageSize} = useSearch(dataset: string)

Handles search functionality for the given dataset. Returns a searchFn function that can be used to fetch results, a facets object with the applied facets for the dataset. The pageSize parameter is the page size for the search results.`

const facets = useFacets()

Returns the configured facets for the current dataset.

const {items} = useFacet(name: string)

Returns the facet items for the given facet.

const details = useDetails()

Returns the details for the current item.

Blocks

Blocks are plugin-like React components that can be used to customize the rendering of both search result card and the detail view. Through Panoptes, you can configure the list of blocks to be rendered for each dataset for both the search result cards as for the detail view. Panoptes come prepared with some default blocks, but you can also provide your own blocks (see Setup).

Panoptes provides the following blocks out of the box:

  • list: Renders a list of items, this may include deep hierarchies
  • cmdi: Renders a CMDI record
  • (TODO) More to come

If you want to provide your own custom blocks, you will have to know the Block interface which is defined as follows:

type BlockValue = string | object | Block[];

interface Block {
    type: string;
    value: BlockValue;
    config?: object;
}

A block consists of a type, a value and sometimes config. The type determines the rendering of the block. The value and the config are passed to the block component as properties. A simple block component could look like this:

interface HelloWorldBlock extends Block {
    type: 'hello_world';
    value: { hello?: string };
}

function RenderHelloWorld({block}: { block: HelloWorldBlock }) {
    return (
        <h1>Hello {block.value.hello || 'World'}</h1>
    );
}