Getting Started
From install to interactive showcase in under 2 minutes.
Prerequisites
- React 18+
- TypeScript 5+
- Node.js 18+ or Bun
Install
bash
bun add jcPeer dependencies: react and react-dom (18+).
Extract
bash
bunx jc extractScans your component files (default: src/components/ui/**/*.tsx), parses TypeScript prop interfaces via react-docgen-typescript, and writes two files:
| File | Contents |
|---|---|
| meta.json | Component names, prop types, defaults, descriptions, enum values, @example presets |
| registry.ts | Lazy import() map keyed by component display name |
Create your page
tsx
// src/app/showcase/page.tsx
'use client'
import type { JcMeta } from 'jc'
import { ShowcaseApp } from 'jc'
import meta from '@/jc/generated/meta.json'
import { registry } from '@/jc/generated/registry'
export default function ShowcasePage() {
return (
<ShowcaseApp
meta={meta as unknown as JcMeta}
registry={registry}
/>
)
}Why 'use client'?
ShowcaseApp uses React hooks, localStorage, and history.replaceState. It must render in a client context.
Or use the Next.js adapter for zero boilerplate:
tsx
// src/app/showcase/page.tsx
import { createShowcasePage } from 'jc/next'
import meta from '@/jc/generated/meta.json'
import { registry } from '@/jc/generated/registry'
export default createShowcasePage({ meta, registry })Add fixtures
Props typed as React components (like icon?: LucideIcon) need concrete values. Fixture plugins provide them with visual pickers.
tsx
import { defineFixtures } from 'jc'
import { Star, Heart, Zap, Download, Trash2 } from 'lucide-react'
import { createElement } from 'react'
function icon(Comp: typeof Star, size = 20) {
return {
render: () => createElement(Comp, { size }),
renderPreview: () => createElement(Comp, { size: 14 }),
component: Comp,
}
}
export const lucideFixtures = defineFixtures({
name: 'lucide',
fixtures: [
{ key: 'star', label: 'Star', category: 'icons', ...icon(Star) },
{ key: 'heart', label: 'Heart', category: 'icons', ...icon(Heart) },
{ key: 'zap', label: 'Zap', category: 'icons', ...icon(Zap) },
{ key: 'download', label: 'Download', category: 'icons', ...icon(Download) },
{ key: 'trash', label: 'Trash', category: 'icons', ...icon(Trash2) },
],
})Pass fixtures to ShowcaseApp:
tsx
<ShowcaseApp
meta={meta as unknown as JcMeta}
registry={registry}
fixtures={[lucideFixtures]}
/>Watch mode
bash
bunx jc extract --watchWatches your component files and re-extracts on save with 200ms debounce. Run alongside your dev server for instant feedback when you add or change props.
What the showcase gives you
| Area | Description |
|---|---|
| Sidebar | Searchable component list grouped by directory |
| Preview | Live component render with checkered background |
| Controls | Auto-generated prop editor — text, number, boolean, select, component picker |
| Code output | Copy-pasteable JSX that updates as you change props |
| Header | Theme toggle (auto/light/dark) and viewport picker (full/375/768/1280px) |