The HTTP layer under TanStack Query, SWR & Vue Query — it handles auth so they don't have to

@mrzr/api-client

A TypeScript-first API client focused on secure browser authentication: coalesced token refresh, Web Worker token isolation, and cross-tab session sync. Zero runtime dependencies, works in every JS runtime.

$npm install @mrzr/api-client

Why @mrzr/api-client?

Most HTTP clients treat authentication as something you bolt on with interceptors. This client treats secure browser auth as the core product.

How it compares

Verified comparison against industry standards, including the rows where this library trades off bundle size for off-thread security.

Feature / Metricaxiosky@mrzr/api-client
Zero runtime dependencies✓ built in
Bundle, min+gzip~14 KB~4 KB13.4 KB*
Built onXHR / node:httpfetchfetch
Retry with backoffvia axios-retry✓ built in✗ (not yet)
Interceptors / hooks✓ global✓ globalper-request transforms
Coalesced token refreshKEY WINbuild it yourselfbuild it yourself✓ built in
Web Worker token isolationKEY WIN✓ built in
Cross-tab auth syncKEY WIN✓ built in
httpOnly cookie session restoreKEY WIN✓ built in
Cancel by URL pattern / scopeKEY WIN✓ built in
CSRF double-submitKEY WINpartial✓ built in

*Size note: 13.4 KB is axios-territory and 3× ky. About 3.8 KB of it is the inlined worker, which ships even when you pass { worker: false } — a runtime flag cannot be tree-shaken away.

Designed for Browser Security

Explore the architecture behind off-thread memory isolation, refresh coalescing, and tab synchronization.

Traditional Clients (axios / ky / fetch)

Tokens are stored in localStorage or main-thread variables. Any third-party npm package or XSS attack can read and exfiltrate tokens immediately.

// Vulnerable Main-Thread Memory
window.localStorage.getItem("access_token");
// Returns: "eyJhbGciOi..." (COMPROMISED)
@mrzr/api-client Web Worker Isolation

All requests and bearer tokens execute inside an inlined Web Worker. Tokens reside exclusively in the worker heap address space, completely invisible to the DOM.

// Web Worker Isolated Memory
window.localStorage.getItem("access_token"); // null
document.cookie; // ""
// Tokens unreachable from XSS!

Works with Your Data Library

It sits under TanStack Query, SWR, or Vue Query—it doesn't replace them. Failures reject with a typed ApiError, while cancellations cleanly resolve.

import { useQuery } from "@tanstack/react-query";
import { ApiError } from "@mrzr/api-client";
import { api } from "@/lib/api";

export function useUser(id: number) {
  return useQuery({
    queryKey: ["users", id],
    // 'signal' wires React Query cancellation straight through to fetch
    queryFn: ({ signal }) =>
      api.get<User>("/users/{id}", { addTemplateToUrl: { id }, signal }).then(r => r.data),
    retry: (count, error) => {
      // Never retry client errors (ApiError carries the HTTP status code)
      if (error instanceof ApiError && error.statusCode < 500) return false;
      return count < 3;
    },
  });
}
VERCEL OPTIMIZED DOCS & RUNTIME

Ready to Deploy on Vercel

This entire documentation website is built with Next.js 15 App Router, Fumadocs MDX, and Orama full-text search. It deploys onto Vercel with zero configuration required.