# Zap Studio

[![CI](https://github.com/zap-studio/monorepo/actions/workflows/ci.yml/badge.svg)](https://github.com/zap-studio/monorepo/actions/workflows/ci.yml) [![License](https://img.shields.io/github/license/zap-studio/monorepo)](https://github.com/zap-studio/monorepo/blob/main/LICENSE)

Small, type-safe TypeScript packages for the infrastructure code every app needs — HTTP calls, retries, auth checks, validation, logging, webhooks. Done once, correctly, so you don't rebuild it per project.

```bash
npm install @zap-studio/fetch
```

[Start with `fetch` →](/fetch/getting-started)

## Quick Look

```ts
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://api.example.com/users/1", UserSchema);
```

## Packages

| Package                                   | What you get                                                      |
| ----------------------------------------- | ----------------------------------------------------------------- |
| [`@zap-studio/fetch`](/fetch)             | Typed responses from any API — no manual casts                    |
| [`@zap-studio/logger`](/logger)           | Structured logs anywhere — console today, any backend tomorrow    |
| [`@zap-studio/monads`](/monads)           | Errors as values you can't forget to handle                       |
| [`@zap-studio/oxfmt`](/oxfmt)             | One decided import/`package.json` order — no more per-repo debate |
| [`@zap-studio/oxlint`](/oxlint)           | A preset per stack, zero-config linting beyond oxlint's defaults  |
| [`@zap-studio/permit`](/permit)           | Every permission check in one auditable place                     |
| [`@zap-studio/react-hooks`](/react-hooks) | Small, focused, tree-shakeable React hooks                        |
| [`@zap-studio/retry`](/retry)             | Retries done right — backoff, jitter, cancellation included       |
| [`@zap-studio/validation`](/validation)   | One validation error shape, whatever schema library you use       |
| [`@zap-studio/webhooks`](/webhooks)       | Verified, routed webhooks without a hand-rolled signature check   |

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

## Why Zap Studio

Most teams solve these problems by hand, per project — and the hard parts get skipped:

* **Fragile by default.** Hand-rolled retries and webhook checks quietly skip the parts that matter.
* **Scattered, not audited.** Permission checks end up copy-pasted across the codebase instead of living in one place.
* **Node-only, until it isn't.** Homegrown wrappers break the moment your code runs on an edge runtime or in the browser.

## Every Package Follows the Same Rules

* **Type safety.** Types come from your schema via [Standard Schema](https://standardschema.dev), not hand-written annotations.
* **Framework-agnostic.** Built on standard runtime APIs — `fetch`, `Request`/`Response`, `AbortSignal`.
* **Composable.** Combine packages as needed — wrap a `fetch` call in a `retry` policy, validate a webhook with `validation`.
* **Tree-shakeable.** Standalone functions, no shared state — unused exports drop out of your bundle.

## Compared to Effect

If you know [Effect](https://effect.website): yes, there's overlap — typed errors, retries, schema validation. Effect is a full ecosystem built around its own runtime, and that investment pays off once you need that level of control.

Zap Studio stays in plain TypeScript — no new runtime, no new mental model, small packages you adopt one at a time. Reach for it when you don't need everything Effect brings.

## Not For You If

* You want one framework that owns your whole effect/error model — Effect is built for that.
* You need every package to come from a single all-in-one SDK.
* What you have today isn't costing you bugs.

## Next Steps

Pick a package and follow its Getting Started guide:

* [`@zap-studio/fetch`](/fetch/getting-started)
* [`@zap-studio/logger`](/logger/getting-started)
* [`@zap-studio/monads`](/monads/getting-started)
* [`@zap-studio/oxfmt`](/oxfmt/getting-started)
* [`@zap-studio/oxlint`](/oxlint/getting-started)
* [`@zap-studio/permit`](/permit/getting-started)
* [`@zap-studio/react-hooks`](/react-hooks/getting-started)
* [`@zap-studio/retry`](/retry/getting-started)
* [`@zap-studio/validation`](/validation/getting-started)
* [`@zap-studio/webhooks`](/webhooks/getting-started)
