MiHCM

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/icons

No 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.com

Further packages are optional and depend on your target:

PackageWhen to add
@mihcm/ai-uiYou want to render model-produced UI descriptors.
@mihcm/cliYou want the mihcm add copy-paste workflow (see Install vs. copy-paste).
@mihcm/mcpYou 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 expected

A 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-check in CI;
  • protect main so checks must pass before merge.

Read the full guide: MiHCM-only Next.js enforcement.

Common pitfalls

SymptomCauseFix
401 or 403 from npm.pkg.github.comStale .npmrc routes MiHCM packages to GitHub PackagesRemove @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 directlyImport only @mihcm/theme/globals.css — it inlines tokens
pnpm audit flags postcssNext.js pins it transitivelyAdd pnpm.overrides.postcss = "^8.5.14" to root package.json (ADR-014)
Native: bg-primary classes don't applyNativeWind v4's Tailwind-3 utilities don't fully consume Tailwind 4 tokensTracked; bumps to v5 once stable. Use the useTheme() hook for token values in the interim
Bundle includes every primitiveBarrel importUse from '@mihcm/ui/Button' per-component
Event handlers cannot be passed to Client Component propsA Server Component passed onClick, render functions, icons, or table/chart callbacks into a client boundaryMove that component tree into a 'use client' wrapper and pass only serializable data

What's next