# Installation

Add @noverax/courier to your project — works with any JavaScript framework.

> **In one command**
>
> `npx @noverax/create-courier` installs what your framework needs and sets it up: the route, the config, Studio and a mock. See [Create Courier](/docs/create-courier). This page installs each package by hand.

## Install the core package

**npm**

```bash
npm install @noverax/courier
```

**pnpm**

```bash
pnpm add @noverax/courier
```

**yarn**

```bash
yarn add @noverax/courier
```

**bun**

```bash
bun add @noverax/courier
```

The core package has zero runtime dependencies and works in any JavaScript runtime with `fetch`.

## Framework adapters

Install the adapter for your server framework. Each adapter is a thin wrapper around `createHandler` — see the [Server Handler](/docs/proxy-mode/api-route) docs for details.

| Framework | Package | Export |
|-----------|---------|--------|
| **Next.js** | `@noverax/courier-next` | `apiRoute`, `sseRoute`, `createAction` |
| **Nuxt / Nitro / h3** | `@noverax/courier-nuxt` | `courierHandler` |
| **SvelteKit** | `@noverax/courier-sveltekit` | `courierHandler` |
| **Astro** | `@noverax/courier-astro` | `courierHandler` |
| **Remix / React Router** | `@noverax/courier-remix` | `courierHandler` |
| **SolidStart** | `@noverax/courier-solid` | `courierHandler` |
| **Express** | `@noverax/courier-express` | `courierHandler` |
| **Hono** | `@noverax/courier-hono` | `courierHandler` |
| **Fastify** | `@noverax/courier-fastify` | `courierPlugin` |
| **NestJS** | `@noverax/courier-nestjs` | `courierMiddleware` |

**Next.js**

```bash
npm install @noverax/courier-next
```

**Nuxt**

```bash
npm install @noverax/courier-nuxt
```

**SvelteKit**

```bash
npm install @noverax/courier-sveltekit
```

**Astro**

```bash
npm install @noverax/courier-astro
```

**Remix**

```bash
npm install @noverax/courier-remix
```

**SolidStart**

```bash
npm install @noverax/courier-solid
```

**Express**

```bash
npm install @noverax/courier-express
```

**Hono**

```bash
npm install @noverax/courier-hono
```

**Fastify**

```bash
npm install @noverax/courier-fastify
```

**NestJS**

```bash
npm install @noverax/courier-nestjs
```

## React Query integration

For React apps, add the query package for type-safe hooks (`useQuery`, `useMutation`, `useSuspenseQuery`, `useInfiniteQuery`):

```bash
npm install @noverax/courier-react @tanstack/react-query
```

## Studio

Studio inspects requests in development. Its runtime registers your sources
from `courier.config.ts`, and every framework's instrumentation snippet imports
it directly — so it is a dependency of your app, not only of the dev server:

```bash
npm install @noverax/courier-studio-core
npm install --save-dev @noverax/courier-studio
```

A production install leaves dev dependencies out, so a server that imports the
runtime would not start if it were one — even a server that calls it only in
development. Studio itself is a development tool and stays a dev dependency.

`@noverax/courier-studio-core/runtime` brings its own socket client and loads
it only outside production, so the connection to the Studio dev server costs a
production build nothing.

Studio and its runtime read `courier.config.ts` at the project root. A project
that has no API sources yet starts with this one; Studio's APIs page offers it
to copy when the project has none, and keeps **Import API** off until it loads:

```ts title="courier.config.ts"
import { defineConfig } from "@noverax/courier/config";
export default defineConfig({ sources: {} });
```

Start Studio with `npx @noverax/courier-studio`, and **Import API** on its APIs page
writes the project's first API — under `src/api/<source name>/` by default,
where `source.ts` exports the source; `npx @noverax/courier-studio import <spec>`
does the same [from the command line](/docs/studio/import-api#from-the-command-line).
Add it to `sources` under its source name, and Studio lists it:

```ts title="courier.config.ts"
import { defineConfig } from "@noverax/courier/config";
import { petstore } from "./src/api/petstore/source";

export default defineConfig({ sources: { petstore } });
```

In a `"type": "module"` package whose tsconfig resolves modules as Node does
(`node16` or `nodenext`), the generated files name each relative import with
its `.js` extension, as TypeScript requires there, and Studio asks the config
to import `./src/api/petstore/source.js`.

### Mock servers

Studio can also run mock servers of your sources. Add the mock package and the
server it runs on, for development only — leave out any your app already lists
under `dependencies`:

```bash
npm install --save-dev @noverax/courier-mock hono @hono/node-server
```

Declare the mocks in `courier.mocks.ts`, beside `courier.config.ts`, or let
Studio's mock wizard write the file for you:

```ts title="courier.mocks.ts"
import { defineMocks, defineMockServer } from "@noverax/courier-mock"
import courierConfig from "./courier.config"

export default defineMocks({
  apiMock: defineMockServer({ source: courierConfig.sources.api, autoStart: true }),
})
```

In a `"type": "module"` package whose tsconfig resolves modules as Node does
(`node16` or `nodenext`), import `./courier.config.js` instead: TypeScript asks
for the extension there, and both TypeScript and Studio map it to
`courier.config.ts`. The wizard writes it that way in such a project.

Reading the source from the config this way, as Studio's wizard writes it,
needs a config whose default export is `defineConfig({ sources })`. With a
config that exports `sources` by name only, import the source from where the
config does instead: a default import of that config does not type-check.

Only Studio reads `courier.mocks.ts`. Your app loads `courier.config.ts` in
production too, where development packages are not installed, so mocks are
never declared there: `courier.config.ts` has no `mocks` key.

> **Install only what you use**
>
> All framework packages and integrations are optional. The core `@noverax/courier` package works standalone for direct API calls from any runtime.

## Routes CLI

A page that calls your API through your server's proxy takes its routes from
`courier.routes.ts`, which Courier writes from the endpoints you mark
`.expose()` — Studio as it runs, and `courier-cli routes` without it. Add the
CLI for development, so your CI checks the module with the version your
lockfile pins:

```bash
npm install --save-dev @noverax/courier-cli
```

`npx @noverax/courier-cli routes` writes the module; with `--check`, it writes
nothing and fails when the module is out of date. See
[Exposing Endpoints](/docs/proxy-mode/expose).

## Requirements

- **Node.js 22** or later for every package; Studio needs 22.13, for the SQLite built into Node.
- **Safari 15.4, Chrome 97 or Firefox 104** or later for the core in a browser — every version released since August 2022. It needs nothing those lack, and no `crypto.subtle`, which a page served over plain HTTP does not get. The published code is ES2022; a bundler that targets older browsers lowers it.
- **A bundler that reads a package's `exports` and `imports` fields**, as Vite, webpack 5, Rollup, esbuild, Turbopack and Metro do. Through `imports` a page takes a stand-in of each module only a server runs — its terminal logger, the addresses a request came through, the check of `forward` — and Node, an edge runtime and React Native take the modules themselves.
- **ES modules.** The packages are published as ES modules only. A CommonJS project loads them with `require()` on Node.js 22.12 or later, which loads an ES module synchronously; with TypeScript, set `"module": "nodenext"`, under which it allows that `require`.
- **TypeScript 6.0** or later, with `strict` on. The published declarations compile with `skipLibCheck` off in a project typed for Node.js alone, without the DOM library; in one resolving modules as a bundler does; in a browser project; and in a CommonJS one. They compile with `exactOptionalPropertyTypes` on too, and there an option you may leave out also takes `undefined`, so a setting that may be missing is passed as it is.

## TypeScript configuration

Courier ships type declarations. Enable strict mode for the best type inference:

```json title="tsconfig.json"
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true
  }
}
```

A project Node.js runs without a bundler resolves modules as Node does instead: `"module": "nodenext"`, which also sets `moduleResolution`.

### An existing project

A project whose tsconfig still says `"moduleResolution": "node"` — `node10`, which reads no `exports` map — finds every entry Courier publishes too, `@noverax/courier/define` and the rest, through each package's `typesVersions`; it needs no change to start. TypeScript 6 deprecates that resolution, though, and with it `baseUrl`, `downlevelIteration`, an ES5 `target` and a few more; it refuses them unless `"ignoreDeprecations": "6.0"` says to wait, and TypeScript 7 drops them. Moving to it, a project that a bundler builds — Next.js, Vite, Nuxt — sets `"moduleResolution": "bundler"`, and one Node.js runs `"module": "node16"`; `paths` are written relative to the tsconfig once `baseUrl` goes. TypeScript 6 also checks side-effect imports, so `import "swiper/css"` needs a declaration — `declare module "swiper/css";` — or `"noUncheckedSideEffectImports": false`. [`create-courier`](/docs/create-courier) lists what your tsconfig sets of these in its plan.

## Environment variables

Add your backend API URL as a server-side environment variable:

```bash title=".env.local"
# Your backend API URL (server-side only)
API_URL=http://localhost:4000
```

This is used in your `defineApi` call. In proxy mode, the browser never sees this URL — requests go through your server's proxy route.

## Next steps

- [Quick Start](/docs/quick-start) — define your first API and make a request
- [Framework Guides](/docs/frameworks/nextjs) — complete setup for your framework
