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
- Quick Start
- Registry Structure
- Creating Registry Items
- Registry Item Schema
- Including XanoScript Content
- Dependency Management
- Testing Your Registry
- Publishing Your Registry
- Best Practices
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?
| Feature | Xano Snippets | Registry Components |
|---|---|---|
| Multi-file components | ✅ | ✅ |
| Dependency management | ✅ | ✅ |
| Team sharing | Limited | ✅ Full control |
| Version tracking | ❌ | ✅ |
| Custom metadata | ❌ | ✅ |
| Programmatic installation | ❌ | ✅ CLI/API |
Quick Start
1. Scaffold a New Registry
# Create a new registry folder with sample components
caly-xano registry scaffold --output ./my-registry
This creates:
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:
{
"$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
caly-xano serve registry --path ./my-registry
Registry available at: http://localhost:5500/registry/definitions
4. Test Installation
# 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)
{
"$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:
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
| Type | Description | Use Case |
|---|---|---|
registry:function | Custom function stack | Reusable business logic |
registry:addon | Addon/extension | Utility functions |
registry:apigroup | API endpoint group | Complete API modules |
registry:table | Database table | Schema definitions |
registry:middleware | Request middleware | Auth, logging, etc. |
registry:task | Scheduled task | Background jobs |
registry:tool | AI tool | LLM integrations |
registry:agent | AI agent | Autonomous workflows |
registry:mcp | MCP server | Model Context Protocol |
registry:realtime | Realtime channel | WebSocket channels |
registry:query | API endpoint | Single API endpoint |
registry:snippet | Code snippet | Reusable code blocks |
registry:test | Test suite | API tests |
registry:file | Generic file | Any file type |
| Triggers | Various trigger types | Event handlers |
Creating a Function Component
1. Create the definition file (definition.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
{
"$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
{
"$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
| Field | Type | Description |
|---|---|---|
name | string | Unique identifier (can include / for hierarchy) |
type | string | Component type (see supported types above) |
files | array | Files that make up this component |
Optional Fields
| Field | Type | Description |
|---|---|---|
title | string | Human-readable display name |
description | string | Brief overview of the component |
docs | string | Markdown documentation (rendered in registry UI) |
author | string | Author info: name <url> |
categories | array | Tags for search and organization |
postInstallHint | string | Message shown after installation |
registryDependencies | array | Other components this depends on |
meta | object | Custom metadata (version, dates, etc.) |
Files Array Entry
| Field | Type | Required | Description |
|---|---|---|---|
path | string | One of path/content | Relative file path |
content | string | One of path/content | Inline XanoScript content |
type | string | Yes | File type (same as component types) |
apiGroupName | string | For registry:query | Target API group name |
meta | object | No | File-specific metadata |
Inline Content Example
Instead of referencing a file, you can inline the content:
{
"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:
{
"files": [
{
"path": "./my-function.xs",
"type": "registry:function"
}
]
}
Option 2: Inline Content
Include XanoScript directly in the definition:
{
"files": [
{
"content": "// Your XanoScript here",
"type": "registry:function"
}
]
}
Writing XanoScript
For comprehensive XanoScript documentation, see:
- Official Xano Docs: XanoScript VS Code Usage
- Xano VS Code Extension: Recommended for XanoScript development
Dependency Management
How Dependencies Work
When you install a component with caly-xano registry add:
- The CLI reads the component's
registryDependenciesarray - All dependencies are resolved recursively
- Dependencies are installed in the correct order (dependencies first)
- Already-installed components are skipped
Declaring Dependencies
{
"name": "api/checkout",
"type": "registry:apigroup",
"registryDependencies": [
"tables/order",
"tables/product",
"utils/stripe-client",
"utils/email-sender"
]
}
Dependency Resolution
api/checkout
├── tables/order
│ └── (no dependencies)
├── tables/product
│ └── (no dependencies)
├── utils/stripe-client
│ └── utils/http-client
└── utils/email-sender
└── utils/template-engine
Installation order:
tables/ordertables/productutils/http-clientutils/stripe-clientutils/template-engineutils/email-senderapi/checkout
Version Tracking
Components track versions via metadata:
{
"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
- Keep dependencies minimal - Only include what's truly required
- Avoid circular dependencies - A cannot depend on B if B depends on A
- Use consistent naming - Follow a clear naming convention
- Document requirements - Use
postInstallHintfor manual steps
Testing Your Registry
Local Testing Workflow
# 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:
# 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:
# 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
# .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:
// package.json
{
"name": "@your-org/xano-registry",
"files": ["registry/**"],
"scripts": {
"serve": "caly-xano serve registry --path ./registry"
}
}
Team Usage
# 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:
// 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:
# 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:
| Feature | Description |
|---|---|
| Access Control | Leverage existing npm org permissions and team roles |
| Version Management | Use npm's semver for registry versioning |
| CI/CD Integration | Easily integrate with existing npm-based pipelines |
| Audit Trail | Track who published what and when via npm audit logs |
| Offline Development | Cache packages locally for air-gapped environments |
| Multi-Registry | Teams can combine public and private registries per scope |
Example: Multi-Team Registry Structure
@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/
// 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:
# 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
category/component-name
Examples:
- auth/jwt-verify
- utils/string-helpers
- integrations/stripe-webhook
- tables/user
- api/user-management
Documentation
Always include:
- Description - What the component does
- Docs - Detailed usage instructions
- postInstallHint - Required post-install steps
- Categories - For discoverability
Component Design
- Single responsibility - Each component should do one thing well
- Minimal dependencies - Reduce coupling
- Clear interfaces - Document inputs/outputs
- Idempotent installation - Safe to install multiple times
Security
- No secrets in code - Use environment variables
- Document required secrets - In postInstallHint
- Review before sharing - Audit code for sensitive data