# What is Courier?

A type-safe, framework-agnostic HTTP client with middleware, runtime validation, and adapters for Next.js, Nuxt, Hono, Express, Fastify, and NestJS.

**@noverax/courier** is a type-safe HTTP client that works with any JavaScript framework and any REST backend. Define your API once as plain TypeScript functions — get autocomplete, type inference, runtime validation, and middleware out of the box.

Types inferred, never generated. No schema files. No changes to your backend.

## How It Works

Define your API using `courier`, `defineGroup`, and `defineApi`. Each endpoint declares its response and variables types:

```ts title="api/sources.ts"
import { courier, defineApi, defineGroup } from "@noverax/courier/define"

const { endpoint } = courier()

type User = { id: string; name: string; email: string }

const users = defineGroup({
  prefix: "users",
  endpoints: {
    getAll: endpoint.get("").response<User[]>(),
    getById: endpoint.get(":id").variables<{ id: string }>().response<User>(),
    create: endpoint.post("").variables<{ name: string; email: string }>().response<User>(),
  },
})

const api = defineApi({
  baseURL: "https://api.example.com",
  groups: { users },
})

export { api }
```

Create a caller and use it with full type inference:

```ts title="lib/caller.ts"
import { createCaller } from "@noverax/courier"
import { api } from "@/api/sources"

const caller = createCaller(api)

const users = await caller.users.getAll()
//    ^? User[]

const user = await caller.users.getById({ id: "1" })
//    ^? User
```

## Two Transport Modes

Both modes share the same API definition and the same type inference:

- **Direct** — `createCaller(api)` — call backends directly from any runtime (Node.js, Bun, Deno, Cloudflare Workers, server components).
- **Proxy** — `createProxyCaller(apiRoutes)` — browser sends requests through your server, which serves the endpoints you mark `.expose()`, hides API keys, bypasses CORS, and carries the session cookies you name.

> **Same definitions, two modes**
>
> You define your API once. Both `createCaller` (direct) and `createProxyCaller` (proxy) consume the same sources with identical type inference.

## Framework Agnostic

The core runs on any JavaScript runtime with `fetch`. Official adapters handle the server-side proxy for your framework:

| Framework | Server Package | Handler |
|-----------|---------------|---------|
| **Next.js** | `@noverax/courier-next` | `apiRoute()` |
| **Nuxt** | `@noverax/courier-nuxt` | `courierHandler()` |
| **Hono** | `@noverax/courier-hono` | `courierHandler()` |
| **Express** | `@noverax/courier-express` | `courierHandler()` |
| **Fastify** | `@noverax/courier-fastify` | `courierPlugin` |
| **NestJS** | `@noverax/courier-nestjs` | `courierMiddleware()` |

All adapter handlers are zero-arg — they read sources from the core global registry populated by `registerSources()` (manual) or `attachRuntime()` (auto-loads `courier.config.ts`).

On the client side, use `createProxyCaller` (vanilla) or `createProxyQueryCaller` (React Query hooks).

## Core Philosophy

- **Types inferred, never generated** — your TypeScript definitions are the source of truth: rename a method and every call to it fails to compile, with no step to run first. Proxy mode keeps one file written for you, `courier.routes.ts` — the list of what a page may call, which a review reads and CI checks.
- **Zero boilerplate** — define a method signature and Courier handles serialization, path parameters, headers, and error wrapping.
- **Any backend** — works with Express, FastAPI, Rails, Go, Laravel, Django — anything that speaks HTTP.
- **Composable middleware** — retry, auth, logging, rate-limiting, caching — or write your own.
- **Standard Schema validation** — plug in Zod, Valibot, ArkType, or any Standard Schema library.

## Comparison

| Feature | fetch | axios | tRPC | Courier |
| --- | --- | --- | --- | --- |
| Type Safety | Manual | Manual | Full | Full |
| Framework Agnostic | Yes | Yes | Yes | Yes |
| React Query | Manual | Manual | Built-in | Built-in |
| Server Components | Manual | Manual | Supported | First-class |
| Middleware Chain | No | Interceptors | Built-in | Composable |
| Runtime Validation | No | No | Any validator | Any Standard Schema |
| Upload Progress | No | Yes | No | Built-in |
| Backend Requirement | Any | Any | tRPC server | Any REST |

## Next Steps

1. [Installation](/docs/installation) — add Courier to your project
2. [Quick Start](/docs/quick-start) — make your first type-safe API call
3. [Framework Guides](/docs/frameworks/nextjs) — setup for your specific framework
