Queek docs

Build an app

From an empty folder to a submitted app. Requirements, capability check, develop on a dev store, host, deploy, submit.

By the end of this page you will have an app running on your own dev store, deployed as a version, and submitted for review.

Check your Node.js version first

Run node -v. The tools need 22.14 or later. Older 22.x releases install the packages and then fail further along, so a version check now saves a confusing error later.

Requirements

RequirementDetail
Node.js22.14 or later
Queek accountCreate one
Developer accessDashboard → account menu → Developer → accept the Developer Terms
Dev storeOne your developer account owns (Developers → Dev stores). queek app dev offers to create the first one. See Dev stores.
Queek CLI0.16 or later: npm install -g @usequeek/cli, or prefix each queek command with npx -y @usequeek/cli. The starter does not install it for you.
HostingOnly to go live. See Host the app

The first command that needs authorisation opens your browser to approve sign-in. Without a browser, pass --no-browser to sign in with a device code. Keep secrets out of queek.app.toml and source control; the CLI writes the registration secret to .queek/.env.local, which is gitignored.

Check the platform can do it

Find the capabilities your app needs in App capabilities before designing anything. The overview also lists example apps and the capabilities they use. The same data is available as capabilities.json and as plain text in llms.txt, which gives the verdict, limits and workaround for every capability in one document. Read it first when an AI agent builds the app. Each example use case in the overview, such as the translation app, lists the capabilities it is built from and the ones to check before you start.

StatusMeaning
AvailableWorks as described.
Partly availableRead what is missing and the workaround first.
Not yet availableNot offered yet. Narrow the feature, use a listed workaround, or leave it out.
Not offered by designQueek does not offer it on purpose. The entry says why and what to use instead.

Do not infer support from an API name, and do not call undocumented endpoints.

  1. App manifest
  2. App SDK
  3. Embedded apps and the dashboard bridge
  4. Merchant API: overview, authentication, scopes, idempotency and rate limits, safe integrations, errors
  5. Webhooks
  6. merchant.json, the typed spec
  7. The page for your use case, for example Translate store content for a translation app, or Dev stores for test data

Build with an AI coding agent

Install the AI toolkit skills, then give the agent this prompt:

Build this Queek app: [what it does and who it is for].
Start at /docs/apps/build-an-app and follow it in order.
Check the capabilities document (capabilities/llms.txt) first. Build only
what it marks supported, or partial within its limits and workaround.
Learn only from the public docs. Never invent endpoints or fields.
Request the smallest Merchant API scopes that cover the task.
Send Idempotency-Key on writes. Verify webhook signatures.
Check `node -v` is 22.14 or later before installing anything.
Develop with `queek app dev`. If the app touches shopper-facing content,
use a separate development app: queek app dev -c development.
Read /docs/apps/embedded-apps before building the embedded page.
Record every docs gap in DOCS-GAPS.md.
Never ask the developer to paste secrets.

1. Scaffold a project

npm create @usequeek/app my-app
cd my-app

This creates the project and queek.app.toml. queek app init my-app is equivalent.

2. Configure access

Edit queek.app.toml: set the name and slug, list only the scopes the app needs under [access], and set the install and uninstall URLs. Add webhook topics and extensions only if the app uses them. See the manifest reference.

3. Run on a dev store

queek app dev

This is the whole development loop in one command, and it works on a brand-new slug:

  1. Registers the app. A slug Queek has not seen yet is registered first, the way queek app deploy --no-release registers it: a development version, nothing served. The signing secret goes to .queek/.env.local and is never printed.
  2. Picks the dev store. See Dev stores. With none, it offers to create one with test data.
  3. Starts a tunnel so Queek can reach your machine, and waits for it. See The tunnel.
  4. Registers a development build with the tunnel's addresses and installs it on the dev store with every scope in queek.app.toml granted automatically. There is no consent screen.
  5. Starts your app with the command in the [dev] table, with APP_BASE_URL, PORT, NODE_ENV=development, QUEEK_API_BASE and the credentials from .queek/.env.local in its environment.
  6. Prints the ready block: the tunnel address, the Preview URL and the address the dashboard embeds the app from.

Saving queek.app.toml registers the build again. Changes to the [dev] table need a restart. Ctrl+C stops the app and the tunnel.

Preview

There is no separate preview mode: the dev install is the preview. Open the Preview URL the command prints. It has the form <dashboard address>/open-store?store=<dev store id>&app=<app slug>: it switches the dashboard to your dev store and opens the app inside it, exactly as a merchant would see it. An embedded page that never loads there is covered in Embedded apps.

Dev stores

A dev store is your own sandbox store (see Dev stores). queek app dev only installs on one:

  • It must be a dev store your developer account owns. The list is under Developers → Dev stores in the dashboard. Merchant stores and merchant test stores are refused, and so is a store that belongs to someone else. The error lists the dev stores you own.
  • --store <p_id|slug|name> names the store and always wins. Without it, the store you used last is reused (it is remembered in .queek/dev.json), otherwise your only dev store is used without asking. With several and no remembered choice, a terminal shows a menu that includes Create a new dev store; with no terminal (CI), the command stops, lists them and names --store.
  • An explicit --store is a one-off. It never changes the remembered store.
  • With no dev store at all, the command offers once to create one named after the app, with test data. Pass --create-dev-store to do it without a prompt.
  • --create-dev-store always creates a new store, even when you already own others, and cannot be combined with --store. Name it with --dev-store-name (default "<app name> dev") and choose its address with --dev-store-address; a taken address answers with a free suggestion. It stops with the server's reason when you are at the limit.
  • The limit is 5 dev stores per developer. Delete one in the dashboard to make room.
  • The storefront password of a store the CLI creates is printed once, when it is created. Save it then; you can also read it later from Developers → Dev stores.

To create a dev store without the CLI, for example from a script, see Create a dev store from a script.

queek app dev and queek app dev clean need a signed-in developer. An App Automation Token cannot run them.

The tunnel

The tunnel gives Queek's servers an https address for your local app: install, uninstall and webhook calls travel through it. The command waits until the tunnel's hostname resolves and GET /health on it answers, printing Waiting for the tunnel (n/90s)… every 5 seconds.

  • The wait is 90 seconds. Change it with --tunnel-timeout <seconds> or the QUEEK_APP_TUNNEL_TIMEOUT environment variable.
  • A free quick tunnel can take about a minute to appear in DNS. If it never answers, the command stops before installing anything and says why. Nothing is installed against a tunnel that cannot be reached. Run the command again: a new tunnel usually resolves within a minute.
  • --url <https-url> uses a tunnel you already run instead of starting one. The same wait and the same hard stop apply.

Develop from http://localhost

queek app dev --use-localhost

The dashboard then embeds your app from http://localhost:<port> plus the path of [extensions] merchant_page_url (for example /admin), so hot reload works inside the dashboard. The tunnel still starts and still serves install, uninstall and webhook calls. The ready block prints the embed address, for example http://localhost:3000/admin.

  • The app needs an embedded page. Without merchant_page_url the flag says so and keeps the tunnel address.
  • Only development apps can use it. See Develop against a development app.
  • It only works on the machine that runs the app. localhost is your own computer, so open the dashboard in a browser on the same machine and signed in there.
  • Browser support. A dashboard page on https:// loading http://localhost is allowed by Chrome and Edge. Safari and Firefox may block it; run without the flag there.

Remove the dev install

queek app dev clean

Uninstalls the dev build from the dev store and prints what was removed; it does nothing when there is no install. --store picks the store the same way dev does, and --reset also forgets the remembered store, so the next queek app dev asks again. Data your app keeps in its own database is not touched, and the dev store stays.

The install ends on the platform at once. The uninstall notice is sent to your app afterwards, by a queued job, so it can arrive seconds after a new queek app dev has already installed again. Key your app's state by the installation, not by the store, and do not rely on an uninstall arriving before the next install.

Develop against a development app

An app's distribution is set when it is registered. An app registered with distribution = "public" is a public listing: a build that needs review, such as a first listing or one that adds a shopper-facing, customer-data or payment scope, is put in review or stops queek app dev with needs review before it can install, and --use-localhost is refused. Editing distribution in the toml afterwards does not turn an app that is already registered into a development app.

For any app that touches shopper-facing content, customer data or payments, develop against a separate development app from the start:

queek.app.development.toml
slug = "my-app-dev"
name = "My App (dev)"
distribution = "development"

Copy the rest of queek.app.toml into it, then run everything with -c development:

queek app dev -c development

A development app is not listed in the app store and is never reviewed. Keep the real app for deploy and submit.

.queek/.env.local holds the signing secret of one app. A new slug registered by queek app dev replaces the value in it, and queek app deploy keeps the existing value and does not save the new app's secret. Before you register a second app in the same project folder, copy .queek/.env.local aside. If a secret is lost, reveal it under Developers → your app → Credentials. The starter keeps its slug in the APP_SLUG constant in app/config.ts, so set it to the slug of the app you run.

4. Generate API types

queek app codegen

Reads the live merchant.json and writes types to types/merchant.ts. Run it again to refresh them.

5. Host the app

Queek calls your app over https, so a deployed app needs a public https URL. Any host that runs a container or Node.js 22.14 or later works. The starter's Dockerfile builds one image that runs as a non-root user.

  • Listen on PORT (3000 by default). GET /health returns 200 without authentication.
  • Set APP_BASE_URL to the public https origin and use the same origin for the install, uninstall, settings and webhook URLs in queek.app.toml. queek app deploy sends them.
  • Store installations in a Postgres database of the app's own, through DATABASE_URL. The SDK refuses the dev SQLite file in production.
  • Supply secrets as environment variables, never in the image or repository:
VariableValue
QUEEK_APP_SECRETThe whsec_ signing secret, printed once by the first queek app deploy
APP_ENCRYPTION_KEY32 random bytes, base64
APP_KEY_IDKey id of the public key registered under the app's Keys in the Developer page
APP_PRIVATE_KEYThe matching PEM private key

The starter's .env.example shows how to generate each one.

6. Deploy a version

queek app deploy

Creates a version from the local manifest and releases it when review rules allow; otherwise it tells you to submit. The registration secret is shown once and saved locally.

7. Submit for review

queek app submit my-app

Checks readiness, collects the submission details and sends the version for review. Failed required checks block submission; warnings need acknowledgement. Give test-store instructions only, never production credentials. Run queek app submit --help for non-interactive options.

The submission includes a link to a screencast of the app: install, set-up, every feature and uninstall. Reviewers will not approve a listing without it. App review and distribution covers what the screencast must show and what review looks at.

CLI reference

CommandPurpose
npm create @usequeek/app my-appCreate a project from the app starter
queek app devRegister the app if needed, then develop through a tunnel on a dev store
queek app dev cleanRemove the dev install from the dev store
queek app codegenGenerate Merchant API types from the live spec
queek app deployCreate a version, and release it when allowed
queek app submit my-appCheck and submit a version for review

Flags for any command: queek app <command> --help, or npx -y @usequeek/cli app <command> --help without a global install.

queek app dev flags

FlagEnvironment variableWhat it does
--store <p_id|slug|name>QUEEK_APP_STOREThe dev store to use. Without it: the store used last, your only dev store, or a choice on a terminal.
--create-dev-storeCreate a new dev store with test data and run on it, even when you own others. Cannot be combined with --store.
--dev-store-name <name>QUEEK_APP_DEV_STORE_NAMEName of the created store. Default "<app name> dev".
--dev-store-address <slug>QUEEK_APP_DEV_STORE_SLUGAddress (slug) of the created store. A taken address answers with a free suggestion.
--port <n>Your local server port. Default: [dev].port, else 3000.
--url <https-url>Use a tunnel you already run instead of starting one.
--tunnel-timeout <seconds>QUEEK_APP_TUNNEL_TIMEOUTHow long to wait for the tunnel to resolve and answer /health. Default 90.
--use-localhostEmbed the app from http://localhost:<port> plus the merchant_page_url path. Development apps only.
-c, --config <name>QUEEK_APP_CONFIGRead queek.app.<name>.toml instead of queek.app.toml.
--path <dir>QUEEK_APP_PATHThe app project, where queek.app.toml lives. Default ..
--no-browserSign in with a device code instead of opening a browser.
--verboseQUEEK_THEME_VERBOSEPrint debug lines to stderr.

queek app dev clean takes --store, --reset, -c, --path, --no-browser and --verbose, plus --json for machine-readable output.

Every failed API call prints the server's request id on its own line (Request id: …). Quote it when you ask support for help.

When something fails

SymptomCause and fix
queek: command not foundThe CLI is not on your PATH. Install it globally or prefix the command with npx -y @usequeek/cli.
The install handoff answers an error and the installation never activatesAnswer the handoff with a 2xx first, then verify. An installation turns active only after your install URL answers success, and token minting is refused (409 app_installation_pending) until it does.
403 insufficient_scope from a Merchant API callThe installation was not granted the scope. Add it under [access] in queek.app.toml and deploy, or request an optional scope. See the manifest.
Webhook signature failsPass the raw request body to the SDK. Parsing and re-serialising it changes the bytes. See Webhooks.
Could not find dev store '<name>'queek app dev only installs on a dev store your developer account owns. The message lists yours. See Dev stores.
You own N dev stores — pass --store …There are several dev stores and no terminal to ask. Pass --store, or --create-dev-store for a new one.
The tunnel … did not become reachable within 90sNothing was installed. Run queek app dev again: a fresh tunnel usually resolves within a minute. Raise --tunnel-timeout on a slow network. See The tunnel.
v… needs review before it can installThe app is registered as a public listing and this build needs review. Develop against a development app.
Missing QUEEK_APP_SECRET and it could not be fetchedThe app's signing secret is not in .queek/.env.local and could not be fetched for this app. Reveal it under Developers → your app → Credentials and put it in that file.
The app opens in the dashboard as "didn't respond"The dashboard never received ready from your page. See Embedded apps.
The SDK refuses to start in productionIt does not use the development SQLite file in production. Set DATABASE_URL to a Postgres database.
429 too_many_requestsYou hit a rate limit. Wait Retry-After seconds. See Idempotency & rate limits.

On this page