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",
  }),
  traceId: "trace_123",
  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
traceIdnot set
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>;
  traceId?: string;
};

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.

Joining a server trace

If your frontend wants its browser logs to join the same trace as the server request that rendered or handled it, pass the server response header through to the client logger:

const response = await fetch("/api/session");
const traceId = response.headers.get("x-blyp-trace-id") ?? undefined;

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

logger.info("session hydrated");

This is optional for standalone browser logs. Use it when you want browser-originated logs, connector-forwarded logs, and database records to share the same correlation ID.

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.