Skip to content
Guides

Customer accounts

Configure Better Auth, sign-in, registration, and generated account routes.

Accounts are optional for browsing and guest checkout. Sign-in, profiles, addresses, and orders require Better Auth and the same-origin proxy.

1. Authentication server

lib/auth.ts
import { createStorefrontAuth } from "@ecomiq/storefront";

export const auth = createStorefrontAuth();

Expose its handler:

pages/api/auth.$.ts
import { auth } from "../../lib/auth";

type ApiHandlerArgs = {
  request: Request;
};

async function handle({ request }: ApiHandlerArgs) {
  return auth.handler(request);
}

export const GET = handle;
export const POST = handle;

You must also create pages/api/$.ts with proxyStorefrontRequest, as shown in pages and routes.

2. Client and provider

lib/auth-client.ts
import { createStorefrontAuthClient } from "@ecomiq/storefront";

export const authClient = createStorefrontAuthClient();

The layout must mount AuthProvider. If you use cart and checkout, mount both:

layout.tsx
import { AuthProvider, CartProvider, defineLayout } from "@ecomiq/storefront";
import { authClient } from "./lib/auth-client";

export default defineLayout(({ children, settings }) => (
  <AuthProvider client={authClient}>
    <CartProvider
      storeId={settings.store.id}
      currencyCode={settings.store.currency}
    >
      {children}
    </CartProvider>
  </AuthProvider>
));

The default layout does not install these providers.

3. Session

import { useAuth } from "@ecomiq/storefront";

export function SessionButton({
  email,
  password,
}: {
  email: string;
  password: string;
}) {
  const { session, isPending, signIn, signOut } = useAuth();

  if (isPending) return <span>Loading…</span>;

  if (!session?.user) {
    return (
      <button onClick={() => void signIn({ email, password })}>Sign in</button>
    );
  }

  return <button onClick={() => void signOut()}>Sign out</button>;
}

4. Registration

registerCustomer requires the proxy client:

import { createStorefrontProxyApi, registerCustomer } from "@ecomiq/storefront";

await registerCustomer(createStorefrontProxyApi(), {
  email: "andrea@example.com",
  password: "a-secure-password",
  firstName: "Andrea",
  lastName: "Ramos",
  countryIsoCode: "US",
  phone: "+1 555 0100",
});

After registration, call signIn to create the session.

Account routes

The framework generates and protects:

  • /account/ — profile.
  • /account/addresses — addresses.
  • /account/orders and /account/orders/:orderId — orders.
  • /account/devices — informational screen; the devices endpoint does not exist yet.

/login and /register are not generated. You must create them under pages/.

The getCustomerMe, patchCustomer, getCustomerAddresses, createCustomerAddress, updateCustomerAddress, deleteCustomerAddress, getCustomerOrders, and getCustomerOrder helpers receive an Api first:

import { createStorefrontProxyApi, getCustomerMe } from "@ecomiq/storefront";

const customer = await getCustomerMe(createStorefrontProxyApi());

Server variables

VariableUse
BETTER_AUTH_SECRETSession secret; configure it as a production secret.
STOREFRONT_API_URLAPI used for sign-in; defaults to https://storefront.ecomiq.pe.
BETTER_AUTH_TRUSTED_HOSTSComma-separated allowed hosts; normally optional.

Sign-in API

api.baseUrl in ecomiq.config.js configures serverApi, but Better Auth sign-in uses STOREFRONT_API_URL. When targeting another environment, point both values to the same API.

On this page