> ## Documentation Index
> Fetch the complete documentation index at: https://juo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Customer

> Current customer profile as reactive state.

The customer service exposes the signed-in customer. The service exposes one reactive signal and one fetch method.

## Setup

```ts theme={null}
import {
  provideContext,
  createCustomerService,
  createApiCustomerAdapter,
  CustomerServiceContext,
} from "@juo/blocks";

provideContext(
  root,
  CustomerServiceContext,
  createCustomerService(createApiCustomerAdapter({ baseUrl: "/api/v1" })),
);
```

## Shape

```ts theme={null}
type Customer = {
  id: string;
  name: string;
  email?: string;
  metadata?: Record<string, unknown>;
};

type CustomerService = {
  current: Signal<Customer | null>;
  getCurrent(): Promise<Result<Customer | null>>;
};
```

## Reactive state

`current` is `null` until a successful call to `getCurrent()` populates it. After that, every block that reads it updates automatically.

## Example: greeting block

```ts theme={null}
import {
  defineBlock,
  effect,
  untracked,
  injectContext,
  CustomerServiceContext,
} from "@juo/blocks";

defineBlock("Greeting", {
  group: "theme",
  schema: { /* ... */ } as const,
  initialValue: () => ({ props: {} }),
  renderer(block) {
    const el = document.createElement("h1");
    const customer = injectContext(el, CustomerServiceContext);

    void customer.getCurrent();

    effect(() => {
      const name = customer.current.value?.name ?? "Guest";
      untracked(() => {
        el.textContent = `Welcome back, ${name}`;
      });
    });

    return el;
  },
});
```

## Custom metadata

The `metadata` field is a free-form record. Adapters can populate it with store-specific fields (loyalty tier, plan flags) without changing the service interface.
