This is a plugin template for extending IvoryOS with standalone pages. It demonstrates how to structure a plugin using Flask's Blueprint system and integrate with IvoryOS.
Clone https://github.com/ivoryos-ai/IvoryOS-plugin-template and prompt with your choice of coding agent.
Example Prompts:
Build from scratch: "I want to build a plugin page for ivoryOS to watch a stream from my webcam, can you help write it for me?"
Build with existing html: "Here is my html page @your_actual.html, can you convert it to fit the ivoryOS plugin format?"
- Uses Flask's
Blueprintto modularize the plugin. - Includes a WebSocket (
SocketIO) integration. - Includes hardware access for components that are initialized for IvoryOS
- Can function as a standalone page or as part of the IvoryOS ecosystem.
ivoryos_plugin/ ├── templates/ │ ├── example.html # Template file for the plugin ├── __init__.py ├── plugin.py # Main plugin file README.rst # README file (optional)
git clone https://gitlab.com/heingroup/ivoryos-plugin-template pip install ivoryos
Each plugin must define an entry point under ivoryos.plugins so that it can be discovered by IvoryOS.
from ivoryos_plugin.plugin import plugin
ivoryos.run(__name__, blueprint_plugins=plugin)- The plugin must define a
mainfunction inside a FlaskBlueprint. This function serves as the main route of the plugin (quick access in the navigation panel).
from flask import render_template, Blueprint, current_app
import os
plugin = Blueprint("plugin", __name__, template_folder=os.path.join(os.path.dirname(__file__), "templates"))
@plugin.route('/')
def main():
base_exists = "base.html" in current_app.jinja_loader.list_templates()
return render_template('example.html', base_exists=base_exists)- Import
deckfromglobal_configif accessing hardware components that are initialized forIvoryOS
# [access hardware] Comment back this block if need access to control hardware
# to get the component, user global_config.deck.hardware_name (e.g. global_config.deck.balance)
from ivoryos.utils.global_config import GlobalConfig
global_config = GlobalConfig()Keynotes:
- The Blueprint name need to be unique (e.g.
pluginas inBlueprint("plugin", __name__, template_folder=...))
plugin = Blueprint("plugin", __name__, template_folder=os.path.join(os.path.dirname(__file__), "templates"))- Include
main()as the main route for the plugin.
This plugin can also run as a standalone Flask app by executing: Example: run with Flask
if __name__ == '__main__':
app = Flask(__name__)
app.register_blueprint(plugin)
app.run()Example: run with websocket
if __name__ == '__main__':
app = Flask(__name__)
app.register_blueprint(plugin)
socketio = SocketIO(app)
init_socketio(socketio)
socketio.run(app, debug=True, allow_unsafe_werkzeug=True)This initializes the Flask app and runs the plugin Blueprint independently.
