āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/crafter-station/elements/final_registry_summary ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
registry/default/blocks/clerk/clerk-sign-in/registry/default/blocks/clerk-sign-in/satisfies Registry pattern__registry__/index.tsx like Supabasepublic/r/registry.json - 64 public componentspublic/r/[name].json - Individual component files (all 64)__registry__/index.tsx - Preview loader (ready for examples)elements/
āāā registry/
ā āāā index.ts # Main export (satisfies Registry)
ā āāā blocks.ts # All 64 component imports
ā āāā examples.ts # Demo components (placeholder)
ā āāā utils.ts # registryItemAppend helper
ā āāā default/
ā āāā blocks/ # ā
FLAT - 64 components
ā ā āāā clerk-sign-in-shadcn/
ā ā āāā tinte-editor/
ā ā āāā apple-logo/
ā ā āāā ... (61 more)
ā āāā examples/ # (to be created)
ā āāā clerk-sign-in-demo.tsx
ā
āāā __registry__/
ā āāā index.tsx # Auto-generated preview loader
ā
āāā public/r/
ā āāā registry.json # Main registry (64 items)
ā āāā *.json # 64 individual component files
ā
āāā scripts/
āāā build-registry.ts # ā
Supabase pattern
āāā flatten-registry-structure.ts
āāā generate-blocks-ts.ts
āāā ... (migration tools)
| Aspect | Before | After (Supabase Pattern) |
|--------|---------|-------------------------|
| Block Organization | blocks/clerk/component/ | blocks/component/ (flat) |
| Registry Index | Auto-generated JSON | TypeScript with imports |
| Organizer Files | None | blocks.ts, examples.ts |
| Example System | None | registry/index.tsx |
| Build Process | Custom merge script | Import + filter pattern |
| Type Safety | Loose | satisfies Registry |
// registry/index.ts
import { blocks } from './blocks'
import { examples } from './examples'
export const registry = {
name: 'elements',
homepage: 'https://tryelements.dev',
items: [
...blocks, // 64 components
...examples, // Internal use only
],
} satisfies Registry // Type-safe!
// registry/blocks.ts (auto-generated)
import clerk_sign_in_shadcn from './default/blocks/clerk-sign-in-shadcn/registry-item.json' with { type: 'json' }
import tinte_editor from './default/blocks/tinte-editor/registry-item.json' with { type: 'json' }
// ... 62 more
export const blocks = [
clerk_sign_in_shadcn as RegistryItem,
tinte_editor as RegistryItem,
// ... 62 more
] as RegistryItem[]
bun run build:registry
Steps:
registry/index.tspublic/r/registry.json__registry__/index.tsx for previewsshadcn build to create individual JSONs# 1. Create component
mkdir registry/default/blocks/my-component
cd registry/default/blocks/my-component
# 2. Add files
touch registry-item.json
mkdir components && touch components/my-component.tsx
# 3. Regenerate blocks.ts
bun scripts/generate-blocks-ts.ts
# 4. Build
bun run build:registry
// registry/blocks.ts
import myComponent from './default/blocks/my-component/registry-item.json'
import { clients } from './clients'
// Create variants: my-component-nextjs, my-component-react, etc.
const combine = (component: RegistryItem) => {
return clients.flatMap((client) => {
return registryItemAppend(
{ ...component, name: `${component.name}-${client.name}` },
[client]
)
})
}
export const blocks = [
...combine(myComponent),
]
// registry/default/examples/clerk-sign-in-demo.tsx
'use client'
import { ClerkSignInShadcn } from '@/registry/default/blocks/clerk-sign-in-shadcn/components/sign-in'
export default function ClerkSignInDemo() {
return (
<div className="max-w-md">
<ClerkSignInShadcn />
</div>
)
}
// registry/examples.ts
export const examples: RegistryItem[] = [
{
name: 'clerk-sign-in-demo',
type: 'registry:example',
registryDependencies: [],
files: [
{
path: 'registry/default/examples/clerk-sign-in-demo.tsx',
type: 'registry:example',
},
],
},
]
// In your docs
import { ComponentPreview } from '@/components/component-preview'
<ComponentPreview name="clerk-sign-in-demo" />
The __registry__/index.tsx will lazy-load it!
| Script | Purpose |
|--------|---------|
| bun run build:registry | Complete registry build |
| bun scripts/generate-blocks-ts.ts | Regenerate blocks.ts |
| bun scripts/flatten-registry-structure.ts | Flatten nested structure |
| bun scripts/migrate-to-shadcn-structure.ts | Original migration tool |
| Feature | Supabase UI Library | Elements (Now) |
|---------|-------------------|----------------|
| Flat blocks structure | ā
| ā
|
| Organizer files (blocks.ts) | ā
| ā
|
| examples.ts | ā
| ā
(placeholder) |
| registry/index.tsx | ā
| ā
|
| Type-safe registry | ā
(satisfies Registry) | ā
|
| JSON imports with with { type: 'json' } | ā
| ā
|
| Component multi-framework support | ā
| š (ready to add) |
| Example filtering in build | ā
| ā
|
combine() functionCreate demo components for documentation:
mkdir registry/default/examples
# Add .tsx files for each component you want to preview
# Update registry/examples.ts
If you need Next.js vs React variants:
mkdir registry/default/clients
# Add framework-specific clients
# Use combine() in blocks.ts
Shared types, database schemas:
mkdir registry/default/fixtures
# Add shared types, schemas
Platform-specific components:
// registry/platform.ts
export const platform = [...] as RegistryItem[]
# Start dev server
bun dev
# In another terminal
npx shadcn add http://localhost:3000/r/clerk-sign-in-shadcn.json
npx shadcn add https://tryelements.dev/r/clerk-sign-in-shadcn.json
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "elements",
"homepage": "https://tryelements.dev",
"items": [ /* 64 components */ ]
}
Individual component files with full source code.
export const Index = {
"default": {
"clerk-sign-in-demo": {
component: React.lazy(() => import("@/registry/default/examples/clerk-sign-in-demo.tsx")),
},
},
} as const
satisfies RegistrySUPABASE_REGISTRY_ANALYSIS.md - Deep analysis of Supabase patternREGISTRY_MIGRATION_SUMMARY.md - Original migration detailsREGISTRY_QUICK_START.md - Quick reference guideFINAL_REGISTRY_SUMMARY.md - This documentš Your Elements registry now follows the official Supabase UI Library pattern!
You have:
The registry is now organized exactly like Supabase's production system, used by thousands of developers. You can confidently deploy and scale this!
Happy building! š
For questions or enhancements, refer to:
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā