Commenting out the 3 compliance-topic webhook subscriptions (previous commit) didn't clear the "not approved to subscribe to webhook topics containing protected customer data" error — same 3 errors, same wording, even with those blocks fully removed from shopify.app.toml. That means the gate isn't about our webhook declarations at all; it's much more likely triggered by the `read_customers` OAuth scope itself; Shopify's Protected Customer Data Access requirement applies to the scope, and the CLI's error message just reuses the same generic wording for the whole policy category regardless of which part of the config triggered it. Removed read_customers from shopify.app.toml, .env, and .env.example. This is also independently correct per CLAUDE.md's "request the minimum OAuth scopes needed" — nothing in the codebase actually calls the Customers API; Booking.customerEmail/customerPhone come straight off the orders/create webhook payload, which read_orders already covers. Add it back only when a feature that genuinely needs it exists, and expect to need Protected Customer Data Access granted at that point regardless. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Delivery Date & Time
Shopify app: scheduling for Shipping / Local Delivery / Store Pickup, with date-time slots, capacity intelligence, and all-plan checkout enforcement via Cart/Checkout Validation Functions.
Read PRODUCT_STRATEGY.md (why) and IMPLEMENTATION_PLAN.md (how, phased build order) before making changes. CLAUDE.md holds the non-negotiables for AI-assisted work in this repo.
Getting started
npm install
cp .env.example .env # fill in Shopify app credentials after linking
docker compose up -d # local Postgres (5433) + Redis (6380)
npx prisma migrate dev
npm run dev # shopify app dev — requires `shopify auth login` first
Dev uses Postgres, same as prod, since the schema relies on Prisma enums and
(from Phase 5 on) array fields that SQLite can't express. npm run worker
runs the BullMQ worker (jobs/worker.ts) once Phase 4 makes it do anything.
Commands
| Command | Purpose |
|---|---|
npm run dev |
shopify app dev — local dev against a dev store |
npm test |
Vitest unit tests |
npm run test:e2e |
Playwright E2E |
npm run lint / npm run typecheck |
ESLint / tsc --noEmit |
npx prisma migrate dev |
DB migrations |
npm run deploy |
shopify app deploy — deploy extensions/functions |
npm run worker |
BullMQ worker (hold-expiry, notifications) |
npm run test:integration |
Redis/Postgres-backed tests (slot-hold concurrency, booking flow) — needs docker compose up -d |
npm run test:functions |
Real WASM build + function-runner tests for both Shopify Functions, against fixtures |
npm run typegen:functions |
Regenerate extensions/*/generated/api.ts from each Function's schema.graphql + .graphql query (also runs automatically before npm run typecheck) |
Before public launch
The 3 mandatory GDPR compliance webhooks (customers/data_request,
customers/redact, shop/redact) are commented out in shopify.app.toml
— Shopify refuses to push them until the org requests and is granted
Protected customer data access in the Partner Dashboard (Apps → this
app → API access → Protected customer data), which is a manual
questionnaire/approval step. The handlers already exist and are fully
wired (app/routes/webhooks.customers.*.tsx, webhooks.shop.redact.tsx) —
once that access is granted, uncomment the three [[webhooks.subscriptions]]
blocks near the bottom of the webhooks section. Required before any
public launch or Built-for-Shopify submission — don't ship without it.
Status
Phase 0 (scaffold & CI) through Phase 4 (enforcement Functions +
slot-holds) are complete. See §6 of IMPLEMENTATION_PLAN.md for the phased
build order and acceptance criteria — next up is Phase 5 (multi-location,
zones, rates, auto-assignment).
The storefront widget's TypeScript source lives in widget-src/datetime-widget/,
not inside extensions/datetime-widget/ — a Theme App Extension's
directory may only contain assets, blocks, snippets, and locales
(the CLI hard-rejects anything else, e.g. a src/ folder, with "Only
assets, blocks, snippets, locales directories are allowed"). Editing the
widget? Run npm run build:widget to bundle it into
extensions/datetime-widget/assets/datetime-widget.js — it also runs
automatically before npm run dev / npm run deploy.
Functions are JavaScript, not Rust (extensions/validation-slot/,
extensions/delivery-customization/) — no Rust toolchain was available in
the environment that built Phase 4, and IMPLEMENTATION_PLAN.md §1
explicitly allows JS as a fallback. Both were generated with
shopify app generate extension (once a real Partner login was available)
and their business logic (src/evaluate.js in each) is verified two ways:
plain Vitest unit tests at the repo root (npm test) and real
function-runner fixture tests that compile actual WASM
(npm run test:functions, also in CI). extensions/*/generated/ and
extensions/*/dist/ aren't committed (matching the CLI's own
.gitignore for these extensions) — npm run typegen:functions
regenerates the types from the committed schema.graphql, and building
runs automatically as part of npm run dev / test:functions.