Get started
Define one procedure, implement it with request context, and call it from a typed client.
This example follows one procedure through a contract, a server implementation, and a client. Put the shared contract in a module that both application sides can import.
Define the contract
import { c } from "@cablejs/contract";
import { z } from "zod";
export const api = c.contract({
greeting: c.query({
input: z.object({ name: z.string().min(1) }),
output: z.object({ message: z.string() }),
}),
});
Implement it on the server
context is your application boundary. The example below supplies an authenticated name; an adapter can derive it from a session, bearer token, or another request credential.
import { createRpcHandler, implement } from "@cablejs/core";
import { api } from "./api.js";
const procedures = implement(api)
.context<{ readonly name: string }>()
.procedures({
greeting: ({ ctx, input }) => ({ message: `Hello, ${input.name} from ${ctx.name}` }),
});
const rpc = createRpcHandler(procedures, {
context: () => ({ name: "cable" }),
});
export default { fetch: rpc.fetch };
Call it from the client
import { createClient } from "@cablejs/client";
import { api } from "./api.js";
const client = createClient({ contract: api, url: "/_cable" });
const greeting = await client.greeting.query({ name: "Mina" });
console.log(greeting.message);
The client infers the procedure input and output from api. Next, learn how to define contracts, authorize procedures, or run the chat example.