Skip to content
MEDAApache-2.0 · TypeScript-first

The UI shell Medal is built with.

Meda is the shared UI shell and runtime primitives behind Medal’s apps — navigation chrome, panels, auth controls, recipes, theme bridges, a command palette and the workbench layout. Published as @medalsocial/meda.

$pnpm add @medalsocial/meda View on GitHub npm
Quickstart

Install, theme, render the shell.

bashInstall
pnpm add @medalsocial/meda lucide-react @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities @xyflow/react

Peer dependencies

Meda expects react 19 or newer and react-dom 19 or newer, plus the required peers lucide-react, @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities and @xyflow/react in your project (next-themes, react-markdown and @react-three/fiber are optional). It ships a styles.css with its design tokens; import it once from your entry stylesheet and put your own token overrides after it, so equal-specificity declarations win by source order.
cssTailwind CSS v4 setup
@import 'tailwindcss'; @import '@medalsocial/meda/styles.css'; :root { /* Overrides go after the Meda import so they win by source order. */ --color-brand-500: oklch(0.62 0.18 245); }
tsxRender the shell
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> ); }

The same shell we ship

Meda powers Medal’s own apps, so the navigation rails, command palette and workbench layout you get are the ones we run in production — not a demo kit.
meda on GitHub @medalsocial/meda on npm NextMedal site engine