Skip to main content

Customer Account API Local Development

The Customer Account API requires OAuth 2.0 flows with HTTPS callback URLs — which means http://localhost won’t work. This guide walks you through running the Pilot theme locally with full Customer Account API support.
The setup differs depending on your store type:
  • Paid stores (Basic, Shopify, Advanced, Plus) → use the built-in dev:ca command with automatic tunneling
  • Development stores (Partner/Staff) → use ngrok or Cloudflare Tunnel with manual OAuth configuration in the Headless sales channel app

Prerequisites

  • A Shopify store with the Hydrogen or Headless sales channel installed
  • Customer accounts enabled in your Shopify admin
  • Shopify CLI installed (@shopify/cli)
  • Your Hydrogen project linked to your store (shopify hydrogen link)

Step 1: Enable Customer Accounts

  1. From your Shopify admin, go to Settings > Customer accounts
  2. Under Accounts in online store and checkout, click Edit
  3. Select Customer accounts
  4. Click Save

If you have an existing .shopify/project.json pointing to a different store, delete it first:
Then link to the correct store:
If .shopify/project.json points to a store where your account lacks Hydrogen/Headless channel access, all shopify hydrogen commands will fail with ACCESS_DENIED — including shopify hydrogen link itself.

Step 3: Pull Environment Variables

Verify your .env has these variables:
When deploying to Shopify Oxygen, these variables are injected automatically — no manual setup needed for production.

Option A: Paid Stores (Basic to Plus)

For stores on a paid Shopify plan, use the built-in dev:ca command. This is the easiest approach — it handles tunneling and OAuth configuration automatically.
The dev:ca script is already configured in the Pilot theme’s package.json — no additional setup needed.

Start the dev server

This runs:
The --customer-account-push flag does two things:
  1. Creates an HTTPS tunnel — publishes your local dev server to a *.tryhydrogen.dev domain
  2. Syncs OAuth credentials — automatically configures the Callback URI, JavaScript Origin, and Logout URI in your Shopify admin

Open the tunnel URL

After the dev server starts, look for the tunnel URL in your terminal:
Use the *.tryhydrogen.dev URL to test customer account flows. Navigate to /account to test login.
Do not use http://localhost:3456 for customer account testing — OAuth redirects will fail on non-HTTPS origins.

Option B: Development Stores — Manual Tunnel Setup

For Shopify development stores (Partner/Staff), the --customer-account-push flag is not available. You must use a third-party tunneling service and manually configure the Customer Account API in the Headless sales channel app.

Set up a tunnel

Choose either ngrok or Cloudflare Tunnel:
Use a static ngrok domain so you don’t have to reconfigure OAuth settings every time you restart.

Configure Customer Account API

For development stores, configure this in the Headless sales channel app:
  1. Open your Shopify admin → Settings > Customer accounts
  2. Find Customer Account API and open Application setup
  3. Ensure the client type is set to Public
  4. Update the following fields with your tunnel URL:

Update Content Security Policy

In your app/entry.server.tsx, add the tunnel domain to your CSP:

Start the dev server

Then access your storefront via the tunnel URL (not localhost).

Account Routes in Pilot Theme

The Pilot theme includes a complete set of customer account routes at app/routes/account/: Source: Pilot theme routes
Customer account pages are code-based routes — they are not editable through Weaverse Studio’s visual editor. Any layout or design changes need to be done directly in the route files.

Troubleshooting

Customer Account API requires HTTPS. Use npm run dev:ca (paid stores) or set up a tunnel (dev stores). Never test account flows on http://localhost.
Your .shopify/project.json is pointing to a store where you don’t have channel access. Delete it and re-link:
The Callback URI in your Shopify admin must exactly match your tunnel URL (including no trailing slash). For paid stores using --customer-account-push, this is synced automatically. For dev stores, update it manually.
Ensure you commit the session at the end of any loader/action with a customer auth check:
The dev server defaults to port 3456. To free it:

Next Steps