Create your first plugin in 5 minutes
Start with the smallest working skeleton, then add settings UI, background work, and Store capabilities only when needed.
Package structure
Recommended structure
tynvr_module_example/
├── manifest.json
├── plugin.py
├── config.example.yml
├── README.md
└── assets/
└── plugin.css
Packaging rules
- Keep exactly one plugin root at ZIP top level.
manifest.jsonandplugin.pyare required.- Keep regular plugin ZIPs at or below 16 MB.
- Do not bundle large models, PyTorch, CUDA, or other heavy runtimes into a regular plugin ZIP.
manifest.json
Defines plugin identity, version, Settings UI, navigation mounts, and actions.
{
"id": "tynvr_module_example",
"name": "Example Plugin",
"version": "1.0.0",
"description": "Example Securex Nvr plugin",
"enabled": true,
"kind": "tynvr_core_module",
"module_id": "example",
"order": 50,
"config_apply": "hot",
"first_install_restart": true,
"navigation_user_toggle": true,
"navigation_default_visible": true,
"actions": [
{"id": "reload", "label": "Reload"}
],
"navigation": {
"key": "example",
"mount": "settings.sidebar.plugins",
"label": "Example Plugin",
"url": "/api/example/?embed=1",
"view": "iframe",
"order": 50,
"icon": "puzzle"
}
}idStable unique ID; tynvr_module_xxx is recommended.versionIncrement for every Store release.navigationDeclare navigation dynamically; provide a stable key explicitly.navigation_user_toggleLets users control sidebar visibility; upgrades must preserve the user choice.config_applyPrefer hot: ordinary settings apply immediately without restarting Frigate.first_install_restartA first install/code update may require one reload; ordinary config saves should not.actionsExplicit operations exposed to plugin management.plugin.py / class Plugin
Current Universal plugins derive from FrigatePlugin. Keep routes, config, background threads, and shutdown behavior inside the plugin instance.
from pathlib import Path
from typing import Any
from fastapi import APIRouter, Depends
from frigate.api.auth import require_role
from frigate.plugins.base import FrigatePlugin
class Plugin(FrigatePlugin):
def __init__(self, frigate_config: Any, plugin_dir: Path, stop_event=None):
super().__init__(frigate_config, plugin_dir, stop_event)
self._router = APIRouter(tags=["example"])
self._build_routes()
@property
def router(self):
return self._router
def _build_routes(self):
@self._router.get(
"/api/example/status",
dependencies=[Depends(require_role(["admin"]))],
)
def status():
return {"ok": True}
def get_public_config(self):
return {"enabled": True}
def update_config(self, payload):
return {"success": True}
def run_action(self, action, payload):
return {"success": action == "reload"}
def stop(self):
passConfiguration, state & user data
Permissions, secrets & sensitive actions
Least privilege: normal reads require authenticated access; config changes, tokens, model deployment, and hardware control require administrator permission.
Secret: keep full tokens, passwords, and keys server-side. UI should show only configured state or a masked value.
CSRF / POST: never use GET for state changes. Same-origin Frigate POST/PUT/PATCH/DELETE should explicitly send X-CSRF-TOKEN: 1 (and preferably X-CACHE-BYPASS: 1). Universal has a generic bridge, but plugins should still implement requests correctly.
Input validation: validate paths, URLs, command arguments, and upload names; never concatenate untrusted input directly into shell commands.
Background work, networking & recovery
Do not block requests
Run training, downloads, synchronization, and scans in background threads/workers. Expose status, progress, stop controls, and useful errors.
No blocking loopback HTTP in async routes
Do not call Frigate loopback APIs with blocking urllib/requests inside async FastAPI routes; this can deadlock the event loop until timeout. Use a threadpool/async client or reuse already available data.
Network operations must recover
Use bounded timeouts, backoff after failures, chunking plus checksums for large files, and idempotent retry behavior where possible.
Logs & runtimes must be maintainable
Provide log-clear controls using in-place truncation so active Worker/training processes continue. Keep heavy runtimes and artifacts outside plugin code so upgrades replace only plugin code.
Official AI plugin reference
Current official baselines that demonstrate the expected platform contracts.
Securex AI Cloud v1.1.7
- Shadow A/B compares production and candidate models on the same frame without switching the production detector.
- Explore manual review submits on Yes/No; “Submitted” appears only after Store confirms correct/incorrect.
- Manual reviews use sample_reason=manual and appear as Correct/Incorrect · Manual review in Images.
- Frigate event/snapshot reads for manual submission run in a threadpool to avoid async loopback deadlocks.
Securex AI Training Worker v1.0.11
- Training runtime is separated from plugin code; plugin upgrades/restarts preserve the environment and artifacts.
- Reattaches to running jobs instead of restarting training.
- Installer and Worker logs can be truncated in place without stopping active processes.
- Embedded UI follows the Frigate theme and state-changing operations follow Frigate CSRF rules.
Simplified / Traditional / English & responsive UI
Plugin names, descriptions, buttons, errors, and settings fields should be complete in all three languages—not just page titles.
- English strings are often longer; buttons and cards must not depend on Chinese-only fixed widths.
- Test at 1366px, tablet widths, and narrow embedded Settings views.
- Wrap or truncate logs, long IDs, and URLs so they cannot break the layout.
Versioning, upgrades & uninstall
When upgrading plugin code, preserve user config, sidebar visibility preferences, and persistent data; ordinary config saves should hot-apply. During uninstall, distinguish removing plugin code from deleting user data; destructive cleanup must be explicit.
Release checklist
ZIP structure is correctmanifest.json / plugin.py
Install and enable workFresh install test
Restart recovery worksState survives Frigate restart
Upgrade preserves dataconfig / db / status
No stale navigation after uninstallDynamic navigation verified
All three languages complete简 / 繁 / EN
No narrow-screen overflow1366 / tablet / embed
Network failures recovertimeout / retry / resume
No secret leakageBrowser and log audit
State-changing requests pass CSRFX-CSRF-TOKEN / POST / PUT / DELETE
Hot-save does not restart Frigateconfig_apply=hot
Upgrade preserves sidebar preferencenavigation_visible
No blocking loopback in async routesthreadpool / async client
Version matches Store metadatamanifest / catalog / ZIP
Plugin ready?
Upload the ZIP after completing the checklist. Store review focuses on security, compatibility, upgrade retention, localization, and UI completeness.