Custom Components Source section: `https://appsudo.com/doc#custom-components` Purpose - A custom component is a reusable unit of UI plus logic that can be embedded as a custom ASXML tag. - It subclasses `Component`, not `App`. - Consumer apps declare dependencies in `components.yaml`. Folder model ```text starrating/ ├── starrating.py ├── icon.png ├── metadata.json ├── data/ ├── res/ └── view/ └── starrating.asxml ``` Important metadata rule - The `scope` field is optional. The framework auto-detects it for you, so you don't need to specify it manually. Component folders are looked up by their directory name from the consumer app's `components.yaml`. - The component folder name must follow the same naming rules as apps: all lowercase with no spaces, hyphens, underscores, or special characters. Examples from the docs Consumer-side XML: ```xml ``` Component metadata: ```json { "icon": "icon.png", "scope": "thirdparty", "displayName": "Star Rating", "description": "Reusable star-based rating widget." } ``` Component implementation: ```python from appsudo import Component from components.view import ViewInflater class StarRatingData: def __init__(self, component_path): self.component_path = component_path self.stars = [] class StarRatingComponent(Component): def __init__(self, component_path): Component.__init__(self, "StarRating", component_path) self.inflater = ViewInflater(self) self.data = StarRatingData(component_path) self.max = 5 self.current_value = 0 self.label = "" self.on_rate = None self.ui_view = self.inflater.inflate("starrating", self.data) def on_star_click(self, element, star): self.current_value = star.get("index") if callable(self.on_rate): self.on_rate(self, self.current_value) ``` `components.yaml`: ```yaml components: - name: starrating version: 1.0.0 ``` Embedding in an app view: ```xml