Skip to main content
Learn how to create your own components and publish them to a custom registry.

Component structure

A component is defined by the ComponentDefinition interface:
interface ComponentDefinition {
  name: string;
  description?: string;
  type: 'react' | 'vue' | 'svelte' | 'solid' | 'vanilla';
  files: ComponentFile[];
  dependencies?: Record<string, string>;
  registryDependencies?: string[];
}

interface ComponentFile {
  name: string;
  content: string;
}

Creating a component

1

Define the component

Create a new component definition:
const myComponent: ComponentDefinition = {
  name: 'countdown',
  description: 'Display a countdown timer',
  type: 'react',
  files: [
    {
      name: 'Countdown.tsx',
      content: `import React from 'react';
import { useVideoFrame } from './useVideoFrame';
import { Helios } from '@helios-project/core';

interface CountdownProps {
helios?: Helios;
targetFrame?: number;
}

export const Countdown: React.FC<CountdownProps> = ({ 
helios, 
targetFrame = 300 
}) => {
const frame = useVideoFrame(helios);
const remaining = Math.max(0, targetFrame - frame);

return <div>{remaining} frames remaining</div>;
};
`
    }
  ],
  dependencies: {
    'react': '^18.0.0',
    '@helios-project/core': 'latest'
  },
  registryDependencies: ['use-video-frame']
};
2

Add to local registry

For testing, add your component to the local registry manifest:
// packages/cli/src/registry/manifest.ts
export const registry: ComponentDefinition[] = [
  // ... existing components
  myComponent
];
3

Test locally

Test your component by installing it:
helios add countdown

Publishing a registry

1

Create registry index

Build a registry index file (index.json):
{
  "version": "1.0.0",
  "components": [
    {
      "name": "countdown",
      "description": "Display a countdown timer",
      "type": "react",
      "files": ["countdown/Countdown.tsx"],
      "dependencies": {
        "react": "^18.0.0",
        "@helios-project/core": "latest"
      },
      "registryDependencies": ["use-video-frame"]
    }
  ]
}
2

Host component files

Place component files at the paths specified in the index:
registry/
├── index.json
└── countdown/
    └── Countdown.tsx
3

Deploy to hosting

Upload your registry to static hosting:
# Example: Deploy to GitHub Pages, Vercel, Netlify, S3, etc.
# Make sure index.json and component files are publicly accessible
4

Configure users

Users point to your registry in helios.config.json:
{
  "registry": "https://your-domain.com/registry/index.json"
}

Registry format

The registry supports two formats:
{
  "version": "1.0.0",
  "components": [
    {
      "name": "timer",
      "description": "Video timecode display",
      "type": "react",
      "files": ["timer/Timer.tsx"],
      "dependencies": { ... },
      "registryDependencies": ["use-video-frame"]
    }
  ]
}
Files are fetched on-demand when installing a component.

Legacy format

[
  {
    "name": "timer",
    "type": "react",
    "files": [
      {
        "name": "Timer.tsx",
        "content": "...full file content..."
      }
    ]
  }
]
All file content is included inline. Not recommended for large registries.

Authentication

For private registries, set an environment variable:
export HELIOS_REGISTRY_TOKEN="your-token"
The CLI sends this as a Bearer token:
Authorization: Bearer your-token

Best practices

  • Keep components focused - One component per responsibility
  • Document props - Use TypeScript interfaces and JSDoc comments
  • Minimize dependencies - Fewer npm packages = easier installation
  • Use registry dependencies - Reuse common utilities like use-video-frame
  • Test thoroughly - Install components in a real project before publishing
  • Version carefully - Consider semantic versioning for breaking changes

Example registry structure

my-registry/
├── index.json
├── timer/
│   └── Timer.tsx
├── progress-bar/
│   └── ProgressBar.tsx
├── watermark/
│   └── Watermark.tsx
└── use-video-frame/
    └── useVideoFrame.ts

Timeout and fallback

The registry client has a 5-second timeout. If fetching fails:
  • The CLI falls back to the local built-in registry
  • Users see a warning but can still use default components
Ensure your registry hosting is reliable and fast.

Multi-framework support

Publish variants for different frameworks:
{
  "components": [
    {
      "name": "timer",
      "type": "react",
      "files": ["timer/Timer.tsx"]
    },
    {
      "name": "timer",
      "type": "vue",
      "files": ["timer/Timer.vue"]
    }
  ]
}
The CLI automatically selects the correct variant based on the user’s configured framework.

Build docs developers (and LLMs) love