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

@medalsocial/meda

v2.4.0

Published

Shared Meda UI shell and runtime package.

Readme

@medalsocial/meda

Shared UI shell and runtime primitives — the navigation chrome, panels, auth controls, recipes, theme bridges, command palette, and workbench layout that power Medal's apps. Published as Apache-2.0.

npm

Install

pnpm add @medalsocial/meda lucide-react

Peer deps: react >= 19, react-dom >= 19, and lucide-react.

Tailwind CSS v4 setup

Meda ships a styles.css with its design tokens. Import it once in your entry stylesheet or entry script:

@import 'tailwindcss';
@import '@medalsocial/meda/styles.css';

:root {
  /* Consumer overrides go after meda so equal-specificity tokens win by source order. */
  --color-brand-500: oklch(0.62 0.18 245);
  --auth-gradient-primary: var(--color-brand-500);
}

.dark {
  --color-brand-500: oklch(0.72 0.16 245);
}

Avoid placing token overrides before the Meda import; tokens.css defines the package defaults and later declarations are what override them:

/* Wrong: meda's imported defaults overwrite this block. */
:root {
  --color-brand-500: oklch(0.62 0.18 245);
}

@import '@medalsocial/meda/styles.css';

Usage

Use AppShell for the styled shell surface:

import { AppShell, MedaShellProvider } from '@medalsocial/meda/shell';
import { Inbox } from 'lucide-react';

export function App() {
  const workspace = { id: 'workspace', name: 'Workspace' };
  const apps = [{ id: 'inbox', label: 'Inbox', icon: Inbox }];

  return (
    <MedaShellProvider workspace={workspace} apps={apps}>
      <AppShell
        variant="workspace"
        iconRail={{
          mainItems: [{ id: 'inbox', label: 'Inbox', icon: Inbox, to: '/inbox' }],
        }}
      >
        {/* your app */}
      </AppShell>
    </MedaShellProvider>
  );
}

For framework routing, pass a render callback and forward Meda props:

import Link from 'next/link';

<AppShell
  variant="workspace"
  iconRail={{
    mainItems,
    renderLink: ({ item, linkProps }) => <Link {...linkProps} href={item.to} prefetch />,
  }}
  appTabs={{
    renderLink: ({ app, linkProps }) =>
      app.to ? <Link {...linkProps} href={app.to} prefetch /> : <a {...linkProps} />,
  }}
>
  {children}
</AppShell>;

Workspace shells also expose chrome-level composition slots:

<AppShell
  variant="workspace"
  headerCenter={<SectionTabs />}
  banners={<SystemHealthBanner />}
  mainLayout="fullbleed"
  mainClassName="marketing-main"
  workspace={{
    menuItems: [{ id: 'settings', label: 'Settings', href: '/settings' }],
    menuFooter: <AccountSwitcher />,
  }}
>
  {children}
</AppShell>

workspace.menuItems, workspace.menuFooter, and the theme toggle are available from the mobile Menu drawer. Use mainLayout/mainClassName when a workspace shell needs the same mobile chrome but a custom main scroll region, such as a full-bleed marketing page. useCommands() works from workspace descendants without manually mounting CommandPalette; lower-level primitive compositions can still mount CommandPalette directly.

ContextRail is usable for both navigation rails and custom rendered rails. Navigation rails show Meda's label header by default. Custom rendered rails hide the automatic visible header by default so consumers can render their own heading without duplication. Rail bodies scroll vertically by default; use contextRail={{ header: "visible" }} or contextRail={{ scroll: "none" }} when you need explicit control.

Foundation primitives

Meda includes small foundation primitives for repeated loading, empty, and filtering surfaces:

import { EmptyState, FilterRail, Skeleton } from '@medalsocial/meda';

Skeleton mirrors shadcn's simple loading placeholder shape. EmptyState standardizes zero/error states across panels and content areas. FilterRail provides a dense filter surface while leaving selected values, URL syncing, and query logic in the consuming app.

The same primitives are available from the shadcn-compatible registry when an app wants local source ownership:

npx shadcn add https://meda.medalsocial.com/r/meda-skeleton.json
npx shadcn add https://meda.medalsocial.com/r/meda-empty-state.json
npx shadcn add https://meda.medalsocial.com/r/meda-filter-rail.json

For app-scoped brand tokens:

import { createMedaThemeCss, defineMedaTheme } from '@medalsocial/meda/theme';

const css = createMedaThemeCss(
  defineMedaTheme({
    appId: 'auto',
    colors: {
      primary: 'var(--hb-brand-500)',
      background: 'var(--hb-base-50)',
    },
    dark: {
      colors: {
        background: 'var(--hb-base-900)',
      },
    },
  })
);

Lower-level ShellStateProvider and layout parts remain available from @medalsocial/meda/shell/primitives for apps that need to own more composition.

See the demo app for a live playground.

Exports

  • @medalsocial/meda — curated public API (components + helpers)
  • @medalsocial/meda/shell — styled shell components and hooks
  • @medalsocial/meda/shell/primitives — lower-level shell state and layout primitives
  • @medalsocial/meda/auth — provider-neutral auth controls
  • @medalsocial/meda/auth/better-auth — optional better-auth adapter
  • @medalsocial/meda/recipes/next — copyable Next.js adoption recipe metadata
  • @medalsocial/meda/theme — app-scoped token bridge helpers
  • @medalsocial/meda/marketing — marketing sections and campaign blocks
  • @medalsocial/meda/styles.css — design tokens + base styles

Alternative: shadcn registry

Prefer to copy source into your project instead of installing? The shadcn-compatible registry is served alongside the demo playground on Cloudflare Workers.

# Once DNS for meda.medalsocial.com is live:
npx shadcn add https://meda.medalsocial.com/r/meda-shell.json
npx shadcn add https://meda.medalsocial.com/r/meda-shell-state.json
npx shadcn add https://meda.medalsocial.com/r/meda-workbench-layout.json
npx shadcn add https://meda.medalsocial.com/r/meda-next-app-shell.json

The registry index is at https://meda.medalsocial.com/registry.json. Source JSON files live under ./registry in this repo and are deployed as static assets via Cloudflare Workers — see wrangler.toml and .github/workflows/deploy-worker.yml.

Development

pnpm install
pnpm build             # compile dist/
pnpm test              # vitest (jsdom)
pnpm typecheck
pnpm lint
pnpm registry:validate
pnpm demo:dev          # run the playground locally
pnpm storybook         # http://localhost:6006
pnpm storybook:build   # storybook-static/
pnpm size-limit        # bundle-size gate

Storybook + Chromatic

Stories are colocated as Component.stories.tsx next to each primitive. Build the static bundle with:

pnpm storybook:build

Visual review runs via Chromatic. The Chromatic GitHub workflow publishes Storybook on pushes and pull requests targeting dev or prod, using the repository secret CHROMATIC_PROJECT_TOKEN.

pnpm chromatic

Chromatic handles UI diffs and review state, so visual snapshot baselines are not committed to this repository.

Release

Changesets + GitHub Actions (OIDC trusted publishing). Add a changeset with pnpm changeset, merge to the release branch, and the Release workflow handles npm publish with provenance.

License

Apache-2.0. See LICENSE and NOTICE.