Skip to content
@calycode/cli docs
GitHub Discord

Registry Authoring Guide

This guide covers how to create, publish, and share reusable Xano components using the Xano Tools registry system.

Table of Contents

Overview

The Xano Tools registry system enables you to:

  • Create reusable components - Package functions, APIs, tables, and more
  • Share with your team - Host registries for organization-wide use
  • Manage dependencies - Components can depend on other components
  • Version your work - Track changes with metadata timestamps
  • Overcome Snippet limitations - Build complex, multi-file components that standard Xano Snippets can't handle

Why Use Registries Over Snippets?

FeatureXano SnippetsRegistry Components
Multi-file components✅✅
Dependency management✅✅
Team sharingLimited✅ Full control
Version tracking❌✅
Custom metadata❌✅
Programmatic installation❌✅ CLI/API

Quick Start

1. Scaffold a New Registry

Bash
# Create a new registry folder with sample components
caly-xano registry scaffold --output ./my-registry

This creates:

Code
my-registry/
├── registry.json           # Registry metadata
├── items/
│   └── sample-function/
│       ├── definition.json # Component definition
│       └── function.xs     # XanoScript content
└── README.md

2. Modify the Sample Component

Edit items/sample-function/definition.json:

JSON
{
   "$schema": "https://calycode.com/schemas/registry/registry-item.json",
   "name": "my-utils/string-helpers",
   "type": "registry:function",
   "title": "String Helper Functions",
   "description": "Utility functions for string manipulation",
   "author": "your-name <https://github.com/your-name>",
   "files": [
      {
         "path": "./function.xs",
         "type": "registry:function"
      }
   ]
}

3. Serve Your Registry Locally

Bash
caly-xano serve registry --path ./my-registry

Registry available at: http://localhost:5500/registry/definitions

4. Test Installation

Bash
# In another terminal, install to your Xano instance
caly-xano registry add my-utils/string-helpers \
  --registry http://localhost:5500/registry/definitions \
  --instance my-instance \
  --workspace main \
  --branch dev

Registry Structure

A registry consists of:

Registry Root (registry.json)

JSON
{
   "$schema": "https://calycode.com/schemas/registry/registry.json",
   "name": "my-company-registry",
   "description": "Reusable Xano components for My Company",
   "items": [
      "items/auth/jwt-verify/definition.json",
      "items/utils/string-helpers/definition.json",
      "items/integrations/stripe/definition.json"
   ]
}

Component Folders

Organize components by category:

Code
my-registry/
├── registry.json
├── items/
│   ├── auth/
│   │   ├── jwt-verify/
│   │   │   ├── definition.json
│   │   │   └── verify.xs
│   │   └── oauth-google/
│   │       ├── definition.json
│   │       ├── init.xs
│   │       └── callback.xs
│   ├── utils/
│   │   └── string-helpers/
│   │       ├── definition.json
│   │       └── helpers.xs
│   └── integrations/
│       └── stripe/
│           ├── definition.json
│           ├── customer.xs
│           └── webhook.xs

Creating Registry Items

Supported Component Types

TypeDescriptionUse Case
registry:functionCustom function stackReusable business logic
registry:addonAddon/extensionUtility functions
registry:apigroupAPI endpoint groupComplete API modules
registry:tableDatabase tableSchema definitions
registry:middlewareRequest middlewareAuth, logging, etc.
registry:taskScheduled taskBackground jobs
registry:toolAI toolLLM integrations
registry:agentAI agentAutonomous workflows
registry:mcpMCP serverModel Context Protocol
registry:realtimeRealtime channelWebSocket channels
registry:queryAPI endpointSingle API endpoint
registry:snippetCode snippetReusable code blocks
registry:testTest suiteAPI tests
registry:fileGeneric fileAny file type
TriggersVarious trigger typesEvent handlers

Creating a Function Component

1. Create the definition file (definition.json):

JSON
{
   "$schema": "https://calycode.com/schemas/registry/registry-item.json",
   "name": "utils/jwt-helper",
   "type": "registry:function",
   "title": "JWT Helper Functions",
   "description": "Functions for JWT token generation and validation",
   "author": "team <https://github.com/team>",
   "categories": ["auth", "security", "jwt"],
   "docs": "## JWT Helper\n\nThis component provides JWT utilities:\n\n- `jwt_generate` - Create signed tokens\n- `jwt_verify` - Validate tokens\n- `jwt_decode` - Decode without verification",
   "postInstallHint": "Remember to set XANO_JWT_SECRET in your environment variables!",
   "files": [
      {
         "path": "./jwt-helper.xs",
         "type": "registry:function",
         "meta": {
            "updated_at": "2024-01-15T10:30:00Z"
         }
      }
   ],
   "registryDependencies": ["utils/base64"],
   "meta": {
      "version": "1.0.0",
      "xano_version": "2.0+"
   }
}

2. Create the XanoScript file (jwt-helper.xs):

For XanoScript syntax and examples, refer to the official Xano documentation.

Creating an API Group Component

JSON
{
   "$schema": "https://calycode.com/schemas/registry/registry-item.json",
   "name": "api/user-management",
   "type": "registry:apigroup",
   "title": "User Management API",
   "description": "Complete CRUD API for user management",
   "files": [
      {
         "path": "./user-api.xs",
         "type": "registry:apigroup"
      }
   ],
   "registryDependencies": ["tables/user", "utils/password-hash", "utils/email-validator"]
}

Creating a Table Component

JSON
{
   "$schema": "https://calycode.com/schemas/registry/registry-item.json",
   "name": "tables/user",
   "type": "registry:table",
   "title": "User Table",
   "description": "Standard user table with common fields",
   "files": [
      {
         "path": "./user-table.xs",
         "type": "registry:table"
      }
   ]
}

Registry Item Schema

Required Fields

FieldTypeDescription
namestringUnique identifier (can include / for hierarchy)
typestringComponent type (see supported types above)
filesarrayFiles that make up this component

Optional Fields

FieldTypeDescription
titlestringHuman-readable display name
descriptionstringBrief overview of the component
docsstringMarkdown documentation (rendered in registry UI)
authorstringAuthor info: name <url>
categoriesarrayTags for search and organization
postInstallHintstringMessage shown after installation
registryDependenciesarrayOther components this depends on
metaobjectCustom metadata (version, dates, etc.)

Files Array Entry

FieldTypeRequiredDescription
pathstringOne of path/contentRelative file path
contentstringOne of path/contentInline XanoScript content
typestringYesFile type (same as component types)
apiGroupNamestringFor registry:queryTarget API group name
metaobjectNoFile-specific metadata

Inline Content Example

Instead of referencing a file, you can inline the content:

JSON
{
   "name": "utils/simple-helper",
   "type": "registry:function",
   "files": [
      {
         "content": "// XanoScript content here\nfunction simple_helper() {\n  // ...\n}",
         "type": "registry:function"
      }
   ]
}

Including XanoScript Content

Option 1: File References

Store XanoScript in separate .xs files:

JSON
{
   "files": [
      {
         "path": "./my-function.xs",
         "type": "registry:function"
      }
   ]
}

Option 2: Inline Content

Include XanoScript directly in the definition:

JSON
{
   "files": [
      {
         "content": "// Your XanoScript here",
         "type": "registry:function"
      }
   ]
}

Writing XanoScript

For comprehensive XanoScript documentation, see:

Dependency Management

How Dependencies Work

When you install a component with caly-xano registry add:

  1. The CLI reads the component's registryDependencies array
  2. All dependencies are resolved recursively
  3. Dependencies are installed in the correct order (dependencies first)
  4. Already-installed components are skipped

Declaring Dependencies

JSON
{
   "name": "api/checkout",
   "type": "registry:apigroup",
   "registryDependencies": [
      "tables/order",
      "tables/product",
      "utils/stripe-client",
      "utils/email-sender"
   ]
}

Dependency Resolution

Code
api/checkout
├── tables/order
│   └── (no dependencies)
├── tables/product
│   └── (no dependencies)
├── utils/stripe-client
│   └── utils/http-client
└── utils/email-sender
    └── utils/template-engine

Installation order:

  1. tables/order
  2. tables/product
  3. utils/http-client
  4. utils/stripe-client
  5. utils/template-engine
  6. utils/email-sender
  7. api/checkout

Version Tracking

Components track versions via metadata:

JSON
{
   "meta": {
      "version": "1.2.0",
      "updated_at": "2024-01-15T10:30:00Z",
      "changelog": "Added support for refresh tokens"
   }
}

Note: The current registry system uses timestamps for version tracking. Full semantic versioning support is planned for future releases.

Best Practices for Dependencies

  1. Keep dependencies minimal - Only include what's truly required
  2. Avoid circular dependencies - A cannot depend on B if B depends on A
  3. Use consistent naming - Follow a clear naming convention
  4. Document requirements - Use postInstallHint for manual steps

Testing Your Registry

Local Testing Workflow

Bash
# Terminal 1: Serve your registry
caly-xano serve registry --path ./my-registry

# Terminal 2: Test installation
caly-xano registry add my-component \
  --registry http://localhost:5500/registry/definitions \
  --instance test-instance \
  --workspace dev \
  --branch feature

Validating Definitions

Ensure your JSON files match the schema:

Bash
# Use a JSON schema validator
npx ajv validate -s https://calycode.com/schemas/registry/registry-item.json -d ./definition.json

Publishing Your Registry

Option 1: Static File Hosting

Host your registry files on any static server:

Bash
# Build your registry
# Copy to web server
scp -r ./my-registry/* user@server:/var/www/registry/

# Access at: https://registry.example.com/definitions

Option 2: GitHub Pages

YAML
# .github/workflows/deploy-registry.yml
name: Deploy Registry
on:
   push:
      branches: [main]
      paths: ['registry/**']

jobs:
   deploy:
      runs-on: ubuntu-latest
      steps:
         - uses: actions/checkout@v4
         - uses: peaceiris/actions-gh-pages@v3
           with:
              github_token: ${{ secrets.GITHUB_TOKEN }}
              publish_dir: ./registry

Option 3: NPM Package

Package your registry for npm distribution:

JSON
// package.json
{
   "name": "@your-org/xano-registry",
   "files": ["registry/**"],
   "scripts": {
      "serve": "caly-xano serve registry --path ./registry"
   }
}

Team Usage

Bash
# Team members install from your registry
caly-xano registry add auth/jwt-verify \
  --registry https://registry.your-company.com/definitions

Team Usage with NPM Scoped Registry

For organizations using private npm registries, you can leverage npm's scoped package system for controlled access:

JSON
// package.json
{
   "name": "@acme-corp/xano-components",
   "version": "1.0.0",
   "description": "Internal Xano components for ACME Corp",
   "private": true,
   "files": ["registry/**"],
   "scripts": {
      "serve": "caly-xano serve registry --path ./registry",
      "validate": "npx ajv validate -s https://calycode.com/schemas/registry/registry.json -d ./registry/registry.json"
   },
   "publishConfig": {
      "registry": "https://npm.pkg.github.com"
   }
}

Team Setup:

Bash
# 1. Configure npm to use your organization's private registry for the scope
npm config set @acme-corp:registry https://npm.pkg.github.com

# 2. Authenticate with your private registry
npm login --registry=https://npm.pkg.github.com --scope=@acme-corp

# 3. Install the shared registry package
npm install @acme-corp/xano-components

# 4. Serve the registry locally from node_modules
caly-xano serve registry --path ./node_modules/@acme-corp/xano-components/registry

# 5. Install components from the local registry
caly-xano registry add auth/sso-integration \
  --registry http://localhost:5500/registry/definitions \
  --instance production \
  --workspace main

Benefits of NPM Scoped Registries:

FeatureDescription
Access ControlLeverage existing npm org permissions and team roles
Version ManagementUse npm's semver for registry versioning
CI/CD IntegrationEasily integrate with existing npm-based pipelines
Audit TrailTrack who published what and when via npm audit logs
Offline DevelopmentCache packages locally for air-gapped environments
Multi-RegistryTeams can combine public and private registries per scope

Example: Multi-Team Registry Structure

Code
@acme-corp/xano-components/
├── package.json
├── registry/
│   ├── registry.json
│   └── items/
│       ├── core/              # Shared by all teams
│       │   ├── auth/
│       │   └── logging/
│       ├── team-payments/     # Payments team components
│       │   ├── stripe/
│       │   └── invoicing/
│       └── team-crm/          # CRM team components
│           ├── contacts/
│           └── pipelines/
JSON
// registry/registry.json
{
   "$schema": "https://calycode.com/schemas/registry/registry.json",
   "name": "acme-corp-registry",
   "description": "ACME Corp internal Xano components",
   "items": [
      "items/core/auth/jwt-sso/definition.json",
      "items/core/logging/audit-log/definition.json",
      "items/team-payments/stripe/checkout/definition.json",
      "items/team-payments/invoicing/generator/definition.json",
      "items/team-crm/contacts/sync/definition.json",
      "items/team-crm/pipelines/automation/definition.json"
   ]
}

Publishing Updates:

Bash
# Bump version and publish to private registry
npm version patch
npm publish

# Team members update to latest
npm update @acme-corp/xano-components

Best Practices

Naming Conventions

Code
category/component-name

Examples:
- auth/jwt-verify
- utils/string-helpers
- integrations/stripe-webhook
- tables/user
- api/user-management

Documentation

Always include:

  1. Description - What the component does
  2. Docs - Detailed usage instructions
  3. postInstallHint - Required post-install steps
  4. Categories - For discoverability

Component Design

  1. Single responsibility - Each component should do one thing well
  2. Minimal dependencies - Reduce coupling
  3. Clear interfaces - Document inputs/outputs
  4. Idempotent installation - Safe to install multiple times

Security

  1. No secrets in code - Use environment variables
  2. Document required secrets - In postInstallHint
  3. Review before sharing - Audit code for sensitive data

Resources