Blyp Docs

Client

The @blyp/core/client entry gives you two major capabilities:

For Expo apps, use the dedicated @blyp/core/expo logger instead of @blyp/core/client.

createClientLogger()

import { createClientLogger } from "@blyp/core/client";

const logger = createClientLogger({
  endpoint: "/inngest",
  credentials: "same-origin",
  metadata: () => ({
    app: "dashboard",
    release: "2026.03.10",
  }),
  delivery: {
    maxRetries: 3,
    retryDelayMs: 5000,
  },
});

logger.info("hydrated", { route: window.location.pathname });
logger.error(new Error("button failed to render"));
logger.child({ feature: "checkout" }).warn("client validation failed");

When to use it

Use the browser client when you want Blyp to:

If your app only needs local browser logging and no remote sync, disable remoteSync.

const logger = createClientLogger({
  endpoint: "/inngest",
  remoteSync: false,
});

Defaults

OptionDefault
endpoint/inngest
credentials"same-origin"
localConsoletrue
remoteSynctrue
delivery.maxRetries3
delivery.retryDelayMs5000
delivery.maxQueueSize100

Delivery behavior

Remote browser delivery is managed by a shared in-memory dispatcher:

Retryable failures are:

Non-retryable response failures, such as 400, fail immediately and trigger terminal failure handling.

If you do not set custom headers, the client logger still uses navigator.sendBeacon() as a last-chance fallback when fetch(..., { keepalive: true }) fails.

Delivery hooks

Use delivery to customize retry policy and observe outcomes:

const logger = createClientLogger({
  delivery: {
    maxRetries: 3,
    retryDelayMs: 5000,
    maxQueueSize: 100,
    warnOnFailure: true,
    onRetry: (ctx) => {
      console.log("retrying", ctx.attempt, ctx.retriesRemaining);
    },
    onSuccess: (ctx) => {
      console.log("delivered via", ctx.transport);
    },
    onFailure: (ctx) => {
      console.error("terminal delivery failure", ctx.reason, ctx.status);
    },
    onDrop: (ctx) => {
      console.warn("dropped", ctx.droppedEvent.message, "for", ctx.replacementEvent.message);
    },
  },
});

Hook context highlights

Event shape

Client events are normalized into a ClientLogEvent shape:

type ClientLogEvent = {
  type: "client_log";
  source: "client";
  id: string;
  level: "debug" | "info" | "warning" | "error" | "critical" | "success" | "table";
  message: string;
  data?: unknown;
  bindings?: Record<string, unknown>;
  clientTimestamp: string;
  page: ClientLogPageContext;
  browser: ClientLogBrowserContext;
  device?: ClientLogDeviceContext;
  session: { pageId: string; sessionId: string };
  metadata?: Record<string, unknown>;
};

Browser error parsing

import { parseError } from "@blyp/core/client";

const response = await fetch("/api/payments", { method: "POST" });

if (!response.ok) {
  throw await parseError(response);
}

See Parse Error for server and browser parsing patterns in more detail.

Pairing with server adapters

Most server-side adapters automatically register or expose a handler for the configured client ingestion path:

See the individual pages under Integrations for exact mounting patterns.

Connector forwarding requests

The browser client can ask Blyp ingestion to forward logs into a configured connector:

const posthogLogger = createClientLogger({
  endpoint: "/inngest",
  connector: "posthog",
});

const sentryLogger = createClientLogger({
  endpoint: "/inngest",
  connector: "sentry",
});

const otlpLogger = createClientLogger({
  endpoint: "/inngest",
  connector: { type: "otlp", name: "grafana" },
});

Important behavior:

Use Connectors for the server-side setup behind these requests.

Expo mobile logging

Expo has its own logger because it does not run in a browser environment and cannot rely on same-origin delivery.

import { createExpoLogger } from "@blyp/core/expo";

const logger = createExpoLogger({
  endpoint: "https://api.example.com/inngest",
  metadata: () => ({
    app: "mobile",
  }),
  delivery: {
    maxRetries: 3,
    retryDelayMs: 5000,
  },
});

Use Expo for the full mobile setup and its delivery constraints.