Getting started

App Manifest

Every Saaslivery app is defined by a manifest.py file. The manifest declares the app's identity, dependencies, events, and pricing. The platform uses it for installation, dependency resolution, marketplace listing, and runtime enforcement.


Full example

manifest = {
    # Required
    "name": "Invoices",
    "slug": "invoices",
    "publisher": "acme",
    "version": "1.0.0",
    "description": "Invoice management and payment tracking",

    # Dependencies
    "requires": ["core.people"],
    "enhances": ["core.calendar"],

    # Events
    "events": {
        "emits": [
            "ext.acme.invoices.invoice.created",
            "ext.acme.invoices.invoice.paid",
        ],
        "listens": [
            "core.people.member.created",
            "core.people.member.deactivated",
        ],
    },

    # Entry point
    "plugin": "plugins.acme_invoices.plugin.InvoicesPlugin",

    # PWA
    "pwa": {
        "theme_color": "#1a1a2e",
        "background_color": "#ffffff",
    },

    # Pricing
    "pricing": {
        "model": "usage",
        "trial_days": 14,
        "dimensions": [
            {
                "type": "seat",
                "label": "User access",
                "unit_price": 4.00,
                "currency": "USD",
                "period": "month",
                "free_allowance": 5,
            },
            {
                "type": "document",
                "label": "Invoices created",
                "unit_price": 0.50,
                "currency": "USD",
                "free_allowance": 10,
            },
        ],
    },

    # Marketplace
    "category": "finance",
    "tags": ["invoicing", "billing", "payments"],
    "homepage": "https://acme.dev/invoices",
    "support": "https://acme.dev/support",
}

Required fields

Field Type Description
name str Human-readable name. Max 50 characters.
slug str URL-safe identifier; becomes the /app/{slug}/ path prefix and the API namespace. Lowercase, alphanumeric + hyphens. Globally unique.
publisher str Publisher ID. microcessor is reserved for core apps.
version str Semantic versioning: MAJOR.MINOR.PATCH
description str One-line description. Max 200 characters.
plugin str Dotted Python path to the plugin class.

Slug rules

  • Lowercase alphanumeric and hyphens only: [a-z0-9-]+
  • Must start with a letter: ^[a-z]
  • Max 30 characters
  • Cannot collide with reserved platform names, including www, api, apps, admin, auth, mail, my, rtc, mx, and saaslivery
  • Cannot collide with an existing app's slug

Dependencies

Field Type Description
requires list[str] Hard dependencies — installation fails without them. Format: core.{slug} or ext.{publisher}.{slug}
enhances list[str] Soft dependencies — app works without them but gains features when present

Checking soft dependencies at runtime

if req.app.has_app("core.calendar"):
    await req.app.emit("ext.acme.invoices.calendar.event_requested", {...})

Events

Field Type Description
events.emits list[str] Events this app will emit. Enforced at runtime — undeclared events are rejected.
events.listens list[str] Events this app subscribes to. Used for dependency resolution.

Naming convention

  • Core apps: core.{app}.{resource}.{action}
  • Third-party: ext.{publisher}.{app}.{resource}.{action}

See Event System for the full spec.


PWA

Field Type Description
pwa.theme_color str Hex color for the PWA theme
pwa.background_color str Hex color for the PWA splash screen

The platform auto-generates the PWA manifest.json for your app from these values.


Pricing

Field Type Description
pricing.model str "free" or "usage"
pricing.trial_days int Optional free trial period in days
pricing.dimensions list[dict] Billing dimensions (see below)

Dimension schema

Field Type Required Description
type str yes seat, minute, document, storage, message, active_resource, or flat
label str yes Shown on invoices
description str no What counts as a unit
unit_price float yes Price per unit
currency str yes ISO 4217 code (e.g., USD)
period str for recurring month or year — required for seat, storage, active_resource, flat
free_allowance int/float no Units included free per workspace per period

Free app shorthand

"pricing": "free"

See Pricing & Billing for the full billing spec.


Marketplace fields

Field Type Description
category str productivity, communication, finance, hr, development, analytics, or other
tags list[str] Searchable tags. Max 10.
homepage str Publisher's homepage for this app
support str Support URL or email

Search integration

Apps can declare searchable types for the MicroSearch command palette:

"searchables": [
    {"type": "task",     "label": "Tasks",     "icon": "assignment",  "color": "#F39C12"},
    {"type": "board",    "label": "Boards",    "icon": "view_kanban", "color": "#3B82F6"},
]

Each searchable requires a matching search API endpoint.


Core app manifest example

manifest = {
    "name": "People",
    "slug": "people",
    "publisher": "microcessor",
    "version": "1.0.0",
    "description": "Shared directory, org chart, and identity provider",
    "requires": [],
    "enhances": [],
    "events": {
        "emits": [
            "core.people.member.created",
            "core.people.member.updated",
            "core.people.member.deactivated",
        ],
        "listens": [],
    },
    "category": "hr",
    "tags": ["directory", "org-chart", "identity"],
    "pricing": "free",
}

Plugin class contract

class MyPlugin:
    def install(self, host_app):
        """Called during installation. Mount the app and register listeners."""
        host_app.mount(self.app, isolated=False)
        host_app.on("core.people.member.created", self.on_member_created)

    def uninstall(self, host_app):       # optional
        """Called during removal. Clean up listeners and resources."""

    def upgrade(self, host_app, from_version):  # optional
        """Called when upgrading. Run migrations."""

Route registration itself lives in plugin.py on the module-level app object: UI routes on the wildcard subdomain under /app/{slug}/, API routes on the api subdomain. See Architecture & routing.


Version rules

Change Bump
Breaking changes to event payloads Major
New events or payload fields Minor
Bug fixes Patch