Start here

Installation

Install the core package and the integration for your server.

On this page

Install @hulla/api to define a contract and create a client or server. Add an adapter package if you’re serving the API through a framework or platform listed below.

  1. 1Install the validated coreStart with @hulla/api and a runtime schema library.

    Run this in the workspace package that owns the shared contract. The examples use Zod, so installing it now gives you the recommended runtime-validated path through the quick start.

    Optional agent skill

    Working with a coding agent?

    Install api from the hulladev/skills repository for guidance on shared contracts, server/client boundaries, and adapters. Run this in your application directory:

    Choose your agent in the installer and check compatibility with your package version.

    Tip: bring your preferred validator

    @hulla/api accepts any Standard Schema-compatible library. Replace Zod with Valibot, ArkType, Effect Schema, or another compatible implementation; the API contract does not change.

    Type-only declarations are also available for already-trusted values. They preserve compile-time types but do not validate real input or output. See contract declarations when that tradeoff is intentional.

  2. 2Connect the server boundaryMount the implementation into the host that receives requests.

    A server adapter translates the host’s native request into a contract call, provides request context, and turns the declared result back into the host’s response. Only server code imports this adapter.

    Install one server adapter in the application that owns the listener or framework route. The shared contract package should not depend on Express, Next.js, Node.js, or another host.

  3. 3Connect the client boundaryChoose how typed calls travel from the caller to the server.

    A client transport carries a contract-shaped call. It does not mount routes or own server middleware. Most applications begin with one of the two transports already included in @hulla/api.

    The client imports the contract and its chosen transport. It imports the implementation only for an in-process call—never for Fetch, MessagePort, or WebSocket.

    Once direct calls work, optionally add @hulla/api-control, @hulla/api-tanstack-query, or @hulla/api-swr. These wrap an existing client; they do not replace its transport.

  4. 4Verify one vertical sliceProve the contract, implementation, and client before adding framework setup.

    Build the first route in process so a listener, proxy, or framework cannot hide contract mistakes. The quick start gives you three small modules:

    1. contract.ts declares and validates what crosses the boundary.
    2. implementation.ts contains server-only behavior.
    3. example.ts creates a typed client, calls the route, and prints the created task.

    When that call works, the core setup is complete. Keep the in-process transport when the caller stays beside the server. For a browser or remote caller, move on to the client transport from step 3 and mount the same implementation with the server adapter from step 2.

    Build the task API quick start →