Project structure
openshop init creates the app definition, sample provider and flow, Shopify
configuration, package scripts, deployment files, and an initial migration.
Create optional feature directories as your app needs them.
Directoryproviders/
- warehouse.ts
Directoryflows/
- syncOrders.ts
Directorydrizzle/
- …
- openshop.app.ts
- openshop.config.ts
- drizzle.config.ts
- shopify.app.toml
- shopify.web.toml
- package.json
- Dockerfile
- ecosystem.config.cjs
| Optional directory | Add it when you need |
|---|---|
proxy/ |
Storefront or Customer Account endpoints |
routes/ |
HTTP endpoints with explicit authentication |
webhooks/ |
Registered Shopify event handlers |
models/ |
Application-owned database tables |
admin/pages/ |
Experimental custom admin screens |
tests/ |
An app test suite; openshop test requires tests/bootstrap.ts |
openshop.app.ts
Section titled “openshop.app.ts”Creates the typed OpenShop app with defineOpenShop(). Register providers here so their connector methods are available in flows.
openshop.config.ts
Section titled “openshop.config.ts”Exports the default runtime config with app.defineConfig(). Register flows, crons, webhooks, Shopify Function UI definitions, worker settings, retry policy, MCP config, and admin page visibility here.
providers/
Section titled “providers/”Contains provider definitions. Providers define admin config fields and methods for external systems.
flows/
Section titled “flows/”Contains background job definitions. Flows run in workers and can use checkpointed steps, Shopify clients, provider connectors, logs, and the database.
proxy/
Section titled “proxy/”Contains file-based app proxy and Customer Account extension routes. Route files export app.defineProxy().
routes/
Section titled “routes/”Contains optional public server routes mounted under /routes/*. Every route must explicitly declare an authentication function or auth: 'none'.
admin/pages/
Section titled “admin/pages/”Contains experimental app-owned Preact pages. A page.tsx file defines a
filesystem route, while a colocated actions.server.ts defines authenticated,
typed loaders and actions. See Custom admin pages.
drizzle/
Section titled “drizzle/”Contains committed SQL migrations owned by the app. The folder includes framework-owned tables and app model tables.
Generated files
Section titled “Generated files”GraphQL codegen can create generated operation types and OpenShop operation bridge files. The template ignores these files by default.
Import aliases
Section titled “Import aliases”The template uses Node package subpath imports in package.json for app-local aliases:
{ "imports": { "#app": "./openshop.app.ts", "#flows/*": "./flows/*.ts", "#functions/*": "./functions/*.ts", "#models/*": "./models/*.ts", "#providers/*": "./providers/*.ts", "#queries/*": "./queries/*.ts", "#routes/*": "./routes/*.ts", "#server/*": "./server/*.ts", "#webhooks/*": "./webhooks/*.ts" }}Use these aliases for imports that cross app folders:
import { app } from '#app'import { syncOrders } from '#flows/syncOrders'import { warehouse } from '#providers/warehouse'Relative imports are still fine for files that live next to each other, such as test helpers in the same directory.