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/courierThe 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.
| 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 |
npm install @noverax/courier-nextReact Query integration
For React apps, add the query package for type-safe hooks (useQuery, useMutation, useSuspenseQuery, useInfiniteQuery):
npm install @noverax/courier-react @tanstack/react-queryStudio
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:
npm install @noverax/courier-studio-core
npm install --save-dev @noverax/courier-studioA 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:
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:
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:
npm install --save-dev @noverax/courier-mock hono @hono/node-serverDeclare the mocks in courier.mocks.ts, beside courier.config.ts, or let
Studio's mock wizard write the file for you:
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 thatrequire. - TypeScript 6.0 or later, with
stricton. The published declarations compile withskipLibCheckoff 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 withexactOptionalPropertyTypeson too, and there an option you may leave out also takesundefined, 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:
{
"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:
# Your backend API URL (server-side only)
API_URL=http://localhost:4000This 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 — define your first API and make a request
- Framework Guides — complete setup for your framework