Skip to main content
The Solar registry is a module-level catalog of all components in your application. Each component registers itself when its file is imported, and the registry exposes the full catalog — including every component’s name and props schema — as a machine-readable manifest. AI agents read this manifest before generating any composition code, ensuring they only reference components that exist and call them with the correct prop types.

Methods

registry.register(component)

Adds a component to the registry. You must call this before using the component with mountComponent() or resolving it by name in h().
component
ComponentFn
required
A component function returned by defineComponent(). Solar checks the _isComponent flag on the argument. If you pass a plain function or any other value, registry.register throws a ContractError.
import { registry } from './solar/index.js'
import Button from './components/Button.js'

registry.register(Button)

registry.list()

Returns an array of all registered components, each with its name and props schema.
returns
array
An array of objects, one per registered component.
name
string
The component’s displayName — the value passed as config.name in defineComponent().
props
object
The component’s full props schema — the same object passed as config.props in defineComponent().
registry.list()
// →
// [
//   {
//     name: 'Button',
//     props: {
//       label:   { type: 'string',   required: true },
//       onClick: { type: 'function', required: true },
//       variant: { type: 'string',   enum: ['primary', 'secondary'], default: 'primary' },
//     }
//   },
//   {
//     name: 'Card',
//     props: { ... }
//   }
// ]

registry.manifest()

Returns a JSON string of registry.list(). Use this to pass the full component catalog to an AI agent or external tool without any additional serialisation step.
returns
string
A formatted JSON string (2-space indent) of the same data that registry.list() returns.
const manifest = registry.manifest()
console.log(manifest)
// [
//   {
//     "name": "Button",
//     "props": {
//       "label":   { "type": "string",   "required": true },
//       "onClick": { "type": "function", "required": true },
//       "variant": { "type": "string",   "enum": ["primary", "secondary"], "default": "primary" }
//     }
//   },
//   {
//     "name": "Card",
//     "props": { ... }
//   }
// ]

registry.get(name)

Retrieves a component function by display name.
name
string
required
The component’s display name, exactly as passed to defineComponent() — for example, 'Button' or 'Card'.
returns
ComponentFn | undefined
The ComponentFn if the component is registered, or undefined if not.
const ButtonFn = registry.get('Button')
if (ButtonFn) {
  const vnode = ButtonFn({ label: 'Go', onClick: handleGo })
}

registry.has(name)

Checks whether a component is registered.
name
string
required
The component’s display name to look up.
returns
boolean
true if the component is registered, false otherwise.
registry.has('Button')  // true
registry.has('Modal')   // false (not yet imported/registered)

Full example

import { registry } from './solar/index.js'

// Importing each file triggers registry.register() inside it
import './components/Button.js'
import './components/Card.js'

// Check registration
console.log(registry.has('Button'))  // true
console.log(registry.has('Modal'))   // false

// Retrieve and call a component function
const ButtonFn = registry.get('Button')

// Inspect all component schemas
const schemas = registry.list()

// Serialise the full manifest for an AI agent
const manifest = registry.manifest()
console.log(manifest)
// [
//   { "name": "Button", "props": { "label": { ... }, "onClick": { ... } } },
//   { "name": "Card",   "props": { ... } }
// ]
The recommended pattern is to call registry.register(ComponentName) at the bottom of each component file, after the defineComponent() call. That way, importing the file is the only thing needed to register the component — no separate registration step anywhere else. This keeps registration co-located with the component definition and makes it impossible to forget.
// components/Button.js
import { defineComponent, createElement, registry } from '../solar/index.js'

const Button = defineComponent({ name: 'Button', /* ... */ })

registry.register(Button)  // ← self-registers on import
export default Button