Developing
The same packages work on three runtimes. Packages are public on npm, so start with install, pick the section that matches your project, ship.
1 · Install
pnpm add @mihcm/ui @mihcm/theme @mihcm/tokens @mihcm/iconsNo GitHub PAT, NODE_AUTH_TOKEN, or project .npmrc is required for MiHCM package installs. If a consumer project already has this legacy override, remove it before installing:
@mihcm:registry=https://npm.pkg.github.com
@yashiel:registry=https://npm.pkg.github.comFurther packages are optional and depend on your target:
| Package | When to add |
|---|---|
@mihcm/ai-ui | You want to render model-produced UI descriptors. |
@mihcm/cli | You want the mihcm add copy-paste workflow (see Install vs. copy-paste). |
@mihcm/mcp | You are building agent workflows around this design system and want live component search, descriptor validation, token lookup, and contract checks. See Agent tooling. |
Component expandability
Before adding local UI or widening a MiHCM primitive, check the Component Expandability Roadmap.
It classifies work into prop expansion, slot expansion, recipe expansion, MCP metadata, or no API change. Use it to decide whether a need belongs in component source, docs examples, Storybook, MCP recipes, or consumer composition.
2 · Wire it up
Pick the section that matches your bundler.
Next.js (App Router)
// next.config.ts — no extra config needed; Tailwind 4 via PostCSS// postcss.config.mjs
export default {
plugins: { '@tailwindcss/postcss': {} },
};/* app/globals.css — single import; theme inlines tokens for you */
@import "@mihcm/theme/globals.css";// app/layout.tsx
import './globals.css';
import type { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body className="bg-background text-foreground">{children}</body>
</html>
);
}// app/page.tsx
import { Button } from '@mihcm/ui/Button';
export default function Home() {
return <Button>Hello</Button>;
}postcss override. Next.js currently pins a postcss version with a known XSS advisory. Add the following to your root
package.json:{ "pnpm": { "overrides": { "postcss": "^8.5.14" } } }Background: ADR-014.
React + Vite
pnpm add -D tailwindcss@^4 @tailwindcss/vite@^4// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
});/* src/index.css */
@import "@mihcm/theme/globals.css";// src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { Button } from '@mihcm/ui/Button';
import './index.css';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<Button>Hello</Button>
</StrictMode>,
);React Native (Expo)
NativeWind v4 is required. NativeWind v5 is still pre-release upstream; the native runtime renders correctly but doesn't fully consume Tailwind 4 tokens yet — see ADR-013. For pure-web targets this caveat doesn't apply.
pnpm add nativewind react-native-reanimated react-native-safe-area-context
pnpm add -D tailwindcss@^4// tailwind.config.js
const preset = require('@mihcm/theme/tailwind.preset').default;
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [preset],
content: [
'./app/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
'./node_modules/@mihcm/ui/**/*.{js,mjs}',
],
};/* global.css — referenced by Metro */
@import "@mihcm/theme/globals.css";// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');
const config = getDefaultConfig(__dirname);
module.exports = withNativeWind(config, { input: './global.css' });// app/_layout.tsx
import { ThemeProvider } from '@mihcm/theme';
import { Button } from '@mihcm/ui/Button';
import './global.css';
export default function Layout() {
return (
<ThemeProvider scheme="light">
<Button>Hello</Button>
</ThemeProvider>
);
}3 · Verify
After install + setup:
pnpm exec tsc --noEmit # 0 errors expected
pnpm audit --audit-level=high # 0 high/critical advisories expectedA minimal verification screen:
import { Button } from '@mihcm/ui/Button';
import { Text } from '@mihcm/ui/Text';
export function ExampleScreen() {
return (
<div className="flex flex-col gap-3 max-w-sm">
<Text size="2xl" weight="semibold">It works</Text>
<Button variant="default" onClick={() => alert('clicked')}>
Click me
</Button>
</div>
);
}If the button shows the brand-blue background and white text, your tokens are loaded correctly. If not, jump to the troubleshooting table below.
5 · Subpath imports
Always import per-component for clean tree-shaking:
// ✅ tree-shakes; bundler pulls only Button + its transitive imports
import { Button } from '@mihcm/ui/Button';
// ❌ pulls the barrel; ships every primitive in your bundle
import { Button } from '@mihcm/ui';Each primitive has a top-level export condition that routes web bundlers to .tsx and React Native bundlers to .native.tsx automatically. You don't pick the variant — the bundler does.
6 · Client and Server Components
In Next.js App Router, @mihcm/ui component entrypoints are client
boundaries that can still be rendered from Server Components when props are
static and serializable.
Use Server Components for data loading and layout. Create a small client wrapper
when you need useState, event handlers, browser APIs, routing hooks,
controlled inputs, charts, tables, or complex menus with icon maps.
Read the full guide: Client and Server Components.
7 · Enforce MiHCM-only UI
For projects that must use only this design system, combine MCP review with local CI gates:
- register the hosted MCP endpoint;
- block non-MiHCM UI imports with ESLint;
- run
mihcm-design-system-checkin CI; - protect
mainso checks must pass before merge.
Read the full guide: MiHCM-only Next.js enforcement.
Common pitfalls
| Symptom | Cause | Fix |
|---|---|---|
401 or 403 from npm.pkg.github.com | Stale .npmrc routes MiHCM packages to GitHub Packages | Remove @mihcm:registry=https://npm.pkg.github.com and legacy @yashiel:registry=https://npm.pkg.github.com overrides from project and user npm config. |
Can't resolve '@mihcm/tokens/tokens.css' | Importing tokens directly | Import only @mihcm/theme/globals.css — it inlines tokens |
pnpm audit flags postcss | Next.js pins it transitively | Add pnpm.overrides.postcss = "^8.5.14" to root package.json (ADR-014) |
Native: bg-primary classes don't apply | NativeWind v4's Tailwind-3 utilities don't fully consume Tailwind 4 tokens | Tracked; bumps to v5 once stable. Use the useTheme() hook for token values in the interim |
| Bundle includes every primitive | Barrel import | Use from '@mihcm/ui/Button' per-component |
Event handlers cannot be passed to Client Component props | A Server Component passed onClick, render functions, icons, or table/chart callbacks into a client boundary | Move that component tree into a 'use client' wrapper and pass only serializable data |
What's next
- Browse every primitive: Components
- Pick install vs. copy-paste per primitive: runbook
- Render UI from a language model: AI-UI
- Wire repo-aware agents: Agent tooling