Files
2026-04-29 17:13:58 -04:00

11 KiB

Contributing to the Arcane Template Registry

Thank you for contributing! This registry is a curated collection of Docker Compose templates for Arcane. Template folders are the single source of truth — CI validates their structure, assembles registry.json from on-disk state, and publishes it to GitHub Pages.

Repository Overview

arcane-repo/
├── templates/           # One directory per template
│   ├── litellm/         # Example: LiteLLM proxy template
│   │   ├── arcane.json        # Metadata (id, name, version, author, tags)
│   │   ├── docker-compose.yml # Compose service definition
│   │   ├── .env.example       # Documented env var reference
│   │   └── README.md          # Template documentation
│   └── ...
├── scripts/
│   └── build-registry.js  # Validates and assembles registry.json
├── schema.json          # JSON Schema for validation
├── .github/workflows/
│   ├── validate.yml     # Runs on PRs touching templates/**
│   └── deploy.yml       # Runs on push to main, publishes to Pages
└── README.md

Adding a New Template

1. Fork and Branch

Fork the repository, clone your fork, and create a feature branch:

git checkout -b add-<template-name>

2. Create the Template Directory

mkdir templates/<template-name>/

Replace <template-name> with a lowercase slug using hyphens only (e.g., my-app, custom-service). This name becomes the template id and must match the folder name exactly.

3. Write the Four Required Files

arcane.json

Template metadata file. The id field must match the folder name, version must be valid semver, and tags must be a non-empty array of unique strings.

{
  "id": "my-app",
  "name": "My App",
  "description": "A clear description of what the template provides and its use case",
  "version": "1.0.0",
  "author": "Your Name or Organization",
  "tags": ["category1", "category2"]
}

Conventions:

  • id — lowercase slug with hyphens only, must match folder name
  • version — valid semver string (e.g., 1.0.0, 1.2.3-beta.1)
  • tags — non-empty array of unique strings; use descriptive categories like ai, llm, automation, workflow, low-code, database, monitoring
  • You do not need to include compose_url, env_url, documentation_url, or content_hash — those are auto-generated by the CI build script
  • Do not include $schema in template-level arcane.json

docker-compose.yml

A valid Docker Compose file (version 3.8 or later). Follow these conventions:

version: '3.8'

services:
  my-service:
    image: ghcr.io/org/image:tag
    container_name: my-service
    hostname: my-service
    ports:
      - "${PORT:-8080}:8080"
    volumes:
      - my_data:/app/data
    restart: unless-stopped
    environment:
      - API_KEY=${API_KEY:-}

volumes:
  my_data:
    name: my_data

Conventions:

  • File name is docker-compose.yml (not compose.yml)
  • Reference env vars using ${VAR:-default} syntax with secure defaults where possible
  • Use ${VAR:?} mandatory-variable syntax for values that must be user-provided and have no safe default (e.g., encryption keys)
  • Always declare volumes under a top-level volumes: key
  • Set restart: unless-stopped
  • Use - for environment variable prefixes, not = (e.g., - API_KEY=${API_KEY:-})

.env.example

Documents all environment variables the compose file consumes. Include defaults, format hints, and comments:

# ── Configuration ──────────────────────────────────────────────────────

# Host port for the service (default: 8080)
PORT=8080

# API key for external service (required — generate a random key)
API_KEY=your-api-key

Conventions:

  • Comment sections with dividers for readability
  • Every docker-compose.yml variable should appear here
  • Show default values where applicable
  • Mark required variables with comments like (required)

README.md

Documents what the template does and how to use it. Include at minimum:

  • One-line description of the template
  • Quick Start section with cp .env.example .env, env setup, and docker compose up -d
  • Environment variable reference table (Variable | Default | Description)
  • Any post-start verification (e.g., curl command for health check)

See the LiteLLM template as a reference example.

4. Validate Locally

Before pushing, run the validation script to catch errors early:

node scripts/build-registry.js --validate-only

This checks every template directory for:

  • Valid arcane.json JSON syntax
  • Required fields: id, name, description, version, author, tags
  • id matches the folder name and is a valid slug (^[a-z0-9-]+$)
  • version is valid semver
  • tags is a non-empty array of unique strings
  • Required files present: docker-compose.yml, .env.example, README.md
  • No duplicate id values across templates

5. Push and Open a PR

git add templates/<template-name>/
git commit -m "feat: add <template-name> template"
git push origin add-<template-name>

Open a pull request against the main branch. The Validate Templates workflow runs automatically on any PR that changes paths under templates/**.

6. After Merge

Once the PR merges to main, the Build and Deploy Registry workflow triggers:

  1. Runs node scripts/build-registry.js to generate registry.json
  2. Configures GitHub Pages
  3. Uploads the repository as a Pages artifact
  4. Deploys to GitHub Pages (~2 minutes total)

After deployment, the published registry is available at:

https://<org>.github.io/arcane-repo/registry.json

Replace <org> with the organization or owner name.

Modifying an Existing Template

Edit any of the four required files in the template's directory:

  • arcane.json — update metadata (version, description, tags)
  • docker-compose.yml — update service configuration
  • .env.example — add or update documented variables
  • README.md — update documentation

The content_hash is computed at build time from all four source files (sorted alphabetically: arcane.json, docker-compose.yml, .env.example, README.md), so any modification is automatically detected by CI. You do not need to update a hash manually.

Run local validation before pushing:

node scripts/build-registry.js --validate-only

Removing a Template

Delete the template directory:

rm -rf templates/<template-name>/
git add -A
git commit -m "feat: remove <template-name> template"

Commit and push. The next CI run skips the removed directory — no other files need updating. The registry.json is rebuilt from whatever directories remain.

CI Workflows

Validate Templates (validate.yml)

  • Triggers on: Pull requests to any branch, when files under templates/** change
  • Steps:
    1. Checkout code
    2. Set up Node.js 22
    3. Run node scripts/build-registry.js --validate-only
  • Failing a PR: If validation errors are found, the workflow exits with a non-zero code, marking the PR check as failed. Fix the reported issue and push again.

Build and Deploy Registry (deploy.yml)

  • Triggers on: Push to main that changes files under templates/**, schema.json, or scripts/build-registry.js
  • Steps:
    1. Checkout code
    2. Set up Node.js 22
    3. Run node scripts/build-registry.js (writes registry.json)
    4. Configure GitHub Pages
    5. Upload the repository as a Pages artifact
    6. Deploy to Pages

Schema

The registry schema lives at schema.json in the repository root. It defines two levels:

Registry (top-level)

Field Type Required Description
name string yes Registry name
description string yes Registry description
version semver yes Registry version
author string yes Registry author
url URI yes Repository URL
templates array yes Array of template objects (min 1 item)

Template

Field Type Required Description
id slug yes Unique identifier, matches folder name
name string yes Human-readable name
description string yes Detailed description
version semver yes Template version
author string yes Template author
compose_url URI yes Auto-generated raw GitHub URL to compose file
env_url URI yes Auto-generated raw GitHub URL to env example
documentation_url URI yes Auto-generated raw GitHub URL to README
content_hash SHA-256 hex yes Auto-generated hash of all source files
tags array yes Non-empty array of unique tags (letters, digits, hyphens)

Auto-Generated Fields

Template authors do not write these fields in arcane.json. The CI build script computes them:

  • compose_urlhttps://raw.githubusercontent.com/<owner>/<repo>/<branch>/templates/<id>/docker-compose.yml
  • env_urlhttps://raw.githubusercontent.com/<owner>/<repo>/<branch>/templates/<id>/.env.example
  • documentation_urlhttps://raw.githubusercontent.com/<owner>/<repo>/<branch>/templates/<id>/README.md
  • content_hash — SHA-256 of the concatenation of all four source files sorted alphabetically

The build script resolves the repository owner and name from GITHUB_REPOSITORY in CI, or from REPO_OWNER/REPO_NAME environment variables locally.

Validation Rules (from build-registry.js)

These are checked by the validation script and CI:

Rule Error level
templates/ directory must exist error
Each subdirectory must have arcane.json error
arcane.json must be valid JSON error
id must match folder name error
id must match slug pattern /^[a-z0-9-]+$/ error
version must be valid semver error
tags must be a non-empty array error
docker-compose.yml must exist error
.env.example must exist error
README.md must exist error
No duplicate template id values error
Duplicate tags (in same template) warning

License

By contributing, you agree that your contributions will be licensed under the MIT License (see LICENSE — if no LICENSE file exists, the repository defaults to MIT).