Files
tribes-plugin-aether/README.md
T

4.7 KiB

Tribes Plugin Template

Template for creating Tribes plugins.

Getting Started

  1. Click "Use this template" on GitHub to create your own repo
  2. Clone and rename:
git clone https://github.com/you/your-plugin.git
cd your-plugin
./scripts/rename.sh your_plugin YourPlugin
  1. Edit manifest.json — set description, capabilities, requirements
  2. Implement your plugin in lib/your_plugin/plugin.ex
  3. Run tests:
mix deps.get
mix test

Development

For local development alongside a Tribes checkout:

# Symlink into the host plugins directory once
cd /path/to/tribes
ln -s /path/to/your-plugin plugins/your_plugin

# Start Tribes dev server
iex --sname dev -S mix phx.server

Then edit the plugin in its own repo. In development, the host now watches symlinked external plugins and automatically:

  • runs mix compile for Elixir/HEEx or manifest changes
  • runs npm run build --prefix assets when assets/package.json is present
  • reloads the plugin in the running Tribes VM
  • triggers a Phoenix browser reload after the rebuild finishes

That means the normal loop is:

cd /path/to/your-plugin
mix deps.get
mix test

# in another terminal
cd /path/to/tribes
iex --sname dev -S mix phx.server

If your plugin does not need a custom frontend pipeline, you can skip assets/package.json and write browser-ready files directly under assets/js and assets/css; the host dev watcher will copy them into priv/static for you in development.

Project Structure

your_plugin/
├── manifest.json           # Plugin metadata (Nix build + runtime)
├── mix.exs                 # Dependencies
├── lib/
│   ├── your_plugin/
│   │   ├── plugin.ex       # Tribes.Plugin entry point
│   │   └── application.ex  # OTP supervision tree (optional)
│   └── your_plugin_web/
│       └── live/            # LiveView pages
├── assets/                 # JS/CSS (one bundle per plugin)
│   ├── package.json        # Optional build script used by dev + Guix packaging
│   └── package-lock.json   # Optional, recommended for reproducible builds
├── priv/
│   ├── static/             # Built assets for release
│   └── repo/migrations/    # Ecto migrations
└── test/

Manifest

manifest.json declares your plugin's identity and capabilities:

{
  "name": "your_plugin",
  "entry_module": "Tribes.Plugins.YourPlugin.Plugin",
  "host_api": "1",
  "otp_app": "your_plugin",
  "provides": ["some_capability@1"],
  "requires": ["ecto@1"],
  "enhances_with": ["inference@1"]
}
  • entry_module — must be Tribes.Plugins.*.Plugin
  • otp_app — required and must match name
  • provides — capabilities this plugin makes available
  • requires — hard dependencies (build fails without them)
  • enhances_with — optional dependencies (plugin degrades gracefully)

See the Plugin System docs for the full specification.

Plugin Data

If your plugin adds Ash resources that should replicate cluster-wide, use extensions: [AshNostrSync] on those resources and follow the host defaults:

  • persisted attributes sync by default unless explicitly excluded
  • synced resources should use one UUID primary key by default
  • AshNostrSync requires exactly one primary key; composite keys are not supported
  • synced resources get extension-managed deleted_at soft-delete support by default
  • destroy actions can use soft_delete() when they should tombstone rows
  • soft_delete?(false) is the opt-out if a synced resource should not use the default tombstone model

Keep resource-specific side effects explicit in actions. AshNostrSync owns the default tombstone/filter/projection behavior, but your plugin still decides which actions are semantic deletes and what else they should do.

Testing

Three test levels:

  • Unit tests (test/your_plugin/) — plugin logic in isolation
  • Manifest tests (test/your_plugin/manifest_test.exs) — manifest schema validation
  • Contract tests (test/contract_test.exs) — runtime spec matches manifest

Run all: mix test

For DB setup/migrations in local development, run:

mix tribes.migrate

This runs Tribes + Parrhesia + plugin migrations via Tribes.Release.

Building for Release

MIX_ENV=prod mix compile
npm run build --prefix assets

mkdir -p dist/your_plugin
cp -r _build/prod/lib/your_plugin/ebin dist/your_plugin/
cp -r priv dist/your_plugin/
cp manifest.json dist/your_plugin/

For Guix-based deployment, package your plugin in the guix-tribes channel and enable it from the node config.

Licence

TODO: Choose a licence.