The base branch tribes/tribes-plugin-template:master has new changes
self ee7d0ac29f dev: add en_GB locale archive to devenv
Provide a Nix glibc locale archive with en_GB.UTF-8 so tools inside the devenv shell inherit a valid UTF-8 locale.
2026-06-02 00:01:42 +02:00
2026-03-25 12:42:19 +01:00
2026-05-27 19:05:39 +02:00
2026-05-27 19:05:39 +02:00
2026-06-02 00:01:42 +02:00
2026-06-02 00:01:42 +02:00
2026-04-26 22:00:17 +02:00
2026-04-26 22:00:17 +02:00
2026-03-25 12:42:19 +01:00
2026-05-14 19:00:12 +02:00
2026-05-27 19:05:39 +02:00
2026-05-24 16:26:29 +02:00
2026-05-27 19:05:39 +02:00
2026-05-27 19:05:39 +02:00
2026-05-27 19:05:39 +02:00

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 validation and tests:
mix deps.get
mix tribes.plugin.validate
scripts/plugin test

If you are using the shared tribes devenv, run through the local helper instead:

devenv shell -- plugin validate
devenv shell -- plugin test
devenv shell -- plugin precommit

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 edit/compile loop is:

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

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

Inside the plugin repo's devenv shell, the plugin helper forwards to the host devenv automatically:

plugin validate
plugin test
plugin precommit

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
├── config/                 # Host-backed test config
├── 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
├── scripts/
│   ├── plugin             # Shared devenv/non-devenv test wrapper
│   └── rename.sh
└── test/

Manifest

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

{
  "id": "org.example.plugins.your-plugin",
  "slug": "your_plugin",
  "display_name": "Your Plugin",
  "entry_module": "TribeOne.TribesPlugin.YourPlugin.Plugin",
  "host_api": "1",
  "otp_app": "your_plugin",
  "provides": ["some_capability@1"],
  "requires": ["org.tribe-one.caps.ui@1"],
  "enhances_with": ["org.tribe-one.caps.inference@1"]
}
  • entry_module — must be <Owner>.<Plugin>.Plugin
  • otp_app — required, vendor-prefixed Mix application 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.

The default template assumes the plugin owns a top-level page such as /your_plugin and any views beneath it.

Sender renders its LiveView pages inside the host chrome through Tribes.Plugin.Layouts.app, so org.tribe-one.caps.ui@1 is a hard runtime dependency.

LiveView Hooks

External plugins register browser hooks from JS bundles listed in manifest.json assets.global_js:

window.TribesPluginHooks = window.TribesPluginHooks || {};
window.TribesPluginHooks.SenderHook = {
  mounted() {}
};

The host loads plugin JS before connecting LiveSocket and does not auto-import external plugin phoenix-colocated/<otp_app> modules into its app.js bundle.

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

The template starts with two host-backed test layers:

  • Contract tests (test/your_plugin/plugin_contract_test.exs) — manifest and runtime spec stay aligned
  • Page tests (test/your_plugin/home_page_test.exs) — the plugin renders through the real host page pipeline

Run them with:

mix tribes.plugin.validate
scripts/plugin test

Use plugin test / plugin precommit for host-backed tests. The helper invokes Mix with the host database/services and host plugin-manager paths, including built-in providers such as tribes_ui. Raw mix test in a plugin checkout is guarded and prints this guidance; mix raw_test / mix raw_precommit are available only for unusual manual debugging when you have set the same host environment yourself.

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.

S
Description
Tribes Broadcast Transmitter Plugin
Readme 1.1 MiB
Languages
Elixir 94.7%
Nix 2.4%
Shell 1.6%
TypeScript 1.1%
CSS 0.2%