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:
rm .shopify/project.json
Then link to the correct store:
shopify hydrogen link
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

shopify hydrogen env pull
Verify your .env has these variables:
PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID=shp_xxxxx
PUBLIC_CUSTOMER_ACCOUNT_API_URL=https://shopify.com/SHOP_ID
PUBLIC_STOREFRONT_API_TOKEN="your-storefront-api-token"
PUBLIC_STORE_DOMAIN="your-store.myshopify.com"
SHOP_ID=your-shop-id
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

npm run dev:ca
This runs:
shopify hydrogen dev --codegen --port 3456 --customer-account-push
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:
  ➜  Local:   http://localhost:3456
  ➜  Tunnel:  https://abc123.tryhydrogen.dev
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:
# Install ngrok
brew install ngrok

# Start a tunnel to your dev server
ngrok http 3456
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:
FieldValue
Callback URI(s)https://your-tunnel-domain/account/authorize
JavaScript origin(s)https://your-tunnel-domain
Logout URIhttps://your-tunnel-domain

Update Content Security Policy

In your app/entry.server.tsx, add the tunnel domain to your CSP:
const { nonce, header, NonceProvider } = createContentSecurityPolicy({
  connectSrc: [
    "'self'",
    "https://your-tunnel-domain",
    // ... other sources
  ],
});

Start the dev server

npm run dev
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/:
RoutePurpose
auth/login.tsRedirects to Shopify login
auth/logout.tsLogs the customer out
auth/authorize.tsHandles OAuth callback
dashboard/index.tsxAccount dashboard
dashboard/account-details.tsxCustomer profile details
dashboard/address-book.tsxSaved addresses
dashboard/orders-history.tsxOrder history
profile.tsxEdit profile
edit.tsxEdit account settings
orders/list.tsxOrders list
orders/order.tsxSingle order view
address/index.tsxAddress management
address/list.tsxAddress list
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:
rm .shopify/project.json
shopify hydrogen 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:
export async function loader({ context }: LoaderFunctionArgs) {
  const customer = await context.customerAccount.query(CUSTOMER_QUERY);
  return json(
    { customer },
    { headers: { "Set-Cookie": await context.session.commit() } }
  );
}
The dev server defaults to port 3456. To free it:
lsof -ti:3456 | xargs kill -9

Next Steps