Customer Account API Local Development
This guide is for Shopify Hydrogen storefronts. Building on Next.js? See the Next.js overview.
http://localhost won’t work. Hydrogen 2026.10 refuses to build a login URL over plain HTTP, so /account/login fails under npm run dev by design. This guide walks you through running the Pilot theme locally with full Customer Account API support.
How Sign-In Works
- Hydrogen 2026.10 owns the fixed, unprefixed routes
/account/login,/account/authorize,/account/refreshand/account/logout, registered inserver.tswithcreateCustomerAccountServerHandlers(). Link to them with a plain<a>or<form>, never React Router’s<Link>or<Form>: they answer with a redirect that client-side routing cannot follow. - The market travels in the query string. An account page visited without a session redirects to
/account/login?return_to=/de-de/account&locale=de, so the shopper signs in on Shopify’s German login page and comes back to the German market. - The customer’s tokens live in the signed session cookie (
SESSION_SECRET).
Prerequisites
- A Shopify store with the Hydrogen or Headless sales channel installed
- Customer accounts enabled in your Shopify admin
- Shopify CLI installed (
@shopify/cli4.4.0 or later, with@shopify/cli-hydrogen13.0.4 or later so the dev server can register its URLs for you) - Your Hydrogen project linked to your store (
shopify hydrogen link)
Step 1: Enable Customer Accounts
- From your Shopify admin, go to Settings > Customer accounts
- Under Accounts in online store and checkout, click Edit
- Select Customer accounts
- Click Save
Step 2: Link Your Project
If you have an existing.shopify/project.json pointing to a different store, delete it first:
Step 3: Pull Environment Variables
.env has these variables:
SHOP_ID is the numeric shop ID, not a GID or domain. Leave SHOP_ID and PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID empty to run the storefront without customer accounts.
Option A: Paid Stores (Basic to Plus)
For stores on a paid Shopify plan, use the built-indev:https command. This is the easiest approach — it serves the dev server over HTTPS and configures OAuth automatically.
The
dev:https script is already configured in the Pilot theme’s package.json — no additional setup needed.Start the HTTPS dev server
vite dev --port 3456 as npm run dev, with Hydrogen’s localHttps Vite plugin turned on in vite.config.ts:
- Serves HTTPS locally — at
https://local.tryhydrogen.dev:3456, a Shopify-owned name that resolves to127.0.0.1, with a locally trusted certificate. On the first run it installs a local certificate authority, which may prompt for your password. To do that ahead of time, runnpx hydrogen certs install. - Syncs OAuth credentials — uses Shopify CLI to add the Callback URI, JavaScript Origin, and Logout URI to your storefront’s Customer Account API settings
Open the HTTPS URL
Open the HTTPS URL the dev server prints, for examplehttps://local.tryhydrogen.dev:3456, and navigate to /account to test login.
If Shopify CLI is missing, outdated or the push fails, the dev server keeps running and prints the values. Set them manually in Hydrogen > Storefront > Customer Account API settings:
Option B: Development Stores — Manual Tunnel Setup
For Shopify development stores (Partner/Staff), the automatic Customer Account API setup 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:- ngrok
- Cloudflare Tunnel
Configure Customer Account API
For development stores, configure this in the Headless sales channel app:- Open your Shopify admin → Settings > Customer accounts
- Find Customer Account API and open Application setup
- Ensure the client type is set to Public
- Update the following fields with your tunnel URL:
Update Content Security Policy
Inapp/weaverse/csp.ts, add the tunnel domain to connectSrc:
Start the dev server
x-forwarded-proto: https header, so the login URL uses HTTPS.
Account Routes in Pilot Theme
Login, OAuth callback, token refresh and logout are handled by Hydrogen’s Customer Account handlers at/account/login, /account/authorize, /account/refresh and /account/logout, not by route files. The Pilot theme includes the account pages 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
Login fails or redirect loop on localhost
Login fails or redirect loop on localhost
Customer Account API requires HTTPS. Use
npm run dev:https (paid stores) or set up a tunnel (dev stores). Never test account flows on http://localhost. An error like Customer Account OAuth origin must use HTTPS means you opened the site over http://.ACCESS_DENIED error on shopify hydrogen commands
ACCESS_DENIED error on shopify hydrogen commands
Your
.shopify/project.json is pointing to a store where you don’t have channel access. Delete it and re-link:OAuth redirect mismatch error
OAuth redirect mismatch error
The Callback URI, JavaScript origin and Logout URI in your Shopify admin must exactly match the URL you are browsing, including the port (except the JavaScript origin, which has none). For paid stores using
dev:https, this is synced automatically. For dev stores, update it manually. A sign-in that lands on /account?login=failed or loops back to Shopify usually has a mismatch here.Customer data not persisting after login
Customer data not persisting after login
The customer’s tokens are stored in the session cookie, which
server.ts must commit on every response path, including the responses of handleShopifyRoutes. Check that SESSION_SECRET is set and that your server entry commits the session as in Step 3 of the v6 migration guide.Port already in use
Port already in use
The dev server uses port
3456 and exits when the port is taken. To free it:Next Steps
- Read the Customer Account API reference for available queries and mutations
- Follow Shopify’s Using Customer Account API with Hydrogen tutorial
- Learn about Weaverse environment variables