or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

examples

edge-cases.mdreal-world-scenarios.md
index.md
tile.json

registry-api.mddocs/reference/

Registry API

Programmatic API for fetching and resolving components from registries. The Registry API provides functions for retrieving components, resolving dependencies, searching across registries, and managing registry configurations.

Capabilities

getRegistryItems

Fetches registry items by name. Retrieves one or more items from configured registries without resolving dependencies.

/**
 * Fetch registry items by name
 * @param items - Array of item names (e.g., ['@shadcn/button', '@acme/card'])
 * @param options - Optional configuration and caching options
 * @returns Promise resolving to array of registry items
 * @throws RegistryNotFoundError if item not found
 * @throws RegistryNotConfiguredError if registry not configured
 * @throws RegistryFetchError on network errors
 */
function getRegistryItems(
  items: string[],
  options?: {
    config?: Partial<Config>
    useCache?: boolean
  }
): Promise<RegistryItem[]>

Parameters:

  • items: string[] - Array of registry item names with namespace prefix (e.g., ['@shadcn/button']). Required, must not be empty.
  • options.config?: Partial<Config> - Optional configuration override. Merges with existing config from components.json.
  • options.useCache?: boolean - Whether to use HTTP cache (default: false). When true, uses cached responses when available.

Returns: Promise<RegistryItem[]> - Array of fetched registry items in the same order as input.

Throws:

  • RegistryNotFoundError - If item or registry not found
  • RegistryNotConfiguredError - If registry not configured in components.json
  • RegistryFetchError - On network or fetch errors
  • ConfigMissingError - If components.json not found

Usage Example:

import { getRegistryItems } from 'shadcn';

// Fetch single item
const [button] = await getRegistryItems(['@shadcn/button']);

// Fetch multiple items
const items = await getRegistryItems([
  '@shadcn/button',
  '@shadcn/card',
  '@acme/special-input'
]);

// With custom config
const items = await getRegistryItems(['@shadcn/button'], {
  config: {
    registries: {
      '@acme': 'https://custom.registry.com/{name}.json'
    }
  }
});

// With caching enabled
const items = await getRegistryItems(['@shadcn/button'], {
  useCache: true
});

// Access item properties
console.log(items[0].name);        // 'button'
console.log(items[0].type);        // 'registry:ui'
console.log(items[0].files);       // Array of file objects
console.log(items[0].dependencies); // Array of npm packages

Error Handling:

import { getRegistryItems } from 'shadcn';
import { RegistryNotFoundError, RegistryNotConfiguredError } from 'shadcn/registry';

try {
  const items = await getRegistryItems(['@custom/button']);
} catch (error) {
  if (error instanceof RegistryNotFoundError) {
    // Item or registry not found
    console.error('Not found:', error.message);
    if (error.suggestion) {
      console.log('Suggestion:', error.suggestion);
    }
  } else if (error instanceof RegistryNotConfiguredError) {
    // Registry not in components.json
    console.error('Registry not configured:', error.context?.registry);
  } else {
    throw error;
  }
}

resolveRegistryItems

Resolves registry items with all dependencies. Fetches items and recursively resolves all registry dependencies, returning a complete dependency tree.

/**
 * Resolve registry items with all dependencies
 * @param items - Array of item names to resolve
 * @param options - Optional configuration and caching options
 * @returns Promise resolving to items tree with dependencies
 * @throws RegistryNotFoundError if item or dependency not found
 * @throws RegistryNotConfiguredError if registry not configured
 */
function resolveRegistryItems(
  items: string[],
  options?: {
    config?: Partial<Config>
    useCache?: boolean
  }
): Promise<RegistryResolvedItemsTree>

Parameters:

  • items: string[] - Array of registry item names. Required, must not be empty.
  • options.config?: Partial<Config> - Optional configuration override.
  • options.useCache?: boolean - Whether to use HTTP cache (default: false).

Returns: Promise<RegistryResolvedItemsTree> - Resolved items tree with all dependencies, including:

  • dependencies?: string[] - Flattened npm dependencies
  • devDependencies?: string[] - Flattened npm dev dependencies
  • files?: RegistryItemFile[] - All files from items and dependencies
  • tailwind?: RegistryItemTailwind - Merged Tailwind configuration
  • cssVars?: RegistryItemCssVars - Merged CSS variables
  • css?: RegistryItemCss - Merged CSS content
  • envVars?: Record<string, string> - Merged environment variables
  • docs?: string - Documentation
  • fonts?: RegistryFontItem[] - Font items

Throws:

  • RegistryNotFoundError - If item or dependency not found
  • RegistryNotConfiguredError - If registry not configured
  • ConfigMissingError - If components.json not found

Usage Example:

import { resolveRegistryItems } from 'shadcn';

// Resolve item with dependencies
const resolved = await resolveRegistryItems(['@shadcn/button']);

// Resolved tree includes the item and all its dependencies
console.log(resolved.items);        // Array of all items including deps
console.log(resolved.dependencies); // Flattened npm dependencies

// Example: button might depend on utils, which is automatically included
const result = await resolveRegistryItems(['@shadcn/dialog']);
// Result includes: dialog, button (dep), utils (transitive dep)

Dependency Resolution:

  • Recursively resolves registryDependencies from each item
  • Deduplicates dependencies (same item only included once)
  • Flattens npm dependencies and devDependencies
  • Merges configuration (Tailwind, CSS, env vars)

Circular Dependency Handling:

  • Detects circular dependencies and throws error
  • Prevents infinite loops in dependency resolution

getRegistry

Gets a registry by name or URL. Fetches complete registry metadata including all available items.

/**
 * Get a registry by name or URL
 * @param name - Registry name (with @ prefix) or full URL
 * @param options - Optional configuration and caching options
 * @returns Promise resolving to registry object
 * @throws RegistryInvalidNamespaceError if name doesn't start with @ (when not URL)
 * @throws RegistryNotFoundError if registry is not found
 * @throws RegistryParseError if registry response is invalid
 */
function getRegistry(
  name: string,
  options?: {
    config?: Partial<Config>
    useCache?: boolean
  }
): Promise<Registry>

Parameters:

  • name: string - Registry name (e.g., '@shadcn') or URL (e.g., 'https://ui.shadcn.com/r/registry'). If name, must start with @.
  • options.config?: Partial<Config> - Optional configuration override.
  • options.useCache?: boolean - Whether to use HTTP cache (default: false).

Returns: Promise<Registry> - Registry object with:

  • name: string - Registry name
  • homepage: string - Registry homepage URL
  • items: RegistryItem[] - Array of all available items

Throws:

  • RegistryInvalidNamespaceError - If name doesn't start with @ (when not URL)
  • RegistryNotFoundError - If registry is not found
  • RegistryParseError - If registry response is invalid
  • RegistryNotConfiguredError - If registry name not in config (when using name)

Usage Example:

import { getRegistry } from 'shadcn';

// Get registry by name
const registry = await getRegistry('@shadcn');

console.log(registry.name);     // 'shadcn'
console.log(registry.homepage); // 'https://ui.shadcn.com'
console.log(registry.items);    // Array of all available items

// Get registry by URL
const customRegistry = await getRegistry(
  'https://custom.registry.com/registry.json'
);

// With caching
const registry = await getRegistry('@shadcn', { useCache: true });

// Browse available items
registry.items.forEach(item => {
  console.log(item.name, item.type, item.description);
});

URL Format:

  • Registry URLs must include {name} placeholder for item-specific requests
  • Example: https://ui.shadcn.com/r/{name}.json

getRegistriesIndex

Gets the registries index listing all available public registries. Fetches the central index of known registries.

/**
 * Get the registries index
 * @param options - Optional caching options
 * @returns Promise resolving to registries index
 * @throws RegistriesIndexParseError if index response is invalid
 */
function getRegistriesIndex(
  options?: { useCache?: boolean }
): Promise<RegistriesIndex>

Parameters:

  • options.useCache?: boolean - Whether to use HTTP cache (default: true). Caching is enabled by default for index.

Returns: Promise<RegistriesIndex> - Record mapping registry namespace to URL:

type RegistriesIndex = Record<string, string>
// Example: { "@shadcn": "https://ui.shadcn.com/r/{name}.json" }

Throws:

  • RegistriesIndexParseError - If index response is invalid
  • RegistryFetchError - On network errors

Usage Example:

import { getRegistriesIndex } from 'shadcn';

// Get list of all public registries
const index = await getRegistriesIndex();

// Browse available registries
Object.entries(index).forEach(([name, url]) => {
  console.log(name);        // Registry name (e.g., '@shadcn')
  console.log(url);         // Registry URL
});

// Without cache
const freshIndex = await getRegistriesIndex({ useCache: false });

searchRegistries

Searches items across multiple registries with fuzzy matching. Performs fuzzy search on item names and descriptions with pagination support.

/**
 * Search items across registries with fuzzy matching
 * @param registries - Array of registry names to search
 * @param options - Search query, pagination, config, and caching options
 * @returns Promise resolving to search results with pagination
 * @throws RegistryNotConfiguredError if registry not configured
 */
function searchRegistries(
  registries: string[],
  options?: {
    query?: string
    limit?: number
    offset?: number
    config?: Partial<Config>
    useCache?: boolean
  }
): Promise<SearchResults>

Parameters:

  • registries: string[] - Array of registry names to search (e.g., ['@shadcn', '@acme']). Required, must not be empty. Must start with @.
  • options.query?: string - Search query for fuzzy matching. Optional - omit to list all items.
  • options.limit?: number - Maximum items to return. Optional, default varies by registry.
  • options.offset?: number - Pagination offset. Optional, default: 0.
  • options.config?: Partial<Config> - Optional configuration override.
  • options.useCache?: boolean - Whether to use HTTP cache (default: false).

Returns: Promise<SearchResults> - Search results with:

interface SearchResults {
  pagination: {
    total: number
    offset: number
    limit: number
    hasMore: boolean
  }
  items: SearchResultItem[]
}

interface SearchResultItem {
  name: string
  type?: string
  description?: string
  registry: string
  addCommandArgument: string  // Full name for add command (e.g., '@shadcn/button')
}

Throws:

  • RegistryNotConfiguredError - If registry not configured
  • RegistryInvalidNamespaceError - If registry name doesn't start with @

Usage Example:

import { searchRegistries } from 'shadcn/registry';

// Search for "button" across registries
const results = await searchRegistries(['@shadcn'], {
  query: 'button'
});

console.log(results.pagination.total);   // Total matches
console.log(results.pagination.hasMore); // More results available?
console.log(results.items);              // Array of matching items

// List all items (no query)
const allItems = await searchRegistries(['@shadcn']);

// With pagination
const firstPage = await searchRegistries(['@shadcn'], {
  query: 'form',
  limit: 10,
  offset: 0
});

const secondPage = await searchRegistries(['@shadcn'], {
  query: 'form',
  limit: 10,
  offset: 10
});

// Search multiple registries
const multiResults = await searchRegistries(
  ['@shadcn', '@acme', '@custom'],
  { query: 'input' }
);

// Access search result items
results.items.forEach(item => {
  console.log(item.name);                // Item name
  console.log(item.type);                // Item type
  console.log(item.description);         // Description
  console.log(item.registry);            // Source registry
  console.log(item.addCommandArgument);  // Full name for add command
});

Fuzzy Matching:

  • Matches item names (partial and full)
  • Matches descriptions (keyword matching)
  • Case-insensitive
  • Results sorted by relevance

getRegistriesConfig

Gets registries configuration from components.json. Loads and merges built-in and user-configured registries.

/**
 * Get registries configuration from components.json
 * @param cwd - Working directory containing components.json
 * @param options - Optional caching options
 * @returns Promise resolving to registries config
 * @throws ConfigMissingError if components.json not found
 * @throws ConfigParseError if components.json is invalid
 */
function getRegistriesConfig(
  cwd: string,
  options?: { useCache?: boolean }
): Promise<{ registries: RegistryConfig }>

Parameters:

  • cwd: string - Working directory path. Searches for components.json in this directory and parent directories.
  • options.useCache?: boolean - Whether to use config cache (default: true). Caching is enabled by default.

Returns: Promise<{ registries: RegistryConfig }> - Merged registries configuration:

type RegistryConfig = Record<string, string | RegistryConfigItem>

interface RegistryConfigItem {
  url: string
  params?: Record<string, string>
  headers?: Record<string, string>
}

Throws:

  • ConfigMissingError - If components.json not found
  • ConfigParseError - If components.json is invalid JSON or schema

Usage Example:

import { getRegistriesConfig } from 'shadcn';

// Get registries from current directory
const { registries } = await getRegistriesConfig(process.cwd());

console.log(Object.keys(registries)); // ['@shadcn', '@acme', ...]

// Access registry config
const shadcnConfig = registries['@shadcn'];
// Can be string URL or object with url, headers, params

// Without cache
const fresh = await getRegistriesConfig(process.cwd(), { useCache: false });

Configuration Merging:

  • Merges built-in registries with user-configured registries
  • User configuration takes precedence
  • Built-in registries include @shadcn

getShadcnRegistryIndex

Gets the shadcn registry index. Fetches the official shadcn/ui component index.

/**
 * Get the shadcn registry index
 * @returns Promise resolving to registry index
 * @throws RegistryFetchError on network errors
 * @throws RegistryParseError if index response is invalid
 */
function getShadcnRegistryIndex(): Promise<RegistryIndex>

Returns: Promise<RegistryIndex> - Array of registry item metadata (RegistryItem[] without full file content).

Throws:

  • RegistryFetchError - On network errors
  • RegistryParseError - If index response is invalid

Usage Example:

import { getShadcnRegistryIndex } from 'shadcn';

// Get shadcn component index
const index = await getShadcnRegistryIndex();

// Browse available components
index.forEach(item => {
  console.log(item.name);                  // Component name
  console.log(item.type);                  // Item type
  console.log(item.description);           // Description
  console.log(item.registryDependencies);  // Registry deps
  console.log(item.dependencies);          // npm deps
});

// Find specific component
const button = index.find(item => item.name === 'button');

Note: This function fetches the index directly from shadcn registry, bypassing local configuration.

getRegistryStyles

Gets available style options from registry. Fetches the list of available visual styles (e.g., 'default', 'new-york').

/**
 * Get available registry styles
 * @returns Promise resolving to array of style objects
 * @throws RegistryFetchError on network errors
 */
function getRegistryStyles(): Promise<Style[]>

Returns: Promise<Style[]> - Array of available styles:

interface Style {
  name: string
  label: string
  description?: string
}

Throws:

  • RegistryFetchError - On network errors

Usage Example:

import { getRegistryStyles } from 'shadcn';

// Get available styles
const styles = await getRegistryStyles();

styles.forEach(style => {
  console.log(style.name);        // 'default', 'new-york'
  console.log(style.label);       // Display name
  console.log(style.description); // Style description
});

getRegistryIcons

Gets available icon libraries from registry. Fetches the list of supported icon library configurations.

/**
 * Get available icon libraries
 * @returns Promise resolving to icons object
 * @throws RegistryFetchError on network errors
 */
function getRegistryIcons(): Promise<Icons>

Returns: Promise<Icons> - Object mapping icon library names to metadata:

type Icons = Record<string, IconLibrary>

interface IconLibrary {
  name: string
  title: string
  packages: string[]
  import: string
  usage: string
  export: string
}

Throws:

  • RegistryFetchError - On network errors

Usage Example:

import { getRegistryIcons } from 'shadcn';

// Get available icon libraries
const icons = await getRegistryIcons();

console.log(Object.keys(icons)); // ['lucide', 'tabler', 'hugeicons', 'phosphor']

// Access icon library config
const lucide = icons.lucide;
console.log(lucide.name);     // 'lucide'
console.log(lucide.packages); // ['lucide-react']
console.log(lucide.import);   // Import pattern
console.log(lucide.usage);    // Usage pattern

getRegistryBaseColors

Gets available base color options. Returns the list of base color choices for theming.

/**
 * Get available base colors
 * @returns Promise resolving to array of base color objects
 * @throws RegistryFetchError on network errors
 */
function getRegistryBaseColors(): Promise<BaseColor[]>

Returns: Promise<BaseColor[]> - Array of base color objects:

interface BaseColor {
  name: string
  label: string
}

Throws:

  • RegistryFetchError - On network errors

Usage Example:

import { getRegistryBaseColors } from 'shadcn';

// Get available base colors
const colors = await getRegistryBaseColors();

console.log(colors);
// [
//   { name: 'neutral', label: 'Neutral' },
//   { name: 'gray', label: 'Gray' },
//   { name: 'zinc', label: 'Zinc' },
//   { name: 'stone', label: 'Stone' },
//   { name: 'slate', label: 'Slate' }
// ]

getRegistryBaseColor

Gets specific base color configuration. Fetches the CSS variable definitions for a base color.

/**
 * Get specific base color configuration
 * @param baseColor - Base color name (e.g., 'slate')
 * @returns Promise resolving to base color config with CSS variables
 * @throws RegistryNotFoundError if base color not found
 * @throws RegistryFetchError on network errors
 */
function getRegistryBaseColor(
  baseColor: string
): Promise<RegistryBaseColor>

Parameters:

  • baseColor: string - Base color name (e.g., 'slate', 'zinc'). Required.

Returns: Promise<RegistryBaseColor> - Base color configuration object:

interface RegistryBaseColor {
  name: string
  label: string
  inlineColors?: Record<string, string>
  cssVars?: {
    light?: Record<string, string>
    dark?: Record<string, string>
  }
  templates?: {
    shadcn?: string
    new_york?: string
  }
}

Throws:

  • RegistryNotFoundError - If base color not found
  • RegistryFetchError - On network errors

Usage Example:

import { getRegistryBaseColor } from 'shadcn';

// Get slate color configuration
const slate = await getRegistryBaseColor('slate');

console.log(slate.name);       // 'slate'
console.log(slate.label);      // 'Slate'
console.log(slate.cssVars);    // CSS variable definitions

// CSS vars structure
console.log(slate.cssVars.light); // Light theme variables
console.log(slate.cssVars.dark);  // Dark theme variables

getPresets

Gets available presets for initialization. Fetches preset configurations that can be used with init command.

/**
 * Get available presets
 * @param options - Optional caching options
 * @returns Promise resolving to array of presets
 * @throws RegistryFetchError on network errors
 */
function getPresets(
  options?: { useCache?: boolean }
): Promise<Preset[]>

Parameters:

  • options.useCache?: boolean - Whether to use HTTP cache (default: true). Caching is enabled by default.

Returns: Promise<Preset[]> - Array of preset configurations:

interface Preset {
  name: string
  label: string
  description?: string
  config: Partial<Config>
}

Throws:

  • RegistryFetchError - On network errors

Usage Example:

import { getPresets } from 'shadcn';

// Get available presets
const presets = await getPresets();

presets.forEach(preset => {
  console.log(preset.name);        // Preset name
  console.log(preset.label);       // Display name
  console.log(preset.description); // Description
  console.log(preset.config);      // Configuration object
});

getPreset

Gets a specific preset by name. Fetches a single preset configuration.

/**
 * Get specific preset by name
 * @param name - Preset name
 * @param options - Optional caching options
 * @returns Promise resolving to preset or null if not found
 * @throws RegistryFetchError on network errors
 */
function getPreset(
  name: string,
  options?: { useCache?: boolean }
): Promise<Preset | null>

Parameters:

  • name: string - Preset name (case-insensitive). Required.
  • options.useCache?: boolean - Whether to use HTTP cache (default: true).

Returns: Promise<Preset | null> - Preset object or null if not found.

Throws:

  • RegistryFetchError - On network errors

Usage Example:

import { getPreset } from 'shadcn';

// Get specific preset
const preset = await getPreset('default');

if (preset) {
  console.log(preset.name);   // 'default'
  console.log(preset.config); // Configuration object
}

Deprecated Functions

These functions are deprecated and will be removed in a future version:

resolveTree (deprecated)

Resolves component dependency tree from registry index.

/**
 * @deprecated Use resolveRegistryItems instead
 */
function resolveTree(
  index: RegistryIndex,
  names: string[]
): Promise<RegistryIndex>

fetchTree (deprecated)

Fetches registry items from dependency tree.

/**
 * @deprecated Use getRegistryItems with resolved names instead
 */
function fetchTree(
  style: string,
  tree: RegistryIndex
): Promise<RegistryItem[]>

getItemTargetPath (deprecated)

Gets target path for registry item installation.

/**
 * @deprecated Path resolution is handled internally
 */
function getItemTargetPath(
  config: Config,
  item: Pick<RegistryItem, "type">,
  override?: string
): Promise<string | null>

Types

// Registry item type
interface RegistryItem {
  name: string
  type: RegistryItemType
  description?: string
  dependencies?: string[]
  devDependencies?: string[]
  registryDependencies?: string[]
  files?: RegistryItemFile[]
  tailwind?: RegistryItemTailwind
  cssVars?: RegistryItemCssVars
  css?: RegistryItemCss
  envVars?: Record<string, string>
  meta?: Record<string, any>
  docs?: string
  categories?: string[]
}

// Registry type
interface Registry {
  name: string
  homepage: string
  items: RegistryItem[]
}

// Search results type
interface SearchResults {
  pagination: {
    total: number
    offset: number
    limit: number
    hasMore: boolean
  }
  items: SearchResultItem[]
}

// Search result item
interface SearchResultItem {
  name: string
  type?: string
  description?: string
  registry: string
  addCommandArgument: string
}

// Registry resolved items tree
interface RegistryResolvedItemsTree {
  dependencies?: string[]
  devDependencies?: string[]
  files?: RegistryItemFile[]
  tailwind?: RegistryItemTailwind
  cssVars?: RegistryItemCssVars
  css?: RegistryItemCss
  envVars?: Record<string, string>
  docs?: string
  fonts?: RegistryFontItem[]
}

// Configuration type
interface Config {
  style: string
  rsc: boolean
  tsx: boolean
  tailwind: {
    config?: string
    css: string
    baseColor: string
    cssVariables: boolean
    prefix?: string
  }
  aliases: {
    components: string
    utils: string
    ui?: string
    lib?: string
    hooks?: string
  }
  registries?: RegistryConfig
  resolvedPaths: {
    cwd: string
    tailwindConfig: string
    tailwindCss: string
    utils: string
    components: string
    lib: string
    hooks: string
    ui: string
  }
}

// Registry configuration
type RegistryConfig = Record<string, string | RegistryConfigItem>

interface RegistryConfigItem {
  url: string
  params?: Record<string, string>
  headers?: Record<string, string>
}

// Registry index (array of registry items)
type RegistryIndex = RegistryItem[]

// Style configuration
interface Style {
  name: string
  label: string
  description?: string
}

// Icons configuration
type Icons = Record<string, IconLibrary>

interface IconLibrary {
  name: string
  title: string
  packages: string[]
  import: string
  usage: string
  export: string
}

// Base color types
interface BaseColor {
  name: string
  label: string
}

interface RegistryBaseColor {
  name: string
  label: string
  inlineColors?: Record<string, string>
  cssVars?: {
    light?: Record<string, string>
    dark?: Record<string, string>
  }
  templates?: {
    shadcn?: string
    new_york?: string
  }
}

// Registries index
type RegistriesIndex = Record<string, string>

// Preset configuration
interface Preset {
  name: string
  label: string
  description?: string
  config: Partial<Config>
}

Error Handling

All registry functions may throw specific registry errors. See the main documentation for error types and handling.

Common Error Patterns:

import {
  getRegistryItems,
  RegistryError,
  RegistryNotFoundError,
  RegistryNotConfiguredError,
  ConfigMissingError
} from 'shadcn/registry';

async function safeRegistryOperation() {
  try {
    const items = await getRegistryItems(['@shadcn/button']);
    return items;
  } catch (error) {
    if (error instanceof ConfigMissingError) {
      throw new Error('Project not initialized. Run: npx shadcn init');
    } else if (error instanceof RegistryNotConfiguredError) {
      throw new Error(`Registry not configured: ${error.context?.registry}`);
    } else if (error instanceof RegistryNotFoundError) {
      throw new Error(`Item not found: ${error.message}`);
    } else if (error instanceof RegistryError) {
      throw new Error(`Registry error: ${error.code} - ${error.message}`);
    }
    throw error;
  }
}