Skip to content

Build your first OpenShop app

This tutorial starts PostgreSQL, creates an OpenShop app from the minimal template, installs it on a development store, and runs the generated flow.

  • Node.js >=26 <27
  • pnpm >=11 <12
  • Docker, or another PostgreSQL 17 instance
  • Shopify CLI
  • A Shopify Partner account with a development store

Create a local database container:

Terminal window
docker run --name openshop-postgres \
-e POSTGRES_DB=openshop \
-e POSTGRES_USER=openshop \
-e POSTGRES_PASSWORD=openshop \
-p 5432:5432 \
-d postgres:17-alpine

On later sessions, restart the same container with docker start openshop-postgres.

Terminal window
pnpm dlx openshop init my-app
cd my-app
pnpm install

The template pins the same OpenShop version used to generate it. It also contains the app definition, config, sample provider, sample flow, Shopify TOML files, Drizzle config, and an initial migration.

  • Directoryproviders/
  • Directoryflows/
  • Directoryproxy/
  • Directoryroutes/
  • Directorydrizzle/
  • openshop.app.ts
  • openshop.config.ts
  • drizzle.config.ts
  • shopify.app.toml
  • shopify.web.toml

The template also defines package.json#imports aliases so app code can use package-private imports such as #app, #flows/syncOrders, #providers/warehouse, and #routes/ping instead of ../ paths.

Create .env in the generated project:

Terminal window
printf '%s\n' \
'DATABASE_URL=postgresql://openshop:openshop@localhost:5432/openshop' \
> .env

openshop dev loads this file without replacing variables already supplied by the process. .env is ignored by the generated Git configuration.

Apply the initial migration and confirm that no migration remains pending:

Terminal window
pnpm run db:migrate
pnpm run db:status

Authenticate Shopify CLI:

Terminal window
shopify auth login

Link shopify.app.toml to an existing Partner Dashboard app, or create one when Shopify CLI prompts:

Terminal window
shopify app config link

Select or create the app and organization you want to use. The generated TOML requests read_products and read_orders; Shopify CLI keeps the linked app configuration for later runs.

Terminal window
pnpm run shopify

This is the only development command needed for the embedded app. It runs shopify app dev, creates the development tunnel, updates the development URLs, and invokes pnpm run dev from [commands] in shopify.web.toml.

In turn, openshop dev:

  1. runs optional GraphQL code generation;
  2. pushes the development schema;
  3. starts the API, admin UI, worker, and cron scheduler;
  4. reloads the API when app files change.

Use pnpm run dev directly only when you deliberately do not need the Shopify tunnel, OAuth installation, or embedded admin context.

  1. Press p in Shopify CLI, or open the preview URL it prints.
  2. Install the app on the selected development store.
  3. In Providers, configure warehouse with https://example.com and any non-empty development API key. The generated provider only logs its push, so this smoke value does not call that URL.
  4. In Flows, run syncOrders with:
{ "limit": 10 }

The run should move from pending or running to completed. Its logs should contain “Orders synced”. A failure is also visible on the run page with its step logs; common causes are a missing app installation or the read_orders scope not being granted.

Run the project checks:

Terminal window
pnpm run lint

The generated template runs GraphQL codegen before TypeScript and ESLint checks.