Build your first app
The maturity test for Qefro is not another internal vertical. It is:
qefro create-app warehouse-pro
→ customize
→ publish
→ install
→ works
This guide is that loop, written so you can finish it without Slack.
What you will build
qefro create-app scaffolds a full booking starter: managed storage,
Customer Hub (optional), Marketing metadata, Organization capability ids,
WhatsApp booking bridge, onboarding, and a staff dashboard.
Rename the domain nouns to your vertical (warehouse, clinic, salon, …). Keep the platform capabilities — that is the point.
| Reference examples | Path |
|---|---|
| Restaurant Pro | qefro-plugin-platform/docs/examples/restaurant-pro |
| Clinic Pro | …/clinic-pro |
| Salon Pro | …/salon-pro |
| Finance Pro | …/finance-pro |
Prerequisites
-
qefroCLI on yourPATH
Build from the platform checkout if you do not have a release binary:cd qefro-plugin-platform/services/qefro-clicargo install --path .For
create-app, either run the CLI from a tree that containstemplates/sdk-app-starter, or set:export QEFRO_APP_TEMPLATE=/absolute/path/to/templates/sdk-app-starter -
Node.js 18+ (starter is
@qefro-ai/backend). -
Publish credentials (only for the publish step — see Publishing):
Env Purpose QEFRO_SOLUTION_URLsolution-service base URL QEFRO_PUBLISHER_IDUUID in QEFRO_PLATFORM_ADMIN_IDSQEFRO_SIGNING_KEY_HEXEd25519 private key (32-byte hex) matching catalog trust anchors QEFRO_TENANT_ID/QEFRO_ORGANIZATION_IDFor qefro solution installQEFRO_INTERNAL_BEARERWhen service auth is enforce
Today, catalog publish is platform-admin only. Tenant admins install;
they do not publish. Ask your Qefro contact for a publisher UUID + signing
key, or use a local stack with QEFRO_PUBLISH_OPEN=true. See
Marketplace.
Step 1 — Scaffold
qefro create-app warehouse-pro --name "Warehouse Pro"
cd warehouse-pro
npm install
npm run dev
# → listening on http://0.0.0.0:8080/qefro
Useful flags:
qefro create-app warehouse-pro --hosting managed # default
qefro create-app warehouse-pro --hosting external --endpoint https://api.example.com/qefro
qefro create-app scratch --minimal # hello-only stub
Generated layout:
warehouse-pro/
├── manifest.yaml # id, version, tools, onboarding, settings
├── src/index.js # required SDK app (/qefro)
├── package.json
├── Dockerfile
├── workflows/ # optional orchestration → app tools
├── prompts/
├── booking/ # static WhatsApp bridge (store-nothing)
├── onboarding/
├── ui/ # staff dashboard
└── assets/
Step 2 — Make it your domain
You do not need a new ADR. Change nouns and collections:
- Tools —
__TOOL_PREFIX__becomeswarehouseautomatically from the app id. Rename handlers (createAppointment→createPick, …) insrc/index.jsandmanifest.yamltools:. - Storage — pick collections that match the domain
(
bins,skus,picksinstead ofstaff/services/appointments). Persist only viactx.storage.*. - Workflows / prompts / UI — update YAML to call your new tool ids.
- Marketing / Organization — keep
app.marketingandapp.organizationregistrations; change opaque ids and labels to fit the domain (stock_low,fulfillment_requested, …). Never put another app's name in an id (finance.approveis forbidden).
Rules that never change:
- Business logic only in the SDK process on
/qefro. - Workflows and UI call app tools, never
storage/*. - WhatsApp number comes from the workspace channel, not install settings.
- Same package version for every tenant.
Step 3 — Validate locally
qefro dev .
This assembles the package (including onboarding/*.yaml) and checks
forbidden storage targets. Fix any errors before publish.
Smoke the app:
curl -s http://127.0.0.1:8080/qefro # expect signed protocol responses via runtime in real installs
For a full local stack, run solution-service + runtime + storage per Managed apps.
Step 4 — Build and publish
export QEFRO_SOLUTION_URL=https://… # or http://127.0.0.1:8105
export QEFRO_PUBLISHER_ID=<admin-uuid>
export QEFRO_SIGNING_KEY_HEX=<32-byte-hex>
# Bump version in manifest.yaml when re-publishing
qefro solution build .
qefro solution publish .
# alias: qefro publish .
Success returns a 201 with name, version, and checksum.
Details: Publishing.
Managed hosting: the platform must run your container image at the
manifest endpoint (e.g. http://warehouse-pro:8080). Ship a Dockerfile
(the starter includes one). Coordinate image build/tag with ops until
partner self-serve image push exists.
External hosting: deploy /qefro yourself, then:
qefro register --endpoint https://your-host/qefro --solution warehouse-pro
Step 5 — Install
From the Admin Console (Applications → Marketplace → Install), or CLI:
export QEFRO_TENANT_ID=…
export QEFRO_ORGANIZATION_ID=…
# workspace context as required by your deployment
qefro solution install warehouse-pro --version 0.1.0
Then in the portal:
- Open the workspace → Installed solutions → Configure (
business_name, brand). - Settings → Customer channels → connect WhatsApp (one active number per workspace).
- Complete onboarding (WhatsApp, business name, optional demo seed, booking link).
- Open the solution UI and create a real record (skip demo seed for production).
Tenant install docs: Installation.
Catalog discovery: Marketplace.
Acceptance checklist
You are done when all of these pass without platform-team intervention beyond provisioned credentials:
-
qefro create-app warehouse-proproduced a runnable tree -
npm run devserves/qefro -
qefro solution build .succeeds (onboarding packaged) -
qefro solution publish .returns 201 - Install appears in Marketplace / Installed
- Staff UI loads and writes through app tools →
ctx.storage - WhatsApp or widget can complete one domain action end-to-end
Next
| Guide | When you need it |
|---|---|
| Publishing | Signing, versions, yank |
| Marketplace | How tenants find and install |
| Organization workflows | Cross-app events/tasks |
| Customer Hub | Shared customer identity |
| Marketing | Audiences and WhatsApp campaigns |
| Troubleshooting | Common failures |
Engineering deep-dive: Building SDK-based solutions.