Skip to main content

Managed Marketplace App

Goal

Build a Qefro Marketplace App as metadata, publish it, install it into a workspace, and let Qefro Runtime execute UI, entities, storage, Business Flows, events, CRM, and Automation.

You do not write a /qefro server for this path.

Reference packages:

PackageApp idNotes
restaurant-pro-runtimerestaurant-pro-runtimeReservations + menu, hosting: runtime
real-estate-runtimereal-estate-runtimeProperties / leads / viewings — same model
shopify-runtimeshopify-runtimeProducts / customers / orders via generic Runtime HTTP

Collection: qefro-marketplace-apps. HTTP surfaces, Hub email OTP, ownership: HTTP tools.

SDK is a different story

To connect Focus ERP, Yaaz, or another customer system, use External SDK Connection. That is not a Marketplace App.

Prerequisites

  • qefro CLI (QEFRO_SOLUTION_URL, tenant headers, publisher credentials)
  • Platform admin id listed in solution-service QEFRO_PLATFORM_ADMIN_IDS to publish

Node.js and Docker are not required for hosting: runtime.

Architecture

Developer

App metadata (manifest · entities · workflows · ui)

qefro app validate / package / publish

Marketplace / catalog

workspace installation

Qefro Runtime
├── UI (dashboards, tables, forms, widgets)
├── Entities + managed storage
├── FlowRunner (Business Flows)
├── Business Events
└── CRM + Automation hosts

Comparison: Runtime vs SDK.

Create

qefro app init restaurant-pro --name "Restaurant Pro"
cd restaurant-pro

Typical package layout (from the CLI and restaurant-pro-runtime):

restaurant-pro/
├── manifest.yaml
├── entities/
│ └── … # required for hosting: runtime
├── workflows/
└── ui/
├── theme.yaml
├── navigation.yaml
├── pages.yaml
├── layouts.yaml
├── widgets.yaml
└── sources.yaml

The polished reference lives at apps/restaurant-pro-runtime (app id restaurant-pro-runtime).

Manifest (actual fields)

From restaurant-pro-runtime. Only document fields that exist there:

FieldExampleRole
idrestaurant-pro-runtimeSolution id
nameRestaurant ProDisplay name
version0.1.0Package version
hostingruntimeQefro Runtime executes metadata
descriptionCatalog copy
category / tagshospitality / …Discovery
channelswidget, whatsappChannel support
entitiestable, reservation, menu_itemDomain schemas under entities/
flowscreate-reservationWorkflow ids
eventsreservation.createdBusiness events
permissionsstorage.read, workflow.execute, …Install permissions
capabilitiesruntime.query, storage.write, …Declared platform capabilities
triggersintent → workflowChannel trigger map
conversation_slotscovers, date, …Chat slot harvest (ADR-006)
uiname, logo, iconStaff UI branding

hosting: runtime must not declare an external /qefro endpoint.

Entities

entities/reservation.yaml (excerpt)
id: reservation
name: Reservation
allocate_code:
prefix: R-
start: 1001
fields:
- name: guest_name
type: string
required: true
- name: covers
type: integer
required: true
- name: date
type: date
required: true
- name: person_id
type: person
ref_entity: person

Storage is Qefro-managed. There is no direct database access. person fields bind to the platform Person CRM.

Workflow tools call Runtime capabilities:

- id: create
type: tool
tool: entity.reservation.create
execution: runtime

UI

Runtime renders navigation, dashboards, tables, forms, and host pages:

# ui/pages.yaml (excerpt)
- id: contacts
title: Contacts
host: contacts
- id: automations
title: Automations
host: automations
# ui/sources.yaml
- id: reservations
type: entity
target: reservation

Configure permissions

permissions:
- workflow.execute
- storage.read
- storage.write
- storage.update
- storage.delete

Validate, package, install

qefro app validate .
qefro app package .
# platform admin:
qefro publish .
# tenant:
qefro app install restaurant-pro-runtime --version 0.1.0

CLI env (from qefro-cli):

  • QEFRO_SOLUTION_URL (default http://127.0.0.1:8105)
  • QEFRO_TENANT_ID, QEFRO_ORGANIZATION_ID
  • QEFRO_PUBLISHER_ID (must be a platform admin)
  • QEFRO_SIGNING_KEY_HEX or QEFRO_KEYS_FILE
  • QEFRO_INTERNAL_BEARER when service auth is enforced

Tenants install; they cannot publish.

Runtime execution

Solution Installation

solution-service (metadata install, no /qefro binding)

Qefro Runtime
├── entity tools (entity.reservation.create, …)
├── FlowRunner (ask → tool → complete)
├── managed storage
└── portal UI + Contacts + Automations

On install the platform:

  1. Accepts the published package
  2. Validates / signs the registry artifact
  3. Records the tenant install (hosting: runtime)
  4. Registers workflows with FlowRunner
  5. Persists the UI bundle
  6. Serves entity data from managed storage

Business events and automation

ConceptRoleExample
ToolRuntime capabilityentity.reservation.create
EventFact on the busreservation.created
FlowMetadata → FlowRunnercreate-reservation
AutomationCRM Automation hostreservation.created → Send WhatsApp

See Events.

Test

validate → package → publish → install → open UI → run create-reservation

Walk the reference: restaurant-pro-runtime.

Production considerations

  • Keep entity field names stable across versions
  • Treat person refs as platform CRM, not app-local contacts
  • Never call other solutions’ tools directly — use Organization workflows or CRM Automation

Troubleshoot

SymptomCheck
Validate failsentities/ present? hosting: runtime? No endpoint?
Install failsManifest validation; permissions
Empty tablesEntity source type: entity / target matches entity id
Flow never startstriggers + conversation_slots; workflow id in flows:

More: troubleshooting.md, marketplace-publishing.md.