Shipflash logoDocs

Customers

Customers gives operators a searchable view of provider customers, customer detail, billing history, and related provider records.

On this page

Where to look

AreaPaths
Routessrc/app/(dashboard)/customers, /customers/[providerCustomerId], /billing/customers
List server codesrc/features/customers/server/list
Detail server codesrc/features/customers/server/detail
Billing groupingsrc/features/customers/server/billing/grouping.ts
Sharedsrc/features/customers/shared
UIsrc/features/customers/ui/list-page.tsx, detail-page.tsx, people-lists.tsx
Billing databilling_customers, billing_subscriptions, billing_orders, billing_invoices, billing_charges, billing_refunds, billing_disputes

Code-backed customers map

Customer list and detail

Customer pages delegate list projection, filtering, and detail reads to the customers feature.

  • src/app/(dashboard)/customers/page.tsx
  • src/app/(dashboard)/customers/[providerCustomerId]/page.tsx
  • src/features/customers/ui/list-page.tsx
  • src/features/customers/ui/detail-page.tsx

List query pipeline

List helpers parse filters, build projections, and paginate before rendering customer tables.

  • src/features/customers/server/list/page-query.ts
  • src/features/customers/server/list/filters.ts
  • src/features/customers/server/list/sensitive-data.ts

Billing-backed detail

Customer detail uses provider customer ids and billing grouping helpers without treating provider ids as profile ids.

  • src/features/customers/server/detail/customer.ts
  • src/features/customers/server/billing/grouping.ts
  • src/features/customers/shared/provider-customer-id.ts

Customer lookup flow

  1. 1

    Parse filters and pagination

    Customer list requests use server-side filters and page queries before UI renders rows.

    • src/features/customers/server/list/filters.ts
    • src/features/customers/server/list/page-query.ts
  2. 2

    Project list rows

    Projection helpers keep list rows compact and prevent detail-only fields from being loaded for every customer.

    • src/features/customers/server/list/sensitive-data.ts
  3. 3

    Resolve provider detail

    Detail pages use provider customer ids to load customer, billing, and related records.

    • src/features/customers/shared/provider-customer-id.ts
    • src/features/customers/server/detail/customer.ts
  4. 4

    Group billing context

    Billing grouping helpers organize subscriptions, invoices, charges, refunds, and disputes for detail UI.

    • src/features/customers/server/billing/grouping.ts

Customer list bounded query

Source: src/features/customers/server/list/page-query.ts

Customer list pages filter server-side, use the active billing provider, and apply a limit before joining detail data.

ts
const provider = await getBillingProvider();
const providerLabel = provider === "lemonsqueezy" ? "Lemon Squeezy" : "Stripe";
const safeQuery = normalizeCustomerQuery(filters.q);

let customersQuery = supabase
  .from("billing_customers")
  .select("provider,provider_customer_id,customer_email,customer_name,profile_id,latest_billing_model,latest_checkout_kind,last_checkout_completed_at,updated_at")
  .eq("provider", provider as never)
  .order("updated_at", { ascending: false })
  .limit(filters.limit);

if (safeQuery) {
  customersQuery = customersQuery.or(buildOrIlikeFilter(["customer_email", "customer_name", "provider_customer_id"], safeQuery) ?? "");
}

Customer view rules

  • Paginate before customer tables grow.
  • Read only fields needed for list pages.
  • Keep provider customer ids separate from internal profile ids.
  • Use explicit sync paths for provider refresh work.