Skip to content
Zap Studio
cache
Esc
navigateopen⌘Jpreview
On this page

Zap Studio

Type-safe, framework-agnostic TypeScript packages for HTTP calls, retries, auth, validation, logging, and webhooks — install one and make your first typed call.

Zap Studio is a set of small TypeScript packages for the code every app needs: HTTP calls, retries, permission checks, validation, logs, webhooks. Pick the one you need, install it, use it. No new runtime, no framework.

This page takes about five minutes. At the end you will have a typed HTTP call that retries on failure.

Before You Start

You need Node.js 18, Bun 1.0, Deno 1.42, a current Cloudflare Workers release, or an evergreen browser. Runtimes has the full matrix, including the four packages that ask for more.

TypeScript 5 or later is recommended — the packages work in plain JavaScript, but the types are the point.

Install Your First Package

Start with fetch. It makes an HTTP call and validates the response against a schema.

npm install @zap-studio/fetch zod
yarn add @zap-studio/fetch zod
pnpm add @zap-studio/fetch zod
bun add @zap-studio/fetch zod
deno add jsr:@zap-studio/fetch npm:zod

You also need a schema library that implements Standard Schema — Zod, Valibot, or ArkType. This page uses Zod.

Make a Typed Call

A schema describes the shape you expect back. You pass it to api.get, which validates the response at runtime and infers the type from it.

import { api } from "@zap-studio/fetch";
import { z } from "zod";

const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.email(),
});

// `user` is typed from UserSchema — no manual annotations, no `as` casts
const user = await api.get("https://jsonplaceholder.typicode.com/users/1", UserSchema);

console.log(user.name);

Run it. You get:

Leanne Graham

Change name: z.string() to name: z.number() and run it again. The call throws a ValidationError instead of handing you bad data. That is the whole idea: the response is checked before your code touches it.

Add a Second Package

Packages compose. Wrap the same call in a retry policy so a flaky network does not break it.

npm install @zap-studio/retry
yarn add @zap-studio/retry
pnpm add @zap-studio/retry
bun add @zap-studio/retry
deno add jsr:@zap-studio/retry

A retry policy decides how many attempts to make and how long to wait between them. exponentialBackoff doubles the delay after each failure, up to a cap.

import { api } from "@zap-studio/fetch";
import { exponentialBackoff, runRetryPolicy } from "@zap-studio/retry";
import { z } from "zod";

const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.email(),
});

const policy = exponentialBackoff({
  maxAttempts: 3, // total attempts, including the first
  baseDelayMs: 100, // first retry waits 100 ms
  maxDelayMs: 2_000, // later retries never wait longer than 2 s
});

const user = await runRetryPolicy(policy, () =>
  api.get("https://jsonplaceholder.typicode.com/users/1", UserSchema),
);

console.log(user.name);

Same output, three attempts instead of one. Point the URL at https://jsonplaceholder.typicode.com/nope and watch it try three times before it throws.

Pick Your Package

Package What you get
cache An in-memory cache with pluggable eviction and optional TTL
env Typed, validated env vars with a server/client/shared split
fetch Typed responses from any API — no manual casts
logger Structured logs anywhere — console today, any backend tomorrow
monads Errors as values you can’t forget to handle
oxfmt One decided import/package.json order — no more per-repo debate
oxlint A preset per stack, zero-config linting beyond oxlint’s defaults
permit Every permission check in one auditable place
react-hooks Small, focused, tree-shakeable React hooks
retry Retries done right — backoff, jitter, cancellation included
store State with derived values that auto-track, and built-in persist
validation One validation error shape, whatever schema library you use
webhooks Verified, routed webhooks without a hand-rolled signature check
webmcp SSR-safe tool registration for the native WebMCP browser API

Install only the packages you need — each one works standalone.

Where to Go Next

Or go deeper on what you just built: fetch Getting Started for error handling, POST/PUT/DELETE and configured clients, retry Getting Started for jitter, cancellation and result objects instead of throws.

Last updated on September 8, 2026

Was this page helpful?