Repository navigation
Creating an extension
Host API 1 extensions are data, not programs. You write a folder and a manifest; Ordryn renders the UI and (for hooks) POSTs JSON.
my-extension/
manifest.json # required
README.md # recommended (install notes for operators)
icon.svg # optional
panel.html # optional sandboxed UI (set manifest `ui`)
Rules:
- The folder name must equal
manifest.id. - Drop the folder into Ordryn’s extensions directory (default
data/extensions/). Hidden directories (names starting with.) are ignored. - Restart Ordryn after adding or changing files on disk. Manifests are not hot-reloaded.
- One bad extension fails that folder only; others still load. Duplicate ids disable both copies.
Override the scan path with EXTENSIONS_DIR (legacy alias: MODS_DIR).
- Choose an
id: lowercase letters, digits, and hyphens; must start with a letter; 2–33 characters (^[a-z][a-z0-9-]{1,32}$). Examples:severity,fields-demo. - Create a directory named exactly that
id. - Add
manifest.jsonwith the required identity fields, plusfields(custom task fields),hooks+delivery(outbound notifications),ui(sandboxed panel), or a combination. See Manifest. - Copy the directory to
data/extensions/<id>on the Ordryn server. - Restart Ordryn. Check server logs for
extensions: loaded <id>orextensions: failed …. - Site admin: Admin → Extensions → enable the extension → Save.
- Project owner: Project settings → Extensions → enable it for that project → Save. Configure secrets, triggers, and templates there if the extension has them.
Both site and project enablement are required for project-scoped behavior. Personal tasks (no project) never get custom fields. Member destinations (“Notify me”) use settings with "scope": "member" and are configured in Settings → Integrations, not on the project Extensions tab. Member destinations are blocked on kanban team boards (team webhook only).
{
"id": "severity",
"name": "Severity",
"version": "1.0.0",
"host_api": 1,
"description": "Adds a severity field to project tasks."
}That manifest loads, but it does nothing until you add fields, hooks, and/or ui.
See Custom fields and the severity example.
{
"id": "severity",
"name": "Severity",
"version": "1.0.0",
"host_api": 1,
"fields": [
{
"key": "level",
"type": "enum",
"label": "Severity",
"show_on": ["sidebar", "kanban"],
"options": [
{ "value": "low", "label": "Low" },
{ "value": "high", "label": "High" }
]
}
]
}See Hooks, Delivery, and the webhook example.
{
"id": "webhook",
"name": "Generic webhook",
"version": "1.0.0",
"host_api": 1,
"hooks": [
{ "on": "task.created" },
{ "on": "task.updated" }
],
"delivery": {
"type": "http.webhook",
"url_from": "webhook_url",
"format": "json"
},
"settings": [
{
"key": "webhook_url",
"type": "secret",
"label": "Webhook URL",
"required": true,
"scope": "project"
}
],
"templates": {
"task.created": "New task {name} in {project} ({url})"
}
}| Layer | Who | What |
|---|---|---|
| Site | Admin | Admin → Extensions. Toggle Enable, Save. Failed extensions cannot be configured. Site-scoped secrets, triggers, and templates live here. |
| Project | Project owner only | Project settings → Extensions. Enable, secrets, triggers, templates. Blocked until the site toggle is on. |
| Member | Signed-in user | Settings → Integrations / Notify me, when the manifest has scope: member settings. Not used on kanban project tasks. |
Editors cannot manage extensions.
An extension appears on the project Extensions tab if it has any project-scoped setting, any member-scoped setting, any custom fields, or a ui panel. Site-only hook extensions such as join-requests do not appear there.
| Variable | Purpose |
|---|---|
EXTENSIONS_DIR |
Scan path for extension folders. Default data/extensions/. |
MODS_DIR |
Legacy alias for EXTENSIONS_DIR. |
PUBLIC_URL |
Public origin used to build {url} in templates (for example https://todo.example.com). |
BASE_PATH |
Used for {url} when it is already a URL-like value and PUBLIC_URL is unset. |
Set PUBLIC_URL in Ordryn’s .env so {url} is a clickable task link ({PUBLIC_URL}/tasks/{id}). For join.* events, {url} points at Admin → Join requests when PUBLIC_URL is set.
- Folder name equals
id -
id,name,version,host_apipresent (host_apiis1) - Field / setting keys are unique and match the key pattern
- Enums have
options; non-enums do not - Hook extensions declare
hooks,delivery.type, and a matching settings key forurl_from -
http.webhooksetsformatif you needjsonorcontent(otherwise you get{"text": "…"}) - Project-facing settings use
"scope": "project"; “Notify me” settings use"scope": "member" -
ui, if set, is a relative HTML path that exists in the folder -
permissions/actionsare only the known values (see Callbacks and inbound) - Copied to
data/extensions/<id>and Ordryn restarted - Enabled in Admin, then enabled (and configured) on a project