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.
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:
npm install --save-dev @noverax/courier-clinpx @noverax/courier-cli routes writes the module; with --check, it writes
nothing and fails when the module is out of date. See
Exposing Endpoints.
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
exportsandimportsfields, as Vite, webpack 5, Rollup, esbuild, Turbopack and Metro do. Throughimportsa page takes a stand-in of each module only a server runs — its terminal logger, the addresses a request came through, the check offorward— 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 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.
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 lists what your tsconfig sets of these in its plan.
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