Skip to content

Getting StartedInstallation

Installation

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

4 min read

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. This page installs each package by hand.

Install the core package

npm install @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 for details.

FrameworkPackageExport
Next.js@noverax/courier-nextapiRoute, sseRoute, createAction
Nuxt / Nitro / h3@noverax/courier-nuxtcourierHandler
SvelteKit@noverax/courier-sveltekitcourierHandler
Astro@noverax/courier-astrocourierHandler
Remix / React Router@noverax/courier-remixcourierHandler
SolidStart@noverax/courier-solidcourierHandler
Express@noverax/courier-expresscourierHandler
Hono@noverax/courier-honocourierHandler
Fastify@noverax/courier-fastifycourierPlugin
NestJS@noverax/courier-nestjscourierMiddleware
npm install @noverax/courier-next

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:

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. Add it to sources under its source name, and Studio lists it:

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:

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.

Requirements

  • Node.js 22 or later for every package; Studio needs 22.13, for the SQLite built into Node. In the browser, the core needs only fetch.
  • 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:

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.

Environment variables

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

.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